| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 1 | //===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines an instruction selector for the MSP430 target. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "MSP430.h" | 
|  | 15 | #include "MSP430ISelLowering.h" | 
|  | 16 | #include "MSP430TargetMachine.h" | 
|  | 17 | #include "llvm/DerivedTypes.h" | 
|  | 18 | #include "llvm/Function.h" | 
|  | 19 | #include "llvm/Intrinsics.h" | 
|  | 20 | #include "llvm/CallingConv.h" | 
|  | 21 | #include "llvm/Constants.h" | 
|  | 22 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 23 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 24 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 25 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | 26 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 27 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 28 | #include "llvm/Target/TargetLowering.h" | 
| Anton Korobeynikov | 9e92857 | 2009-10-21 19:18:28 +0000 | [diff] [blame] | 29 | #include "llvm/Support/CommandLine.h" | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 30 | #include "llvm/Support/Compiler.h" | 
|  | 31 | #include "llvm/Support/Debug.h" | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 32 | #include "llvm/Support/ErrorHandling.h" | 
|  | 33 | #include "llvm/Support/raw_ostream.h" | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 34 | #include "llvm/ADT/Statistic.h" | 
|  | 35 |  | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 36 | using namespace llvm; | 
|  | 37 |  | 
| Anton Korobeynikov | 9e92857 | 2009-10-21 19:18:28 +0000 | [diff] [blame] | 38 | #ifndef NDEBUG | 
|  | 39 | static cl::opt<bool> | 
|  | 40 | ViewRMWDAGs("view-msp430-rmw-dags", cl::Hidden, | 
|  | 41 | cl::desc("Pop up a window to show isel dags after RMW preprocess")); | 
|  | 42 | #else | 
|  | 43 | static const bool ViewRMWDAGs = false; | 
|  | 44 | #endif | 
|  | 45 |  | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 46 | STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor"); | 
|  | 47 |  | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 48 | /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine | 
|  | 49 | /// instructions for SelectionDAG operations. | 
|  | 50 | /// | 
|  | 51 | namespace { | 
|  | 52 | class MSP430DAGToDAGISel : public SelectionDAGISel { | 
|  | 53 | MSP430TargetLowering &Lowering; | 
|  | 54 | const MSP430Subtarget &Subtarget; | 
|  | 55 |  | 
|  | 56 | public: | 
| Anton Korobeynikov | 1324f81 | 2009-05-03 13:19:42 +0000 | [diff] [blame] | 57 | MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel) | 
|  | 58 | : SelectionDAGISel(TM, OptLevel), | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 59 | Lowering(*TM.getTargetLowering()), | 
|  | 60 | Subtarget(*TM.getSubtargetImpl()) { } | 
|  | 61 |  | 
|  | 62 | virtual void InstructionSelect(); | 
|  | 63 |  | 
|  | 64 | virtual const char *getPassName() const { | 
|  | 65 | return "MSP430 DAG->DAG Pattern Instruction Selection"; | 
|  | 66 | } | 
|  | 67 |  | 
| Anton Korobeynikov | 6bce6bb | 2009-10-11 19:14:21 +0000 | [diff] [blame] | 68 | virtual bool | 
|  | 69 | SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, | 
|  | 70 | std::vector<SDValue> &OutOps); | 
|  | 71 |  | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 72 | // Include the pieces autogenerated from the target description. | 
|  | 73 | #include "MSP430GenDAGISel.inc" | 
|  | 74 |  | 
|  | 75 | private: | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 76 | void PreprocessForRMW(); | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 77 | SDNode *Select(SDValue Op); | 
| Anton Korobeynikov | ed65671 | 2009-05-03 13:09:40 +0000 | [diff] [blame] | 78 | bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 79 |  | 
|  | 80 | #ifndef NDEBUG | 
|  | 81 | unsigned Indent; | 
|  | 82 | #endif | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 83 | }; | 
|  | 84 | }  // end anonymous namespace | 
|  | 85 |  | 
|  | 86 | /// createMSP430ISelDag - This pass converts a legalized DAG into a | 
|  | 87 | /// MSP430-specific DAG, ready for instruction scheduling. | 
|  | 88 | /// | 
| Anton Korobeynikov | 1324f81 | 2009-05-03 13:19:42 +0000 | [diff] [blame] | 89 | FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM, | 
|  | 90 | CodeGenOpt::Level OptLevel) { | 
|  | 91 | return new MSP430DAGToDAGISel(TM, OptLevel); | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 92 | } | 
|  | 93 |  | 
| Anton Korobeynikov | 6399a3d | 2009-05-03 13:09:10 +0000 | [diff] [blame] | 94 | // FIXME: This is pretty dummy routine and needs to be rewritten in the future. | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 95 | bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr, | 
| Anton Korobeynikov | ed65671 | 2009-05-03 13:09:40 +0000 | [diff] [blame] | 96 | SDValue &Base, SDValue &Disp) { | 
| Anton Korobeynikov | 0d1234f | 2009-05-03 13:10:11 +0000 | [diff] [blame] | 97 | // Try to match frame address first. | 
|  | 98 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 99 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); | 
|  | 100 | Disp = CurDAG->getTargetConstant(0, MVT::i16); | 
| Anton Korobeynikov | 0d1234f | 2009-05-03 13:10:11 +0000 | [diff] [blame] | 101 | return true; | 
|  | 102 | } | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 103 |  | 
| Anton Korobeynikov | a3bce28 | 2009-05-03 13:08:51 +0000 | [diff] [blame] | 104 | switch (Addr.getOpcode()) { | 
|  | 105 | case ISD::ADD: | 
| Anton Korobeynikov | 7212c15 | 2009-05-03 13:11:35 +0000 | [diff] [blame] | 106 | // Operand is a result from ADD with constant operand which fits into i16. | 
|  | 107 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 108 | uint64_t CVal = CN->getZExtValue(); | 
|  | 109 | // Offset should fit into 16 bits. | 
|  | 110 | if (((CVal << 48) >> 48) == CVal) { | 
| Anton Korobeynikov | 0d1234f | 2009-05-03 13:10:11 +0000 | [diff] [blame] | 111 | SDValue N0 = Addr.getOperand(0); | 
|  | 112 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N0)) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 113 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); | 
| Anton Korobeynikov | 0d1234f | 2009-05-03 13:10:11 +0000 | [diff] [blame] | 114 | else | 
|  | 115 | Base = N0; | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 116 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 117 | Disp = CurDAG->getTargetConstant(CVal, MVT::i16); | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 118 | return true; | 
|  | 119 | } | 
|  | 120 | } | 
| Anton Korobeynikov | a3bce28 | 2009-05-03 13:08:51 +0000 | [diff] [blame] | 121 | break; | 
|  | 122 | case MSP430ISD::Wrapper: | 
|  | 123 | SDValue N0 = Addr.getOperand(0); | 
|  | 124 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) { | 
| Anton Korobeynikov | ed65671 | 2009-05-03 13:09:40 +0000 | [diff] [blame] | 125 | Base = CurDAG->getTargetGlobalAddress(G->getGlobal(), | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 126 | MVT::i16, G->getOffset()); | 
|  | 127 | Disp = CurDAG->getTargetConstant(0, MVT::i16); | 
| Anton Korobeynikov | 6399a3d | 2009-05-03 13:09:10 +0000 | [diff] [blame] | 128 | return true; | 
| Anton Korobeynikov | ba0e81d | 2009-05-03 13:14:46 +0000 | [diff] [blame] | 129 | } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(N0)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 130 | Base = CurDAG->getTargetExternalSymbol(E->getSymbol(), MVT::i16); | 
|  | 131 | Disp = CurDAG->getTargetConstant(0, MVT::i16); | 
| Anton Korobeynikov | a3bce28 | 2009-05-03 13:08:51 +0000 | [diff] [blame] | 132 | } | 
|  | 133 | break; | 
|  | 134 | }; | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 135 |  | 
| Anton Korobeynikov | ed65671 | 2009-05-03 13:09:40 +0000 | [diff] [blame] | 136 | Base = Addr; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 137 | Disp = CurDAG->getTargetConstant(0, MVT::i16); | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 138 |  | 
|  | 139 | return true; | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 |  | 
| Anton Korobeynikov | 6bce6bb | 2009-10-11 19:14:21 +0000 | [diff] [blame] | 143 | bool MSP430DAGToDAGISel:: | 
|  | 144 | SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, | 
|  | 145 | std::vector<SDValue> &OutOps) { | 
|  | 146 | SDValue Op0, Op1; | 
|  | 147 | switch (ConstraintCode) { | 
|  | 148 | default: return true; | 
|  | 149 | case 'm':   // memory | 
|  | 150 | if (!SelectAddr(Op, Op, Op0, Op1)) | 
|  | 151 | return true; | 
|  | 152 | break; | 
|  | 153 | } | 
|  | 154 |  | 
|  | 155 | OutOps.push_back(Op0); | 
|  | 156 | OutOps.push_back(Op1); | 
|  | 157 | return false; | 
|  | 158 | } | 
| Anton Korobeynikov | 31ecd23 | 2009-05-03 13:06:03 +0000 | [diff] [blame] | 159 |  | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 160 | /// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand | 
|  | 161 | /// and move load below the TokenFactor. Replace store's chain operand with | 
|  | 162 | /// load's chain result. | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 163 | static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, | 
|  | 164 | SDValue Store, SDValue TF) { | 
|  | 165 | SmallVector<SDValue, 4> Ops; | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 166 | for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 167 | if (Load.getNode() == TF.getOperand(i).getNode()) | 
|  | 168 | Ops.push_back(Load.getOperand(0)); | 
|  | 169 | else | 
|  | 170 | Ops.push_back(TF.getOperand(i)); | 
|  | 171 | SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size()); | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 172 | SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF, | 
|  | 173 | Load.getOperand(1), | 
|  | 174 | Load.getOperand(2)); | 
|  | 175 | CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1), | 
|  | 176 | Store.getOperand(2), Store.getOperand(3)); | 
|  | 177 | } | 
|  | 178 |  | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 179 | /// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. | 
|  | 180 | /// The chain produced by the load must only be used by the store's chain | 
|  | 181 | /// operand, otherwise this may produce a cycle in the DAG. | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 182 | static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, | 
|  | 183 | SDValue &Load) { | 
|  | 184 | if (N.getOpcode() == ISD::BIT_CONVERT) | 
|  | 185 | N = N.getOperand(0); | 
|  | 186 |  | 
|  | 187 | LoadSDNode *LD = dyn_cast<LoadSDNode>(N); | 
|  | 188 | if (!LD || LD->isVolatile()) | 
|  | 189 | return false; | 
|  | 190 | if (LD->getAddressingMode() != ISD::UNINDEXED) | 
|  | 191 | return false; | 
|  | 192 |  | 
|  | 193 | ISD::LoadExtType ExtType = LD->getExtensionType(); | 
|  | 194 | if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) | 
|  | 195 | return false; | 
|  | 196 |  | 
|  | 197 | if (N.hasOneUse() && | 
|  | 198 | LD->hasNUsesOfValue(1, 1) && | 
|  | 199 | N.getOperand(1) == Address && | 
|  | 200 | LD->isOperandOf(Chain.getNode())) { | 
|  | 201 | Load = N; | 
|  | 202 | return true; | 
|  | 203 | } | 
|  | 204 | return false; | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | /// PreprocessForRMW - Preprocess the DAG to make instruction selection better. | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 208 | /// This is only run if not in -O0 mode. | 
|  | 209 | /// This allows the instruction selector to pick more read-modify-write | 
|  | 210 | /// instructions. This is a common case: | 
|  | 211 | /// | 
|  | 212 | ///     [Load chain] | 
|  | 213 | ///         ^ | 
|  | 214 | ///         | | 
|  | 215 | ///       [Load] | 
|  | 216 | ///       ^    ^ | 
|  | 217 | ///       |    | | 
|  | 218 | ///      /      \- | 
|  | 219 | ///     /         | | 
|  | 220 | /// [TokenFactor] [Op] | 
|  | 221 | ///     ^          ^ | 
|  | 222 | ///     |          | | 
|  | 223 | ///      \        / | 
|  | 224 | ///       \      / | 
|  | 225 | ///       [Store] | 
|  | 226 | /// | 
|  | 227 | /// The fact the store's chain operand != load's chain will prevent the | 
|  | 228 | /// (store (op (load))) instruction from being selected. We can transform it to: | 
|  | 229 | /// | 
|  | 230 | ///     [Load chain] | 
|  | 231 | ///         ^ | 
|  | 232 | ///         | | 
|  | 233 | ///    [TokenFactor] | 
|  | 234 | ///         ^ | 
|  | 235 | ///         | | 
|  | 236 | ///       [Load] | 
|  | 237 | ///       ^    ^ | 
|  | 238 | ///       |    | | 
|  | 239 | ///       |     \- | 
|  | 240 | ///       |       | | 
|  | 241 | ///       |     [Op] | 
|  | 242 | ///       |       ^ | 
|  | 243 | ///       |       | | 
|  | 244 | ///       \      / | 
|  | 245 | ///        \    / | 
|  | 246 | ///       [Store] | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 247 | void MSP430DAGToDAGISel::PreprocessForRMW() { | 
|  | 248 | for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), | 
|  | 249 | E = CurDAG->allnodes_end(); I != E; ++I) { | 
|  | 250 | if (!ISD::isNON_TRUNCStore(I)) | 
|  | 251 | continue; | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 252 | SDValue Chain = I->getOperand(0); | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 253 |  | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 254 | if (Chain.getNode()->getOpcode() != ISD::TokenFactor) | 
|  | 255 | continue; | 
|  | 256 |  | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 257 | SDValue N1 = I->getOperand(1); | 
|  | 258 | SDValue N2 = I->getOperand(2); | 
|  | 259 | if ((N1.getValueType().isFloatingPoint() && | 
|  | 260 | !N1.getValueType().isVector()) || | 
|  | 261 | !N1.hasOneUse()) | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 262 | continue; | 
|  | 263 |  | 
|  | 264 | bool RModW = false; | 
|  | 265 | SDValue Load; | 
|  | 266 | unsigned Opcode = N1.getNode()->getOpcode(); | 
|  | 267 | switch (Opcode) { | 
| Anton Korobeynikov | ccfa3e3 | 2009-10-21 19:17:55 +0000 | [diff] [blame] | 268 | case ISD::ADD: | 
|  | 269 | case ISD::AND: | 
|  | 270 | case ISD::OR: | 
|  | 271 | case ISD::XOR: | 
|  | 272 | case ISD::ADDC: | 
|  | 273 | case ISD::ADDE: { | 
|  | 274 | SDValue N10 = N1.getOperand(0); | 
|  | 275 | SDValue N11 = N1.getOperand(1); | 
|  | 276 | RModW = isRMWLoad(N10, Chain, N2, Load); | 
|  | 277 | if (!RModW) | 
|  | 278 | RModW = isRMWLoad(N11, Chain, N2, Load); | 
|  | 279 | break; | 
|  | 280 | } | 
|  | 281 | case ISD::SUB: | 
|  | 282 | case ISD::SUBC: | 
|  | 283 | case ISD::SUBE: { | 
|  | 284 | SDValue N10 = N1.getOperand(0); | 
|  | 285 | RModW = isRMWLoad(N10, Chain, N2, Load); | 
|  | 286 | break; | 
|  | 287 | } | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 288 | } | 
|  | 289 |  | 
|  | 290 | if (RModW) { | 
|  | 291 | MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain); | 
|  | 292 | ++NumLoadMoved; | 
|  | 293 | } | 
|  | 294 | } | 
|  | 295 | } | 
|  | 296 |  | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 297 | /// InstructionSelect - This callback is invoked by | 
|  | 298 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
| Anton Korobeynikov | e10f69a | 2009-05-03 12:58:40 +0000 | [diff] [blame] | 299 | void MSP430DAGToDAGISel::InstructionSelect() { | 
| Anton Korobeynikov | 9e92857 | 2009-10-21 19:18:28 +0000 | [diff] [blame] | 300 | std::string BlockName; | 
|  | 301 | if (ViewRMWDAGs) | 
|  | 302 | BlockName = MF->getFunction()->getNameStr() + ":" + | 
|  | 303 | BB->getBasicBlock()->getNameStr(); | 
|  | 304 |  | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 305 | PreprocessForRMW(); | 
|  | 306 |  | 
| Anton Korobeynikov | 9e92857 | 2009-10-21 19:18:28 +0000 | [diff] [blame] | 307 | if (ViewRMWDAGs) CurDAG->viewGraph("RMW preprocessed:" + BlockName); | 
|  | 308 |  | 
| Anton Korobeynikov | 415c3dc | 2009-10-11 23:03:28 +0000 | [diff] [blame] | 309 | DEBUG(errs() << "Selection DAG after RMW preprocessing:\n"); | 
|  | 310 | DEBUG(CurDAG->dump()); | 
|  | 311 |  | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 312 | DEBUG(BB->dump()); | 
|  | 313 |  | 
| Anton Korobeynikov | f3a6bc8 | 2009-05-03 13:16:37 +0000 | [diff] [blame] | 314 | // Codegen the basic block. | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 315 | DEBUG(errs() << "===== Instruction selection begins:\n"); | 
| Daniel Dunbar | 34ee203 | 2009-08-23 08:50:52 +0000 | [diff] [blame] | 316 | DEBUG(Indent = 0); | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 317 | SelectRoot(*CurDAG); | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 318 | DEBUG(errs() << "===== Instruction selection ends:\n"); | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 319 |  | 
|  | 320 | CurDAG->RemoveDeadNodes(); | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | SDNode *MSP430DAGToDAGISel::Select(SDValue Op) { | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 324 | SDNode *Node = Op.getNode(); | 
| Anton Korobeynikov | 7784ae9 | 2009-05-03 13:10:26 +0000 | [diff] [blame] | 325 | DebugLoc dl = Op.getDebugLoc(); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 326 |  | 
|  | 327 | // Dump information about the Node being selected | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 328 | DEBUG(errs().indent(Indent) << "Selecting: "); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 329 | DEBUG(Node->dump(CurDAG)); | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 330 | DEBUG(errs() << "\n"); | 
| Daniel Dunbar | 34ee203 | 2009-08-23 08:50:52 +0000 | [diff] [blame] | 331 | DEBUG(Indent += 2); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 332 |  | 
|  | 333 | // If we have a custom node, we already have selected! | 
|  | 334 | if (Node->isMachineOpcode()) { | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 335 | DEBUG(errs().indent(Indent-2) << "== "; | 
|  | 336 | Node->dump(CurDAG); | 
|  | 337 | errs() << "\n"); | 
| Daniel Dunbar | 34ee203 | 2009-08-23 08:50:52 +0000 | [diff] [blame] | 338 | DEBUG(Indent -= 2); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 339 | return NULL; | 
|  | 340 | } | 
|  | 341 |  | 
| Anton Korobeynikov | 7784ae9 | 2009-05-03 13:10:26 +0000 | [diff] [blame] | 342 | // Few custom selection stuff. | 
|  | 343 | switch (Node->getOpcode()) { | 
|  | 344 | default: break; | 
|  | 345 | case ISD::FrameIndex: { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 346 | assert(Op.getValueType() == MVT::i16); | 
| Anton Korobeynikov | 7784ae9 | 2009-05-03 13:10:26 +0000 | [diff] [blame] | 347 | int FI = cast<FrameIndexSDNode>(Node)->getIndex(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 348 | SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16); | 
| Anton Korobeynikov | 7784ae9 | 2009-05-03 13:10:26 +0000 | [diff] [blame] | 349 | if (Node->hasOneUse()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 350 | return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16, | 
|  | 351 | TFI, CurDAG->getTargetConstant(0, MVT::i16)); | 
| Dan Gohman | 32f71d7 | 2009-09-25 18:54:59 +0000 | [diff] [blame] | 352 | return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16, | 
|  | 353 | TFI, CurDAG->getTargetConstant(0, MVT::i16)); | 
| Anton Korobeynikov | 7784ae9 | 2009-05-03 13:10:26 +0000 | [diff] [blame] | 354 | } | 
|  | 355 | } | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 356 |  | 
|  | 357 | // Select the default instruction | 
|  | 358 | SDNode *ResNode = SelectCode(Op); | 
|  | 359 |  | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 360 | DEBUG(errs() << std::string(Indent-2, ' ') << "=> "); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 361 | if (ResNode == NULL || ResNode == Op.getNode()) | 
|  | 362 | DEBUG(Op.getNode()->dump(CurDAG)); | 
|  | 363 | else | 
|  | 364 | DEBUG(ResNode->dump(CurDAG)); | 
| Chris Lattner | af29ea6 | 2009-08-23 06:49:22 +0000 | [diff] [blame] | 365 | DEBUG(errs() << "\n"); | 
| Daniel Dunbar | 34ee203 | 2009-08-23 08:50:52 +0000 | [diff] [blame] | 366 | DEBUG(Indent -= 2); | 
| Anton Korobeynikov | 64717bb | 2009-05-03 12:58:58 +0000 | [diff] [blame] | 367 |  | 
|  | 368 | return ResNode; | 
| Anton Korobeynikov | 1013800 | 2009-05-03 12:57:15 +0000 | [diff] [blame] | 369 | } |