From 2d973e45b8a8d33f45ccb4940f599cadcfa5a19d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 18 Aug 2005 20:07:59 +0000 Subject: [PATCH] Implement the first chunk of a code emitter. This is sophisticated enough to codegen: _empty: .LBB_empty_0: ; blr but can't do anything more (yet). :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22876 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/ScheduleDAG.cpp | 95 +++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index 28edbe30b5d..c4dba414416 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -14,10 +14,103 @@ #define DEBUG_TYPE "sched" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" using namespace llvm; +namespace { + class SimpleSched { + SelectionDAG &DAG; + MachineBasicBlock *BB; + const TargetMachine &TM; + const TargetInstrInfo &TII; + + std::map EmittedOps; + public: + SimpleSched(SelectionDAG &D, MachineBasicBlock *bb) + : DAG(D), BB(bb), TM(D.getTarget()), TII(*TM.getInstrInfo()) { + assert(&TII && "Target doesn't provide instr info?"); + } + + void Run() { + Emit(DAG.getRoot()); + } + + private: + unsigned Emit(SDOperand Op); + }; +} + +unsigned SimpleSched::Emit(SDOperand Op) { + // Check to see if we have already emitted this. If so, return the value + // already emitted. Note that if a node has a single use it cannot be + // revisited, so don't bother putting it in the map. + unsigned *OpSlot; + if (Op.Val->hasOneUse()) { + OpSlot = 0; // No reuse possible. + } else { + std::map::iterator OpI = EmittedOps.lower_bound(Op.Val); + if (OpI != EmittedOps.end() && OpI->first == Op.Val) + return OpI->second + Op.ResNo; + OpSlot = &EmittedOps.insert(OpI, std::make_pair(Op.Val, 0))->second; + } + + unsigned ResultReg = 0; + if (Op.isTargetOpcode()) { + unsigned Opc = Op.getTargetOpcode(); + const TargetInstrDescriptor &II = TII.get(Opc); + + // Target nodes have any register or immediate operands before any chain + // nodes. Check that the DAG matches the TD files's expectation of # + // operands. + assert((unsigned(II.numOperands) == Op.getNumOperands() || + // It could be some number of operands followed by a token chain. + (unsigned(II.numOperands)+1 == Op.getNumOperands() && + Op.getOperand(II.numOperands).getValueType() == MVT::Other)) && + "#operands for dag node doesn't match .td file!"); + + // Create the new machine instruction. + MachineInstr *MI = new MachineInstr(Opc, II.numOperands, true, true); + + // Add result register values for things that are defined by this + // instruction. + assert(Op.Val->getNumValues() == 1 && + Op.getValue(0).getValueType() == MVT::Other && + "Return values not implemented yet"); + + // Emit all of the operands of this instruction, adding them to the + // instruction as appropriate. + for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) { + if (ConstantSDNode *C = dyn_cast(Op.getOperand(i))) { + MI->addZeroExtImm64Operand(C->getValue()); + } else if (RegisterSDNode*R =dyn_cast(Op.getOperand(i))) { + MI->addRegOperand(R->getReg(), MachineOperand::Use); + } else { + unsigned R = Emit(Op.getOperand(i)); + // Add an operand, unless this corresponds to a chain node. + if (Op.getOperand(i).getValueType() != MVT::Other) + MI->addRegOperand(R, MachineOperand::Use); + } + } + + // Now that we have emitted all operands, emit this instruction itself. + BB->insert(BB->end(), MI); + } else { + switch (Op.getOpcode()) { + default: assert(0 && + "This target-independent node should have been selected!"); + case ISD::EntryToken: break; + } + } + + if (OpSlot) *OpSlot = ResultReg; + return ResultReg+Op.ResNo; +} + + /// Pick a safe ordering and emit instructions for each target node in the /// graph. void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &SD) { - + SimpleSched(SD, BB).Run(); }