aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-08-18 20:07:59 +0000
committerChris Lattner <sabre@nondot.org>2005-08-18 20:07:59 +0000
commit2d973e45b8a8d33f45ccb4940f599cadcfa5a19d (patch)
treef3f36379eceb55e8510174d8d07b98204dde7144 /lib/CodeGen
parente5df8ea4a6ca275fc13267ef88a2dbf1b8eed7d1 (diff)
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAG.cpp95
1 files changed, 94 insertions, 1 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
index 28edbe30b5..c4dba41441 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<SDNode *, unsigned> 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<SDNode *, unsigned>::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<ConstantSDNode>(Op.getOperand(i))) {
+ MI->addZeroExtImm64Operand(C->getValue());
+ } else if (RegisterSDNode*R =dyn_cast<RegisterSDNode>(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();
}