blob: 2ca184e5eafd2d354b26619f57d3af330a494bfd [file] [log] [blame]
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +00001//===-- 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"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000031#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/raw_ostream.h"
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +000033#include "llvm/ADT/Statistic.h"
34
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000035using namespace llvm;
36
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +000037STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
38
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000039
40namespace {
41 struct MSP430ISelAddressMode {
42 enum {
43 RegBase,
44 FrameIndexBase
45 } BaseType;
46
47 struct { // This is really a union, discriminated by BaseType!
48 SDValue Reg;
49 int FrameIndex;
50 } Base;
51
52 int16_t Disp;
53 GlobalValue *GV;
54 Constant *CP;
55 BlockAddress *BlockAddr;
56 const char *ES;
57 int JT;
58 unsigned Align; // CP alignment.
59
60 MSP430ISelAddressMode()
61 : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0),
62 ES(0), JT(-1), Align(0) {
63 }
64
65 bool hasSymbolicDisplacement() const {
66 return GV != 0 || CP != 0 || ES != 0 || JT != -1;
67 }
68
69 bool hasBaseReg() const {
70 return Base.Reg.getNode() != 0;
71 }
72
73 void setBaseReg(SDValue Reg) {
74 BaseType = RegBase;
75 Base.Reg = Reg;
76 }
77
78 void dump() {
79 errs() << "MSP430ISelAddressMode " << this << '\n';
Anton Korobeynikovcdcad112009-12-13 01:00:32 +000080 if (BaseType == RegBase && Base.Reg.getNode() != 0) {
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000081 errs() << "Base.Reg ";
82 Base.Reg.getNode()->dump();
Anton Korobeynikovcdcad112009-12-13 01:00:32 +000083 } else if (BaseType == FrameIndexBase) {
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000084 errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
85 }
86 errs() << " Disp " << Disp << '\n';
87 if (GV) {
88 errs() << "GV ";
89 GV->dump();
90 } else if (CP) {
91 errs() << " CP ";
92 CP->dump();
93 errs() << " Align" << Align << '\n';
94 } else if (ES) {
95 errs() << "ES ";
96 errs() << ES << '\n';
97 } else if (JT != -1)
98 errs() << " JT" << JT << " Align" << Align << '\n';
99 }
100 };
101}
102
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000103/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
104/// instructions for SelectionDAG operations.
105///
106namespace {
107 class MSP430DAGToDAGISel : public SelectionDAGISel {
108 MSP430TargetLowering &Lowering;
109 const MSP430Subtarget &Subtarget;
110
111 public:
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000112 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
113 : SelectionDAGISel(TM, OptLevel),
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000114 Lowering(*TM.getTargetLowering()),
115 Subtarget(*TM.getSubtargetImpl()) { }
116
Chris Lattner7c306da2010-03-02 06:34:30 +0000117 virtual void PreprocessISelDAG();
118 virtual void PostprocessISelDAG();
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000119
120 virtual const char *getPassName() const {
121 return "MSP430 DAG->DAG Pattern Instruction Selection";
122 }
123
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000124 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
125 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
126 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
127
Chris Lattnerd1b73822010-03-02 22:20:06 +0000128#if 0
Evan Cheng014bf212010-02-15 19:41:07 +0000129 bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
Chris Lattnerd1b73822010-03-02 22:20:06 +0000130#endif
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000131
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000132 virtual bool
133 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
134 std::vector<SDValue> &OutOps);
135
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000136 // Include the pieces autogenerated from the target description.
137 #include "MSP430GenDAGISel.inc"
138
139 private:
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000140 DenseMap<SDNode*, SDNode*> RMWStores;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000141 void PreprocessForRMW();
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000142 SDNode *Select(SDNode *N);
143 SDNode *SelectIndexedLoad(SDNode *Op);
144 SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000145 unsigned Opc8, unsigned Opc16);
146
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000147 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Disp);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000148 };
149} // end anonymous namespace
150
151/// createMSP430ISelDag - This pass converts a legalized DAG into a
152/// MSP430-specific DAG, ready for instruction scheduling.
153///
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000154FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
155 CodeGenOpt::Level OptLevel) {
156 return new MSP430DAGToDAGISel(TM, OptLevel);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000157}
158
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000159
160/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
161/// These wrap things that will resolve down into a symbol reference. If no
162/// match is possible, this returns true, otherwise it returns false.
163bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
164 // If the addressing mode already has a symbol as the displacement, we can
165 // never match another symbol.
166 if (AM.hasSymbolicDisplacement())
167 return true;
168
169 SDValue N0 = N.getOperand(0);
170
171 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
172 AM.GV = G->getGlobal();
173 AM.Disp += G->getOffset();
174 //AM.SymbolFlags = G->getTargetFlags();
175 } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
176 AM.CP = CP->getConstVal();
177 AM.Align = CP->getAlignment();
178 AM.Disp += CP->getOffset();
179 //AM.SymbolFlags = CP->getTargetFlags();
180 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
181 AM.ES = S->getSymbol();
182 //AM.SymbolFlags = S->getTargetFlags();
183 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
184 AM.JT = J->getIndex();
185 //AM.SymbolFlags = J->getTargetFlags();
186 } else {
187 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
188 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
189 }
190 return false;
191}
192
193/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
194/// specified addressing mode without any further recursion.
195bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
196 // Is the base register already occupied?
197 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
198 // If so, we cannot select it.
Anton Korobeynikov82e46c22009-05-03 13:10:11 +0000199 return true;
200 }
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000201
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000202 // Default, generate it as a register.
203 AM.BaseType = MSP430ISelAddressMode::RegBase;
204 AM.Base.Reg = N;
205 return false;
206}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000207
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000208bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000209 DEBUG({
210 errs() << "MatchAddress: ";
211 AM.dump();
212 });
213
214 switch (N.getOpcode()) {
215 default: break;
216 case ISD::Constant: {
217 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
218 AM.Disp += Val;
219 return false;
220 }
221
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000222 case MSP430ISD::Wrapper:
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000223 if (!MatchWrapper(N, AM))
224 return false;
225 break;
226
227 case ISD::FrameIndex:
228 if (AM.BaseType == MSP430ISelAddressMode::RegBase
229 && AM.Base.Reg.getNode() == 0) {
230 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
231 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
232 return false;
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000233 }
234 break;
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000235
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000236 case ISD::ADD: {
237 MSP430ISelAddressMode Backup = AM;
238 if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
239 !MatchAddress(N.getNode()->getOperand(1), AM))
240 return false;
241 AM = Backup;
242 if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
243 !MatchAddress(N.getNode()->getOperand(0), AM))
244 return false;
245 AM = Backup;
246
247 break;
248 }
249
250 case ISD::OR:
251 // Handle "X | C" as "X + C" iff X is known to have C bits clear.
252 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
253 MSP430ISelAddressMode Backup = AM;
254 uint64_t Offset = CN->getSExtValue();
255 // Start with the LHS as an addr mode.
256 if (!MatchAddress(N.getOperand(0), AM) &&
257 // Address could not have picked a GV address for the displacement.
258 AM.GV == NULL &&
259 // Check to see if the LHS & C is zero.
260 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
261 AM.Disp += Offset;
262 return false;
263 }
264 AM = Backup;
265 }
266 break;
267 }
268
269 return MatchAddressBase(N, AM);
270}
271
272/// SelectAddr - returns true if it is able pattern match an addressing mode.
273/// It returns the operands which make up the maximal addressing mode it can
274/// match by reference.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000275bool MSP430DAGToDAGISel::SelectAddr(SDNode *Op, SDValue N,
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000276 SDValue &Base, SDValue &Disp) {
277 MSP430ISelAddressMode AM;
278
279 if (MatchAddress(N, AM))
280 return false;
281
282 EVT VT = N.getValueType();
283 if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
284 if (!AM.Base.Reg.getNode())
285 AM.Base.Reg = CurDAG->getRegister(0, VT);
286 }
287
288 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ?
289 CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy()) :
290 AM.Base.Reg;
291
292 if (AM.GV)
293 Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i16, AM.Disp,
294 0/*AM.SymbolFlags*/);
295 else if (AM.CP)
296 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
297 AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
298 else if (AM.ES)
299 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
300 else if (AM.JT != -1)
301 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
302 else if (AM.BlockAddr)
Dan Gohman71a41962009-11-20 23:21:00 +0000303 Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32,
304 true, 0/*AM.SymbolFlags*/);
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000305 else
306 Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000307
308 return true;
309}
310
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000311bool MSP430DAGToDAGISel::
312SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
313 std::vector<SDValue> &OutOps) {
314 SDValue Op0, Op1;
315 switch (ConstraintCode) {
316 default: return true;
317 case 'm': // memory
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000318 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000319 return true;
320 break;
321 }
322
323 OutOps.push_back(Op0);
324 OutOps.push_back(Op1);
325 return false;
326}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000327
Chris Lattnerd1b73822010-03-02 22:20:06 +0000328#if 0
Evan Cheng014bf212010-02-15 19:41:07 +0000329bool MSP430DAGToDAGISel::IsLegalToFold(SDValue N, SDNode *U,
330 SDNode *Root) const {
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000331 if (OptLevel == CodeGenOpt::None) return false;
332
333 /// RMW preprocessing creates the following code:
Benjamin Kramer1395d1d2009-10-22 09:28:49 +0000334 /// [Load1]
335 /// ^ ^
336 /// / |
337 /// / |
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000338 /// [Load2] |
339 /// ^ ^ |
340 /// | | |
341 /// | \-|
342 /// | |
343 /// | [Op]
344 /// | ^
345 /// | |
346 /// \ /
347 /// \ /
348 /// [Store]
349 ///
350 /// The path Store => Load2 => Load1 is via chain. Note that in general it is
351 /// not allowed to fold Load1 into Op (and Store) since it will creates a
352 /// cycle. However, this is perfectly legal for the loads moved below the
353 /// TokenFactor by PreprocessForRMW. Query the map Store => Load1 (created
354 /// during preprocessing) to determine whether it's legal to introduce such
355 /// "cycle" for a moment.
Jeffrey Yasskin81cf4322009-11-10 01:02:17 +0000356 DenseMap<SDNode*, SDNode*>::const_iterator I = RMWStores.find(Root);
Evan Cheng014bf212010-02-15 19:41:07 +0000357 if (I != RMWStores.end() && I->second == N.getNode())
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000358 return true;
359
360 // Proceed to 'generic' cycle finder code
Evan Cheng014bf212010-02-15 19:41:07 +0000361 return SelectionDAGISel::IsLegalToFold(N, U, Root);
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000362}
Chris Lattnerd1b73822010-03-02 22:20:06 +0000363#endif
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000364
365
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000366/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
367/// and move load below the TokenFactor. Replace store's chain operand with
368/// load's chain result.
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000369static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
370 SDValue Store, SDValue TF) {
371 SmallVector<SDValue, 4> Ops;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000372 for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i)
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000373 if (Load.getNode() == TF.getOperand(i).getNode())
374 Ops.push_back(Load.getOperand(0));
375 else
376 Ops.push_back(TF.getOperand(i));
377 SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size());
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000378 SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF,
379 Load.getOperand(1),
380 Load.getOperand(2));
381 CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1),
382 Store.getOperand(2), Store.getOperand(3));
383}
384
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000385/// MoveBelowTokenFactor2 - Replace TokenFactor operand with load's chain operand
386/// and move load below the TokenFactor. Replace store's chain operand with
387/// load's chain result. This a version which sinks two loads below token factor.
388/// Look into PreprocessForRMW comments for explanation of transform.
389static void MoveBelowTokenFactor2(SelectionDAG *CurDAG,
390 SDValue Load1, SDValue Load2,
391 SDValue Store, SDValue TF) {
392 SmallVector<SDValue, 4> Ops;
393 for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) {
394 SDNode* N = TF.getOperand(i).getNode();
395 if (Load2.getNode() == N)
396 Ops.push_back(Load2.getOperand(0));
397 else if (Load1.getNode() != N)
398 Ops.push_back(TF.getOperand(i));
399 }
400
401 SDValue NewTF = SDValue(CurDAG->MorphNodeTo(TF.getNode(),
402 TF.getOpcode(),
403 TF.getNode()->getVTList(),
404 &Ops[0], Ops.size()), TF.getResNo());
405 SDValue NewLoad2 = CurDAG->UpdateNodeOperands(Load2, NewTF,
406 Load2.getOperand(1),
407 Load2.getOperand(2));
408
409 SDValue NewLoad1 = CurDAG->UpdateNodeOperands(Load1, NewLoad2.getValue(1),
410 Load1.getOperand(1),
411 Load1.getOperand(2));
412
413 CurDAG->UpdateNodeOperands(Store,
414 NewLoad1.getValue(1),
415 Store.getOperand(1),
416 Store.getOperand(2), Store.getOperand(3));
417}
418
419/// isAllowedToSink - return true if N a load which can be moved below token
420/// factor. Basically, the load should be non-volatile and has single use.
421static bool isLoadAllowedToSink(SDValue N, SDValue Chain) {
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000422 if (N.getOpcode() == ISD::BIT_CONVERT)
423 N = N.getOperand(0);
424
425 LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
426 if (!LD || LD->isVolatile())
427 return false;
428 if (LD->getAddressingMode() != ISD::UNINDEXED)
429 return false;
430
431 ISD::LoadExtType ExtType = LD->getExtensionType();
432 if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD)
433 return false;
434
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000435 return (N.hasOneUse() &&
436 LD->hasNUsesOfValue(1, 1) &&
437 LD->isOperandOf(Chain.getNode()));
438}
439
440
441/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG.
442/// The chain produced by the load must only be used by the store's chain
443/// operand, otherwise this may produce a cycle in the DAG.
444static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
445 SDValue &Load) {
446 if (isLoadAllowedToSink(N, Chain) &&
447 N.getOperand(1) == Address) {
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000448 Load = N;
449 return true;
450 }
451 return false;
452}
453
454/// PreprocessForRMW - Preprocess the DAG to make instruction selection better.
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000455/// This is only run if not in -O0 mode.
456/// This allows the instruction selector to pick more read-modify-write
457/// instructions. This is a common case:
458///
459/// [Load chain]
460/// ^
461/// |
462/// [Load]
463/// ^ ^
464/// | |
465/// / \-
466/// / |
467/// [TokenFactor] [Op]
468/// ^ ^
469/// | |
470/// \ /
471/// \ /
472/// [Store]
473///
474/// The fact the store's chain operand != load's chain will prevent the
475/// (store (op (load))) instruction from being selected. We can transform it to:
476///
477/// [Load chain]
478/// ^
479/// |
480/// [TokenFactor]
481/// ^
482/// |
483/// [Load]
484/// ^ ^
485/// | |
486/// | \-
487/// | |
488/// | [Op]
489/// | ^
490/// | |
491/// \ /
492/// \ /
493/// [Store]
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000494///
495/// We also recognize the case where second operand of Op is load as well and
496/// move it below token factor as well creating DAG as follows:
497///
Benjamin Kramer1395d1d2009-10-22 09:28:49 +0000498/// [Load chain]
499/// ^
500/// |
501/// [TokenFactor]
502/// ^
503/// |
504/// [Load1]
505/// ^ ^
506/// / |
507/// / |
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000508/// [Load2] |
509/// ^ ^ |
510/// | | |
511/// | \-|
512/// | |
513/// | [Op]
514/// | ^
515/// | |
516/// \ /
517/// \ /
518/// [Store]
519///
520/// This allows selection of mem-mem instructions. Yay!
521
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000522void MSP430DAGToDAGISel::PreprocessForRMW() {
Chris Lattnerd1b73822010-03-02 22:20:06 +0000523 return;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000524 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
525 E = CurDAG->allnodes_end(); I != E; ++I) {
526 if (!ISD::isNON_TRUNCStore(I))
527 continue;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000528 SDValue Chain = I->getOperand(0);
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000529
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000530 if (Chain.getNode()->getOpcode() != ISD::TokenFactor)
531 continue;
532
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000533 SDValue N1 = I->getOperand(1);
534 SDValue N2 = I->getOperand(2);
535 if ((N1.getValueType().isFloatingPoint() &&
536 !N1.getValueType().isVector()) ||
537 !N1.hasOneUse())
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000538 continue;
539
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000540 unsigned RModW = 0;
541 SDValue Load1, Load2;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000542 unsigned Opcode = N1.getNode()->getOpcode();
543 switch (Opcode) {
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000544 case ISD::ADD:
545 case ISD::AND:
546 case ISD::OR:
547 case ISD::XOR:
548 case ISD::ADDC:
549 case ISD::ADDE: {
550 SDValue N10 = N1.getOperand(0);
551 SDValue N11 = N1.getOperand(1);
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000552 if (isRMWLoad(N10, Chain, N2, Load1)) {
553 if (isLoadAllowedToSink(N11, Chain)) {
554 Load2 = N11;
555 RModW = 2;
556 } else
557 RModW = 1;
558 } else if (isRMWLoad(N11, Chain, N2, Load1)) {
559 if (isLoadAllowedToSink(N10, Chain)) {
560 Load2 = N10;
561 RModW = 2;
562 } else
563 RModW = 1;
564 }
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000565 break;
566 }
567 case ISD::SUB:
568 case ISD::SUBC:
569 case ISD::SUBE: {
570 SDValue N10 = N1.getOperand(0);
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000571 SDValue N11 = N1.getOperand(1);
572 if (isRMWLoad(N10, Chain, N2, Load1)) {
573 if (isLoadAllowedToSink(N11, Chain)) {
574 Load2 = N11;
575 RModW = 2;
576 } else
577 RModW = 1;
578 }
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000579 break;
580 }
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000581 }
582
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000583 NumLoadMoved += RModW;
584 if (RModW == 1)
585 MoveBelowTokenFactor(CurDAG, Load1, SDValue(I, 0), Chain);
586 else if (RModW == 2) {
587 MoveBelowTokenFactor2(CurDAG, Load1, Load2, SDValue(I, 0), Chain);
588 SDNode* Store = I;
589 RMWStores[Store] = Load2.getNode();
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000590 }
591 }
592}
593
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000594
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000595static bool isValidIndexedLoad(const LoadSDNode *LD) {
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000596 ISD::MemIndexedMode AM = LD->getAddressingMode();
597 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000598 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000599
600 EVT VT = LD->getMemoryVT();
601
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000602 switch (VT.getSimpleVT().SimpleTy) {
603 case MVT::i8:
604 // Sanity check
605 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000606 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000607
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000608 break;
609 case MVT::i16:
610 // Sanity check
611 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000612 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000613
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000614 break;
615 default:
616 return false;
617 }
618
619 return true;
620}
621
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000622SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) {
623 LoadSDNode *LD = cast<LoadSDNode>(N);
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000624 if (!isValidIndexedLoad(LD))
625 return NULL;
626
627 MVT VT = LD->getMemoryVT().getSimpleVT();
628
629 unsigned Opcode = 0;
630 switch (VT.SimpleTy) {
631 case MVT::i8:
632 Opcode = MSP430::MOV8rm_POST;
633 break;
634 case MVT::i16:
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000635 Opcode = MSP430::MOV16rm_POST;
636 break;
637 default:
638 return NULL;
639 }
640
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000641 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(),
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000642 VT, MVT::i16, MVT::Other,
643 LD->getBasePtr(), LD->getChain());
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000644}
645
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000646SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000647 SDValue N1, SDValue N2,
648 unsigned Opc8, unsigned Opc16) {
649 if (N1.getOpcode() == ISD::LOAD &&
650 N1.hasOneUse() &&
Evan Cheng014bf212010-02-15 19:41:07 +0000651 IsLegalToFold(N1, Op, Op)) {
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000652 LoadSDNode *LD = cast<LoadSDNode>(N1);
653 if (!isValidIndexedLoad(LD))
654 return NULL;
655
656 MVT VT = LD->getMemoryVT().getSimpleVT();
657 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
658 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
659 MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
660 SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
661 SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000662 CurDAG->SelectNodeTo(Op, Opc,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000663 VT, MVT::i16, MVT::Other,
664 Ops0, 3);
665 cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000666 // Transfer chain.
667 ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
668 // Transfer writeback.
669 ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000670 return ResNode;
671 }
672
673 return NULL;
674}
675
676
Chris Lattner7c306da2010-03-02 06:34:30 +0000677void MSP430DAGToDAGISel::PreprocessISelDAG() {
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000678 PreprocessForRMW();
Chris Lattner7c306da2010-03-02 06:34:30 +0000679}
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000680
Chris Lattner7c306da2010-03-02 06:34:30 +0000681void MSP430DAGToDAGISel::PostprocessISelDAG() {
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000682 RMWStores.clear();
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000683}
684
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000685SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) {
686 DebugLoc dl = Node->getDebugLoc();
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000687
688 // Dump information about the Node being selected
Chris Lattner7c306da2010-03-02 06:34:30 +0000689 DEBUG(errs() << "Selecting: ");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000690 DEBUG(Node->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000691 DEBUG(errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000692
693 // If we have a custom node, we already have selected!
694 if (Node->isMachineOpcode()) {
Chris Lattner7c306da2010-03-02 06:34:30 +0000695 DEBUG(errs() << "== ";
Chris Lattner893e1c92009-08-23 06:49:22 +0000696 Node->dump(CurDAG);
697 errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000698 return NULL;
699 }
700
Anton Korobeynikov40477312009-05-03 13:10:26 +0000701 // Few custom selection stuff.
702 switch (Node->getOpcode()) {
703 default: break;
704 case ISD::FrameIndex: {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000705 assert(Node->getValueType(0) == MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000706 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
Owen Anderson825b72b2009-08-11 20:47:22 +0000707 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000708 if (Node->hasOneUse())
Owen Anderson825b72b2009-08-11 20:47:22 +0000709 return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
710 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Dan Gohman602b0c82009-09-25 18:54:59 +0000711 return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
712 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Anton Korobeynikov40477312009-05-03 13:10:26 +0000713 }
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000714 case ISD::LOAD:
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000715 if (SDNode *ResNode = SelectIndexedLoad(Node))
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000716 return ResNode;
717 // Other cases are autogenerated.
718 break;
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000719 case ISD::ADD:
720 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000721 SelectIndexedBinOp(Node,
722 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000723 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
724 return ResNode;
725 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000726 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000727 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
728 return ResNode;
729
730 // Other cases are autogenerated.
731 break;
732 case ISD::SUB:
733 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000734 SelectIndexedBinOp(Node,
735 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000736 MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
737 return ResNode;
738
739 // Other cases are autogenerated.
740 break;
741 case ISD::AND:
742 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000743 SelectIndexedBinOp(Node,
744 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000745 MSP430::AND8rm_POST, MSP430::AND16rm_POST))
746 return ResNode;
747 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000748 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000749 MSP430::AND8rm_POST, MSP430::AND16rm_POST))
750 return ResNode;
751
752 // Other cases are autogenerated.
753 break;
754 case ISD::OR:
755 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000756 SelectIndexedBinOp(Node,
757 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000758 MSP430::OR8rm_POST, MSP430::OR16rm_POST))
759 return ResNode;
760 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000761 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000762 MSP430::OR8rm_POST, MSP430::OR16rm_POST))
763 return ResNode;
764
765 // Other cases are autogenerated.
766 break;
767 case ISD::XOR:
768 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000769 SelectIndexedBinOp(Node,
770 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000771 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
772 return ResNode;
773 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000774 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000775 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
776 return ResNode;
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000777
778 // Other cases are autogenerated.
779 break;
Anton Korobeynikov40477312009-05-03 13:10:26 +0000780 }
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000781
782 // Select the default instruction
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000783 SDNode *ResNode = SelectCode(Node);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000784
Chris Lattner7c306da2010-03-02 06:34:30 +0000785 DEBUG(errs() << "=> ");
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000786 if (ResNode == NULL || ResNode == Node)
787 DEBUG(Node->dump(CurDAG));
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000788 else
789 DEBUG(ResNode->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000790 DEBUG(errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000791
792 return ResNode;
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000793}