Chris Lattner | d32b236 | 2005-08-18 18:45:24 +0000 | [diff] [blame] | 1 | //===-- ScheduleDAG.cpp - Implement a trivial DAG scheduler ---------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Chris Lattner and is distributed under the |
| 6 | // University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This implements a simple code linearizer for DAGs. This is not a very good |
| 11 | // way to emit code, but gets working code quickly. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #define DEBUG_TYPE "sched" |
Chris Lattner | 5839bf2 | 2005-08-26 17:15:30 +0000 | [diff] [blame^] | 16 | #include "llvm/CodeGen/MachineConstantPool.h" |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 17 | #include "llvm/CodeGen/MachineFunction.h" |
Chris Lattner | d32b236 | 2005-08-18 18:45:24 +0000 | [diff] [blame] | 18 | #include "llvm/CodeGen/SelectionDAGISel.h" |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 19 | #include "llvm/CodeGen/SelectionDAG.h" |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/SSARegMap.h" |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 21 | #include "llvm/Target/TargetMachine.h" |
| 22 | #include "llvm/Target/TargetInstrInfo.h" |
Chris Lattner | 068ca15 | 2005-08-18 20:11:49 +0000 | [diff] [blame] | 23 | #include "llvm/Support/CommandLine.h" |
Chris Lattner | d32b236 | 2005-08-18 18:45:24 +0000 | [diff] [blame] | 24 | using namespace llvm; |
| 25 | |
Chris Lattner | 068ca15 | 2005-08-18 20:11:49 +0000 | [diff] [blame] | 26 | #ifndef _NDEBUG |
| 27 | static cl::opt<bool> |
| 28 | ViewDAGs("view-sched-dags", cl::Hidden, |
| 29 | cl::desc("Pop up a window to show sched dags as they are processed")); |
| 30 | #else |
| 31 | static const bool ViewDAGS = 0; |
| 32 | #endif |
| 33 | |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 34 | namespace { |
| 35 | class SimpleSched { |
| 36 | SelectionDAG &DAG; |
| 37 | MachineBasicBlock *BB; |
| 38 | const TargetMachine &TM; |
| 39 | const TargetInstrInfo &TII; |
Chris Lattner | 0189197 | 2005-08-19 20:50:53 +0000 | [diff] [blame] | 40 | const MRegisterInfo &MRI; |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 41 | SSARegMap *RegMap; |
Chris Lattner | 5839bf2 | 2005-08-26 17:15:30 +0000 | [diff] [blame^] | 42 | MachineConstantPool *ConstPool; |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 43 | |
| 44 | std::map<SDNode *, unsigned> EmittedOps; |
| 45 | public: |
| 46 | SimpleSched(SelectionDAG &D, MachineBasicBlock *bb) |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 47 | : DAG(D), BB(bb), TM(D.getTarget()), TII(*TM.getInstrInfo()), |
Chris Lattner | 5839bf2 | 2005-08-26 17:15:30 +0000 | [diff] [blame^] | 48 | MRI(*TM.getRegisterInfo()), RegMap(BB->getParent()->getSSARegMap()), |
| 49 | ConstPool(BB->getParent()->getConstantPool()) { |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 50 | assert(&TII && "Target doesn't provide instr info?"); |
Chris Lattner | 0189197 | 2005-08-19 20:50:53 +0000 | [diff] [blame] | 51 | assert(&MRI && "Target doesn't provide register info?"); |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | void Run() { |
| 55 | Emit(DAG.getRoot()); |
| 56 | } |
| 57 | |
| 58 | private: |
| 59 | unsigned Emit(SDOperand Op); |
| 60 | }; |
| 61 | } |
| 62 | |
| 63 | unsigned SimpleSched::Emit(SDOperand Op) { |
| 64 | // Check to see if we have already emitted this. If so, return the value |
| 65 | // already emitted. Note that if a node has a single use it cannot be |
| 66 | // revisited, so don't bother putting it in the map. |
| 67 | unsigned *OpSlot; |
| 68 | if (Op.Val->hasOneUse()) { |
| 69 | OpSlot = 0; // No reuse possible. |
| 70 | } else { |
| 71 | std::map<SDNode *, unsigned>::iterator OpI = EmittedOps.lower_bound(Op.Val); |
| 72 | if (OpI != EmittedOps.end() && OpI->first == Op.Val) |
| 73 | return OpI->second + Op.ResNo; |
| 74 | OpSlot = &EmittedOps.insert(OpI, std::make_pair(Op.Val, 0))->second; |
| 75 | } |
| 76 | |
| 77 | unsigned ResultReg = 0; |
| 78 | if (Op.isTargetOpcode()) { |
| 79 | unsigned Opc = Op.getTargetOpcode(); |
| 80 | const TargetInstrDescriptor &II = TII.get(Opc); |
| 81 | |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 82 | // The results of target nodes have register or immediate operands first, |
| 83 | // then an optional chain, and optional flag operands (which do not go into |
| 84 | // the machine instrs). |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 85 | unsigned NumResults = Op.Val->getNumValues(); |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 86 | while (NumResults && Op.Val->getValueType(NumResults-1) == MVT::Flag) |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 87 | --NumResults; |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 88 | if (NumResults && Op.Val->getValueType(NumResults-1) == MVT::Other) |
| 89 | --NumResults; // Skip over chain result. |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 90 | |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 91 | // The inputs to target nodes have any actual inputs first, followed by an |
| 92 | // optional chain operand, then flag operands. Compute the number of actual |
| 93 | // operands that will go into the machine instr. |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 94 | unsigned NodeOperands = Op.getNumOperands(); |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 95 | while (NodeOperands && |
| 96 | Op.getOperand(NodeOperands-1).getValueType() == MVT::Flag) |
| 97 | --NodeOperands; |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 98 | if (NodeOperands && // Ignore chain if it exists. |
| 99 | Op.getOperand(NodeOperands-1).getValueType() == MVT::Other) |
| 100 | --NodeOperands; |
| 101 | |
| 102 | unsigned NumMIOperands = NodeOperands+NumResults; |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 103 | #ifndef _NDEBUG |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 104 | assert((unsigned(II.numOperands) == NumMIOperands || II.numOperands == -1)&& |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 105 | "#operands for dag node doesn't match .td file!"); |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 106 | #endif |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 107 | |
| 108 | // Create the new machine instruction. |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 109 | MachineInstr *MI = new MachineInstr(Opc, NumMIOperands, true, true); |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 110 | |
| 111 | // Add result register values for things that are defined by this |
| 112 | // instruction. |
Chris Lattner | 4ccd406 | 2005-08-19 20:45:43 +0000 | [diff] [blame] | 113 | if (NumResults) { |
| 114 | // Create the result registers for this node and add the result regs to |
| 115 | // the machine instruction. |
| 116 | const TargetOperandInfo *OpInfo = II.OpInfo; |
| 117 | ResultReg = RegMap->createVirtualRegister(OpInfo[0].RegClass); |
| 118 | MI->addRegOperand(ResultReg, MachineOperand::Def); |
| 119 | for (unsigned i = 1; i != NumResults; ++i) { |
| 120 | assert(OpInfo[i].RegClass && "Isn't a register operand!"); |
| 121 | MI->addRegOperand(RegMap->createVirtualRegister(OpInfo[0].RegClass), |
| 122 | MachineOperand::Def); |
| 123 | } |
| 124 | } |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 125 | |
| 126 | // Emit all of the operands of this instruction, adding them to the |
| 127 | // instruction as appropriate. |
| 128 | for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) { |
Chris Lattner | 23553cf | 2005-08-22 01:04:32 +0000 | [diff] [blame] | 129 | if (Op.getOperand(i).isTargetOpcode()) { |
| 130 | // Note that this case is redundant with the final else block, but we |
| 131 | // include it because it is the most common and it makes the logic |
| 132 | // simpler here. |
| 133 | unsigned R = Emit(Op.getOperand(i)); |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 134 | // Add an operand, unless this corresponds to a chain or flag node. |
| 135 | MVT::ValueType VT = Op.getOperand(i).getValueType(); |
| 136 | if (VT != MVT::Other && VT != MVT::Flag) |
Chris Lattner | 23553cf | 2005-08-22 01:04:32 +0000 | [diff] [blame] | 137 | MI->addRegOperand(R, MachineOperand::Use); |
| 138 | } else if (ConstantSDNode *C = |
| 139 | dyn_cast<ConstantSDNode>(Op.getOperand(i))) { |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 140 | MI->addZeroExtImm64Operand(C->getValue()); |
| 141 | } else if (RegisterSDNode*R =dyn_cast<RegisterSDNode>(Op.getOperand(i))) { |
| 142 | MI->addRegOperand(R->getReg(), MachineOperand::Use); |
Chris Lattner | 9b78db7 | 2005-08-19 22:38:24 +0000 | [diff] [blame] | 143 | } else if (GlobalAddressSDNode *TGA = |
| 144 | dyn_cast<GlobalAddressSDNode>(Op.getOperand(i))) { |
| 145 | MI->addGlobalAddressOperand(TGA->getGlobal(), false, 0); |
Chris Lattner | f85ab15 | 2005-08-21 18:49:29 +0000 | [diff] [blame] | 146 | } else if (BasicBlockSDNode *BB = |
| 147 | dyn_cast<BasicBlockSDNode>(Op.getOperand(i))) { |
| 148 | MI->addMachineBasicBlockOperand(BB->getBasicBlock()); |
Chris Lattner | 81e72b1 | 2005-08-21 19:56:04 +0000 | [diff] [blame] | 149 | } else if (FrameIndexSDNode *FI = |
| 150 | dyn_cast<FrameIndexSDNode>(Op.getOperand(i))) { |
| 151 | MI->addFrameIndexOperand(FI->getIndex()); |
Chris Lattner | 23553cf | 2005-08-22 01:04:32 +0000 | [diff] [blame] | 152 | } else if (ConstantPoolSDNode *CP = |
| 153 | dyn_cast<ConstantPoolSDNode>(Op.getOperand(i))) { |
Chris Lattner | 5839bf2 | 2005-08-26 17:15:30 +0000 | [diff] [blame^] | 154 | unsigned Idx = ConstPool->getConstantPoolIndex(CP->get()); |
| 155 | MI->addConstantPoolIndexOperand(Idx); |
Chris Lattner | 14b392a | 2005-08-24 22:02:41 +0000 | [diff] [blame] | 156 | } else if (ExternalSymbolSDNode *ES = |
| 157 | dyn_cast<ExternalSymbolSDNode>(Op.getOperand(i))) { |
| 158 | MI->addExternalSymbolOperand(ES->getSymbol(), false); |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 159 | } else { |
| 160 | unsigned R = Emit(Op.getOperand(i)); |
Chris Lattner | 376d54f | 2005-08-25 17:48:54 +0000 | [diff] [blame] | 161 | // Add an operand, unless this corresponds to a chain or flag node. |
| 162 | MVT::ValueType VT = Op.getOperand(i).getValueType(); |
| 163 | if (VT != MVT::Other && VT != MVT::Flag) |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 164 | MI->addRegOperand(R, MachineOperand::Use); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | // Now that we have emitted all operands, emit this instruction itself. |
| 169 | BB->insert(BB->end(), MI); |
| 170 | } else { |
| 171 | switch (Op.getOpcode()) { |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 172 | default: |
| 173 | Op.Val->dump(); |
| 174 | assert(0 && "This target-independent node should have been selected!"); |
Chris Lattner | 81e72b1 | 2005-08-21 19:56:04 +0000 | [diff] [blame] | 175 | case ISD::EntryToken: break; |
Chris Lattner | 7ef3304 | 2005-08-19 21:43:53 +0000 | [diff] [blame] | 176 | case ISD::TokenFactor: |
| 177 | for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) |
| 178 | Emit(Op.getOperand(i)); |
| 179 | break; |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 180 | case ISD::CopyToReg: { |
Chris Lattner | 7ef3304 | 2005-08-19 21:43:53 +0000 | [diff] [blame] | 181 | Emit(Op.getOperand(0)); // Emit the chain. |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 182 | unsigned Val = Emit(Op.getOperand(2)); |
Chris Lattner | 0189197 | 2005-08-19 20:50:53 +0000 | [diff] [blame] | 183 | MRI.copyRegToReg(*BB, BB->end(), |
| 184 | cast<RegisterSDNode>(Op.getOperand(1))->getReg(), Val, |
| 185 | RegMap->getRegClass(Val)); |
Chris Lattner | ca6aa2f | 2005-08-19 01:01:34 +0000 | [diff] [blame] | 186 | break; |
| 187 | } |
Chris Lattner | 7ef3304 | 2005-08-19 21:43:53 +0000 | [diff] [blame] | 188 | case ISD::CopyFromReg: { |
| 189 | Emit(Op.getOperand(0)); // Emit the chain. |
| 190 | unsigned SrcReg = cast<RegisterSDNode>(Op.getOperand(1))->getReg(); |
| 191 | |
| 192 | // Figure out the register class to create for the destreg. |
Chris Lattner | fe0c2c8 | 2005-08-20 18:07:27 +0000 | [diff] [blame] | 193 | const TargetRegisterClass *TRC = 0; |
Chris Lattner | 7ef3304 | 2005-08-19 21:43:53 +0000 | [diff] [blame] | 194 | if (MRegisterInfo::isVirtualRegister(SrcReg)) { |
| 195 | TRC = RegMap->getRegClass(SrcReg); |
| 196 | } else { |
| 197 | // FIXME: we don't know what register class to generate this for. Do |
| 198 | // a brute force search and pick the first match. :( |
| 199 | for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), |
| 200 | E = MRI.regclass_end(); I != E; ++I) |
| 201 | if ((*I)->contains(SrcReg)) { |
| 202 | TRC = *I; |
| 203 | break; |
| 204 | } |
| 205 | assert(TRC && "Couldn't find register class for reg copy!"); |
| 206 | } |
| 207 | |
| 208 | // Create the reg, emit the copy. |
| 209 | ResultReg = RegMap->createVirtualRegister(TRC); |
| 210 | MRI.copyRegToReg(*BB, BB->end(), ResultReg, SrcReg, TRC); |
| 211 | break; |
| 212 | } |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 213 | } |
| 214 | } |
| 215 | |
| 216 | if (OpSlot) *OpSlot = ResultReg; |
| 217 | return ResultReg+Op.ResNo; |
| 218 | } |
| 219 | |
| 220 | |
Chris Lattner | d32b236 | 2005-08-18 18:45:24 +0000 | [diff] [blame] | 221 | /// Pick a safe ordering and emit instructions for each target node in the |
| 222 | /// graph. |
| 223 | void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &SD) { |
Chris Lattner | 068ca15 | 2005-08-18 20:11:49 +0000 | [diff] [blame] | 224 | if (ViewDAGs) SD.viewGraph(); |
Chris Lattner | 2d973e4 | 2005-08-18 20:07:59 +0000 | [diff] [blame] | 225 | SimpleSched(SD, BB).Run(); |
Chris Lattner | d32b236 | 2005-08-18 18:45:24 +0000 | [diff] [blame] | 226 | } |