Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/MSP430/MSP430ISelDAGToDAG.cpp @ 0:95c75e76d11b LLVM3.4
LLVM 3.4
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 12 Dec 2013 13:56:28 +0900 |
parents | |
children | 54457678186b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:95c75e76d11b |
---|---|
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 "MSP430TargetMachine.h" | |
16 #include "llvm/CodeGen/MachineFrameInfo.h" | |
17 #include "llvm/CodeGen/MachineFunction.h" | |
18 #include "llvm/CodeGen/MachineInstrBuilder.h" | |
19 #include "llvm/CodeGen/MachineRegisterInfo.h" | |
20 #include "llvm/CodeGen/SelectionDAG.h" | |
21 #include "llvm/CodeGen/SelectionDAGISel.h" | |
22 #include "llvm/IR/CallingConv.h" | |
23 #include "llvm/IR/Constants.h" | |
24 #include "llvm/IR/DerivedTypes.h" | |
25 #include "llvm/IR/Function.h" | |
26 #include "llvm/IR/Intrinsics.h" | |
27 #include "llvm/Support/Compiler.h" | |
28 #include "llvm/Support/Debug.h" | |
29 #include "llvm/Support/ErrorHandling.h" | |
30 #include "llvm/Support/raw_ostream.h" | |
31 #include "llvm/Target/TargetLowering.h" | |
32 using namespace llvm; | |
33 | |
34 namespace { | |
35 struct MSP430ISelAddressMode { | |
36 enum { | |
37 RegBase, | |
38 FrameIndexBase | |
39 } BaseType; | |
40 | |
41 struct { // This is really a union, discriminated by BaseType! | |
42 SDValue Reg; | |
43 int FrameIndex; | |
44 } Base; | |
45 | |
46 int16_t Disp; | |
47 const GlobalValue *GV; | |
48 const Constant *CP; | |
49 const BlockAddress *BlockAddr; | |
50 const char *ES; | |
51 int JT; | |
52 unsigned Align; // CP alignment. | |
53 | |
54 MSP430ISelAddressMode() | |
55 : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0), | |
56 ES(0), JT(-1), Align(0) { | |
57 } | |
58 | |
59 bool hasSymbolicDisplacement() const { | |
60 return GV != 0 || CP != 0 || ES != 0 || JT != -1; | |
61 } | |
62 | |
63 void dump() { | |
64 errs() << "MSP430ISelAddressMode " << this << '\n'; | |
65 if (BaseType == RegBase && Base.Reg.getNode() != 0) { | |
66 errs() << "Base.Reg "; | |
67 Base.Reg.getNode()->dump(); | |
68 } else if (BaseType == FrameIndexBase) { | |
69 errs() << " Base.FrameIndex " << Base.FrameIndex << '\n'; | |
70 } | |
71 errs() << " Disp " << Disp << '\n'; | |
72 if (GV) { | |
73 errs() << "GV "; | |
74 GV->dump(); | |
75 } else if (CP) { | |
76 errs() << " CP "; | |
77 CP->dump(); | |
78 errs() << " Align" << Align << '\n'; | |
79 } else if (ES) { | |
80 errs() << "ES "; | |
81 errs() << ES << '\n'; | |
82 } else if (JT != -1) | |
83 errs() << " JT" << JT << " Align" << Align << '\n'; | |
84 } | |
85 }; | |
86 } | |
87 | |
88 /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine | |
89 /// instructions for SelectionDAG operations. | |
90 /// | |
91 namespace { | |
92 class MSP430DAGToDAGISel : public SelectionDAGISel { | |
93 const MSP430TargetLowering &Lowering; | |
94 const MSP430Subtarget &Subtarget; | |
95 | |
96 public: | |
97 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel) | |
98 : SelectionDAGISel(TM, OptLevel), | |
99 Lowering(*TM.getTargetLowering()), | |
100 Subtarget(*TM.getSubtargetImpl()) { } | |
101 | |
102 virtual const char *getPassName() const { | |
103 return "MSP430 DAG->DAG Pattern Instruction Selection"; | |
104 } | |
105 | |
106 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM); | |
107 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM); | |
108 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM); | |
109 | |
110 virtual bool | |
111 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, | |
112 std::vector<SDValue> &OutOps); | |
113 | |
114 // Include the pieces autogenerated from the target description. | |
115 #include "MSP430GenDAGISel.inc" | |
116 | |
117 private: | |
118 SDNode *Select(SDNode *N); | |
119 SDNode *SelectIndexedLoad(SDNode *Op); | |
120 SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, | |
121 unsigned Opc8, unsigned Opc16); | |
122 | |
123 bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp); | |
124 }; | |
125 } // end anonymous namespace | |
126 | |
127 /// createMSP430ISelDag - This pass converts a legalized DAG into a | |
128 /// MSP430-specific DAG, ready for instruction scheduling. | |
129 /// | |
130 FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM, | |
131 CodeGenOpt::Level OptLevel) { | |
132 return new MSP430DAGToDAGISel(TM, OptLevel); | |
133 } | |
134 | |
135 | |
136 /// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode. | |
137 /// These wrap things that will resolve down into a symbol reference. If no | |
138 /// match is possible, this returns true, otherwise it returns false. | |
139 bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) { | |
140 // If the addressing mode already has a symbol as the displacement, we can | |
141 // never match another symbol. | |
142 if (AM.hasSymbolicDisplacement()) | |
143 return true; | |
144 | |
145 SDValue N0 = N.getOperand(0); | |
146 | |
147 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) { | |
148 AM.GV = G->getGlobal(); | |
149 AM.Disp += G->getOffset(); | |
150 //AM.SymbolFlags = G->getTargetFlags(); | |
151 } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) { | |
152 AM.CP = CP->getConstVal(); | |
153 AM.Align = CP->getAlignment(); | |
154 AM.Disp += CP->getOffset(); | |
155 //AM.SymbolFlags = CP->getTargetFlags(); | |
156 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) { | |
157 AM.ES = S->getSymbol(); | |
158 //AM.SymbolFlags = S->getTargetFlags(); | |
159 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) { | |
160 AM.JT = J->getIndex(); | |
161 //AM.SymbolFlags = J->getTargetFlags(); | |
162 } else { | |
163 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress(); | |
164 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags(); | |
165 } | |
166 return false; | |
167 } | |
168 | |
169 /// MatchAddressBase - Helper for MatchAddress. Add the specified node to the | |
170 /// specified addressing mode without any further recursion. | |
171 bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) { | |
172 // Is the base register already occupied? | |
173 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) { | |
174 // If so, we cannot select it. | |
175 return true; | |
176 } | |
177 | |
178 // Default, generate it as a register. | |
179 AM.BaseType = MSP430ISelAddressMode::RegBase; | |
180 AM.Base.Reg = N; | |
181 return false; | |
182 } | |
183 | |
184 bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) { | |
185 DEBUG(errs() << "MatchAddress: "; AM.dump()); | |
186 | |
187 switch (N.getOpcode()) { | |
188 default: break; | |
189 case ISD::Constant: { | |
190 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); | |
191 AM.Disp += Val; | |
192 return false; | |
193 } | |
194 | |
195 case MSP430ISD::Wrapper: | |
196 if (!MatchWrapper(N, AM)) | |
197 return false; | |
198 break; | |
199 | |
200 case ISD::FrameIndex: | |
201 if (AM.BaseType == MSP430ISelAddressMode::RegBase | |
202 && AM.Base.Reg.getNode() == 0) { | |
203 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase; | |
204 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); | |
205 return false; | |
206 } | |
207 break; | |
208 | |
209 case ISD::ADD: { | |
210 MSP430ISelAddressMode Backup = AM; | |
211 if (!MatchAddress(N.getNode()->getOperand(0), AM) && | |
212 !MatchAddress(N.getNode()->getOperand(1), AM)) | |
213 return false; | |
214 AM = Backup; | |
215 if (!MatchAddress(N.getNode()->getOperand(1), AM) && | |
216 !MatchAddress(N.getNode()->getOperand(0), AM)) | |
217 return false; | |
218 AM = Backup; | |
219 | |
220 break; | |
221 } | |
222 | |
223 case ISD::OR: | |
224 // Handle "X | C" as "X + C" iff X is known to have C bits clear. | |
225 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | |
226 MSP430ISelAddressMode Backup = AM; | |
227 uint64_t Offset = CN->getSExtValue(); | |
228 // Start with the LHS as an addr mode. | |
229 if (!MatchAddress(N.getOperand(0), AM) && | |
230 // Address could not have picked a GV address for the displacement. | |
231 AM.GV == NULL && | |
232 // Check to see if the LHS & C is zero. | |
233 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) { | |
234 AM.Disp += Offset; | |
235 return false; | |
236 } | |
237 AM = Backup; | |
238 } | |
239 break; | |
240 } | |
241 | |
242 return MatchAddressBase(N, AM); | |
243 } | |
244 | |
245 /// SelectAddr - returns true if it is able pattern match an addressing mode. | |
246 /// It returns the operands which make up the maximal addressing mode it can | |
247 /// match by reference. | |
248 bool MSP430DAGToDAGISel::SelectAddr(SDValue N, | |
249 SDValue &Base, SDValue &Disp) { | |
250 MSP430ISelAddressMode AM; | |
251 | |
252 if (MatchAddress(N, AM)) | |
253 return false; | |
254 | |
255 EVT VT = N.getValueType(); | |
256 if (AM.BaseType == MSP430ISelAddressMode::RegBase) { | |
257 if (!AM.Base.Reg.getNode()) | |
258 AM.Base.Reg = CurDAG->getRegister(0, VT); | |
259 } | |
260 | |
261 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ? | |
262 CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, | |
263 getTargetLowering()->getPointerTy()) : | |
264 AM.Base.Reg; | |
265 | |
266 if (AM.GV) | |
267 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N), | |
268 MVT::i16, AM.Disp, | |
269 0/*AM.SymbolFlags*/); | |
270 else if (AM.CP) | |
271 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, | |
272 AM.Align, AM.Disp, 0/*AM.SymbolFlags*/); | |
273 else if (AM.ES) | |
274 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/); | |
275 else if (AM.JT != -1) | |
276 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/); | |
277 else if (AM.BlockAddr) | |
278 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0, | |
279 0/*AM.SymbolFlags*/); | |
280 else | |
281 Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16); | |
282 | |
283 return true; | |
284 } | |
285 | |
286 bool MSP430DAGToDAGISel:: | |
287 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, | |
288 std::vector<SDValue> &OutOps) { | |
289 SDValue Op0, Op1; | |
290 switch (ConstraintCode) { | |
291 default: return true; | |
292 case 'm': // memory | |
293 if (!SelectAddr(Op, Op0, Op1)) | |
294 return true; | |
295 break; | |
296 } | |
297 | |
298 OutOps.push_back(Op0); | |
299 OutOps.push_back(Op1); | |
300 return false; | |
301 } | |
302 | |
303 static bool isValidIndexedLoad(const LoadSDNode *LD) { | |
304 ISD::MemIndexedMode AM = LD->getAddressingMode(); | |
305 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD) | |
306 return false; | |
307 | |
308 EVT VT = LD->getMemoryVT(); | |
309 | |
310 switch (VT.getSimpleVT().SimpleTy) { | |
311 case MVT::i8: | |
312 // Sanity check | |
313 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1) | |
314 return false; | |
315 | |
316 break; | |
317 case MVT::i16: | |
318 // Sanity check | |
319 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2) | |
320 return false; | |
321 | |
322 break; | |
323 default: | |
324 return false; | |
325 } | |
326 | |
327 return true; | |
328 } | |
329 | |
330 SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) { | |
331 LoadSDNode *LD = cast<LoadSDNode>(N); | |
332 if (!isValidIndexedLoad(LD)) | |
333 return NULL; | |
334 | |
335 MVT VT = LD->getMemoryVT().getSimpleVT(); | |
336 | |
337 unsigned Opcode = 0; | |
338 switch (VT.SimpleTy) { | |
339 case MVT::i8: | |
340 Opcode = MSP430::MOV8rm_POST; | |
341 break; | |
342 case MVT::i16: | |
343 Opcode = MSP430::MOV16rm_POST; | |
344 break; | |
345 default: | |
346 return NULL; | |
347 } | |
348 | |
349 return CurDAG->getMachineNode(Opcode, SDLoc(N), | |
350 VT, MVT::i16, MVT::Other, | |
351 LD->getBasePtr(), LD->getChain()); | |
352 } | |
353 | |
354 SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op, | |
355 SDValue N1, SDValue N2, | |
356 unsigned Opc8, unsigned Opc16) { | |
357 if (N1.getOpcode() == ISD::LOAD && | |
358 N1.hasOneUse() && | |
359 IsLegalToFold(N1, Op, Op, OptLevel)) { | |
360 LoadSDNode *LD = cast<LoadSDNode>(N1); | |
361 if (!isValidIndexedLoad(LD)) | |
362 return NULL; | |
363 | |
364 MVT VT = LD->getMemoryVT().getSimpleVT(); | |
365 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8); | |
366 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); | |
367 MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand(); | |
368 SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() }; | |
369 SDNode *ResNode = | |
370 CurDAG->SelectNodeTo(Op, Opc, | |
371 VT, MVT::i16, MVT::Other, | |
372 Ops0, 3); | |
373 cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1); | |
374 // Transfer chain. | |
375 ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2)); | |
376 // Transfer writeback. | |
377 ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1)); | |
378 return ResNode; | |
379 } | |
380 | |
381 return NULL; | |
382 } | |
383 | |
384 | |
385 SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) { | |
386 SDLoc dl(Node); | |
387 | |
388 // Dump information about the Node being selected | |
389 DEBUG(errs() << "Selecting: "); | |
390 DEBUG(Node->dump(CurDAG)); | |
391 DEBUG(errs() << "\n"); | |
392 | |
393 // If we have a custom node, we already have selected! | |
394 if (Node->isMachineOpcode()) { | |
395 DEBUG(errs() << "== "; | |
396 Node->dump(CurDAG); | |
397 errs() << "\n"); | |
398 Node->setNodeId(-1); | |
399 return NULL; | |
400 } | |
401 | |
402 // Few custom selection stuff. | |
403 switch (Node->getOpcode()) { | |
404 default: break; | |
405 case ISD::FrameIndex: { | |
406 assert(Node->getValueType(0) == MVT::i16); | |
407 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); | |
408 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16); | |
409 if (Node->hasOneUse()) | |
410 return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16, | |
411 TFI, CurDAG->getTargetConstant(0, MVT::i16)); | |
412 return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16, | |
413 TFI, CurDAG->getTargetConstant(0, MVT::i16)); | |
414 } | |
415 case ISD::LOAD: | |
416 if (SDNode *ResNode = SelectIndexedLoad(Node)) | |
417 return ResNode; | |
418 // Other cases are autogenerated. | |
419 break; | |
420 case ISD::ADD: | |
421 if (SDNode *ResNode = | |
422 SelectIndexedBinOp(Node, | |
423 Node->getOperand(0), Node->getOperand(1), | |
424 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST)) | |
425 return ResNode; | |
426 else if (SDNode *ResNode = | |
427 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), | |
428 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST)) | |
429 return ResNode; | |
430 | |
431 // Other cases are autogenerated. | |
432 break; | |
433 case ISD::SUB: | |
434 if (SDNode *ResNode = | |
435 SelectIndexedBinOp(Node, | |
436 Node->getOperand(0), Node->getOperand(1), | |
437 MSP430::SUB8rm_POST, MSP430::SUB16rm_POST)) | |
438 return ResNode; | |
439 | |
440 // Other cases are autogenerated. | |
441 break; | |
442 case ISD::AND: | |
443 if (SDNode *ResNode = | |
444 SelectIndexedBinOp(Node, | |
445 Node->getOperand(0), Node->getOperand(1), | |
446 MSP430::AND8rm_POST, MSP430::AND16rm_POST)) | |
447 return ResNode; | |
448 else if (SDNode *ResNode = | |
449 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), | |
450 MSP430::AND8rm_POST, MSP430::AND16rm_POST)) | |
451 return ResNode; | |
452 | |
453 // Other cases are autogenerated. | |
454 break; | |
455 case ISD::OR: | |
456 if (SDNode *ResNode = | |
457 SelectIndexedBinOp(Node, | |
458 Node->getOperand(0), Node->getOperand(1), | |
459 MSP430::OR8rm_POST, MSP430::OR16rm_POST)) | |
460 return ResNode; | |
461 else if (SDNode *ResNode = | |
462 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), | |
463 MSP430::OR8rm_POST, MSP430::OR16rm_POST)) | |
464 return ResNode; | |
465 | |
466 // Other cases are autogenerated. | |
467 break; | |
468 case ISD::XOR: | |
469 if (SDNode *ResNode = | |
470 SelectIndexedBinOp(Node, | |
471 Node->getOperand(0), Node->getOperand(1), | |
472 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST)) | |
473 return ResNode; | |
474 else if (SDNode *ResNode = | |
475 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), | |
476 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST)) | |
477 return ResNode; | |
478 | |
479 // Other cases are autogenerated. | |
480 break; | |
481 } | |
482 | |
483 // Select the default instruction | |
484 SDNode *ResNode = SelectCode(Node); | |
485 | |
486 DEBUG(errs() << "=> "); | |
487 if (ResNode == NULL || ResNode == Node) | |
488 DEBUG(Node->dump(CurDAG)); | |
489 else | |
490 DEBUG(ResNode->dump(CurDAG)); | |
491 DEBUG(errs() << "\n"); | |
492 | |
493 return ResNode; | |
494 } |