blob: 37a6107c25cc6c62b4bd67f8b53abbb583db8071 [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"
Anton Korobeynikova91f4c52009-10-21 19:18:28 +000029#include "llvm/Support/CommandLine.h"
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000030#include "llvm/Support/Compiler.h"
31#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000032#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/raw_ostream.h"
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +000034#include "llvm/ADT/Statistic.h"
35
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000036using namespace llvm;
37
Anton Korobeynikova91f4c52009-10-21 19:18:28 +000038#ifndef NDEBUG
39static cl::opt<bool>
40ViewRMWDAGs("view-msp430-rmw-dags", cl::Hidden,
41 cl::desc("Pop up a window to show isel dags after RMW preprocess"));
42#else
43static const bool ViewRMWDAGs = false;
44#endif
45
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +000046STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
47
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000048
49namespace {
50 struct MSP430ISelAddressMode {
51 enum {
52 RegBase,
53 FrameIndexBase
54 } BaseType;
55
56 struct { // This is really a union, discriminated by BaseType!
57 SDValue Reg;
58 int FrameIndex;
59 } Base;
60
61 int16_t Disp;
62 GlobalValue *GV;
63 Constant *CP;
64 BlockAddress *BlockAddr;
65 const char *ES;
66 int JT;
67 unsigned Align; // CP alignment.
68
69 MSP430ISelAddressMode()
70 : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0),
71 ES(0), JT(-1), Align(0) {
72 }
73
74 bool hasSymbolicDisplacement() const {
75 return GV != 0 || CP != 0 || ES != 0 || JT != -1;
76 }
77
78 bool hasBaseReg() const {
79 return Base.Reg.getNode() != 0;
80 }
81
82 void setBaseReg(SDValue Reg) {
83 BaseType = RegBase;
84 Base.Reg = Reg;
85 }
86
87 void dump() {
88 errs() << "MSP430ISelAddressMode " << this << '\n';
89 if (Base.Reg.getNode() != 0) {
90 errs() << "Base.Reg ";
91 Base.Reg.getNode()->dump();
92 } else {
93 errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
94 }
95 errs() << " Disp " << Disp << '\n';
96 if (GV) {
97 errs() << "GV ";
98 GV->dump();
99 } else if (CP) {
100 errs() << " CP ";
101 CP->dump();
102 errs() << " Align" << Align << '\n';
103 } else if (ES) {
104 errs() << "ES ";
105 errs() << ES << '\n';
106 } else if (JT != -1)
107 errs() << " JT" << JT << " Align" << Align << '\n';
108 }
109 };
110}
111
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000112/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
113/// instructions for SelectionDAG operations.
114///
115namespace {
116 class MSP430DAGToDAGISel : public SelectionDAGISel {
117 MSP430TargetLowering &Lowering;
118 const MSP430Subtarget &Subtarget;
119
120 public:
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000121 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
122 : SelectionDAGISel(TM, OptLevel),
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000123 Lowering(*TM.getTargetLowering()),
124 Subtarget(*TM.getSubtargetImpl()) { }
125
126 virtual void InstructionSelect();
127
128 virtual const char *getPassName() const {
129 return "MSP430 DAG->DAG Pattern Instruction Selection";
130 }
131
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000132 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
133 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
134 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
135
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000136 bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
137 SDNode *Root) const;
138
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000139 virtual bool
140 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
141 std::vector<SDValue> &OutOps);
142
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000143 // Include the pieces autogenerated from the target description.
144 #include "MSP430GenDAGISel.inc"
145
146 private:
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000147 DenseMap<SDNode*, SDNode*> RMWStores;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000148 void PreprocessForRMW();
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000149 SDNode *Select(SDValue Op);
Anton Korobeynikovcf14ae52009-05-03 13:09:40 +0000150 bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000151
152 #ifndef NDEBUG
153 unsigned Indent;
154 #endif
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000155 };
156} // end anonymous namespace
157
158/// createMSP430ISelDag - This pass converts a legalized DAG into a
159/// MSP430-specific DAG, ready for instruction scheduling.
160///
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000161FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
162 CodeGenOpt::Level OptLevel) {
163 return new MSP430DAGToDAGISel(TM, OptLevel);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000164}
165
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000166
167/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
168/// These wrap things that will resolve down into a symbol reference. If no
169/// match is possible, this returns true, otherwise it returns false.
170bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
171 // If the addressing mode already has a symbol as the displacement, we can
172 // never match another symbol.
173 if (AM.hasSymbolicDisplacement())
174 return true;
175
176 SDValue N0 = N.getOperand(0);
177
178 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
179 AM.GV = G->getGlobal();
180 AM.Disp += G->getOffset();
181 //AM.SymbolFlags = G->getTargetFlags();
182 } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
183 AM.CP = CP->getConstVal();
184 AM.Align = CP->getAlignment();
185 AM.Disp += CP->getOffset();
186 //AM.SymbolFlags = CP->getTargetFlags();
187 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
188 AM.ES = S->getSymbol();
189 //AM.SymbolFlags = S->getTargetFlags();
190 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
191 AM.JT = J->getIndex();
192 //AM.SymbolFlags = J->getTargetFlags();
193 } else {
194 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
195 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
196 }
197 return false;
198}
199
200/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
201/// specified addressing mode without any further recursion.
202bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
203 // Is the base register already occupied?
204 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
205 // If so, we cannot select it.
Anton Korobeynikov82e46c22009-05-03 13:10:11 +0000206 return true;
207 }
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000208
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000209 // Default, generate it as a register.
210 AM.BaseType = MSP430ISelAddressMode::RegBase;
211 AM.Base.Reg = N;
212 return false;
213}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000214
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000215bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
216 DebugLoc dl = N.getDebugLoc();
217 DEBUG({
218 errs() << "MatchAddress: ";
219 AM.dump();
220 });
221
222 switch (N.getOpcode()) {
223 default: break;
224 case ISD::Constant: {
225 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
226 AM.Disp += Val;
227 return false;
228 }
229
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000230 case MSP430ISD::Wrapper:
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000231 if (!MatchWrapper(N, AM))
232 return false;
233 break;
234
235 case ISD::FrameIndex:
236 if (AM.BaseType == MSP430ISelAddressMode::RegBase
237 && AM.Base.Reg.getNode() == 0) {
238 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
239 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
240 return false;
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000241 }
242 break;
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000243
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000244 case ISD::ADD: {
245 MSP430ISelAddressMode Backup = AM;
246 if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
247 !MatchAddress(N.getNode()->getOperand(1), AM))
248 return false;
249 AM = Backup;
250 if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
251 !MatchAddress(N.getNode()->getOperand(0), AM))
252 return false;
253 AM = Backup;
254
255 break;
256 }
257
258 case ISD::OR:
259 // Handle "X | C" as "X + C" iff X is known to have C bits clear.
260 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
261 MSP430ISelAddressMode Backup = AM;
262 uint64_t Offset = CN->getSExtValue();
263 // Start with the LHS as an addr mode.
264 if (!MatchAddress(N.getOperand(0), AM) &&
265 // Address could not have picked a GV address for the displacement.
266 AM.GV == NULL &&
267 // Check to see if the LHS & C is zero.
268 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
269 AM.Disp += Offset;
270 return false;
271 }
272 AM = Backup;
273 }
274 break;
275 }
276
277 return MatchAddressBase(N, AM);
278}
279
280/// SelectAddr - returns true if it is able pattern match an addressing mode.
281/// It returns the operands which make up the maximal addressing mode it can
282/// match by reference.
283bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue N,
284 SDValue &Base, SDValue &Disp) {
285 MSP430ISelAddressMode AM;
286
287 if (MatchAddress(N, AM))
288 return false;
289
290 EVT VT = N.getValueType();
291 if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
292 if (!AM.Base.Reg.getNode())
293 AM.Base.Reg = CurDAG->getRegister(0, VT);
294 }
295
296 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ?
297 CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy()) :
298 AM.Base.Reg;
299
300 if (AM.GV)
301 Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i16, AM.Disp,
302 0/*AM.SymbolFlags*/);
303 else if (AM.CP)
304 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
305 AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
306 else if (AM.ES)
307 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
308 else if (AM.JT != -1)
309 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
310 else if (AM.BlockAddr)
311 Disp = CurDAG->getBlockAddress(AM.BlockAddr, DebugLoc()/*MVT::i32*/,
312 true /*AM.SymbolFlags*/);
313 else
314 Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000315
316 return true;
317}
318
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000319bool MSP430DAGToDAGISel::
320SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
321 std::vector<SDValue> &OutOps) {
322 SDValue Op0, Op1;
323 switch (ConstraintCode) {
324 default: return true;
325 case 'm': // memory
326 if (!SelectAddr(Op, Op, Op0, Op1))
327 return true;
328 break;
329 }
330
331 OutOps.push_back(Op0);
332 OutOps.push_back(Op1);
333 return false;
334}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000335
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000336bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
337 SDNode *Root) const {
338 if (OptLevel == CodeGenOpt::None) return false;
339
340 /// RMW preprocessing creates the following code:
Benjamin Kramer1395d1d2009-10-22 09:28:49 +0000341 /// [Load1]
342 /// ^ ^
343 /// / |
344 /// / |
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000345 /// [Load2] |
346 /// ^ ^ |
347 /// | | |
348 /// | \-|
349 /// | |
350 /// | [Op]
351 /// | ^
352 /// | |
353 /// \ /
354 /// \ /
355 /// [Store]
356 ///
357 /// The path Store => Load2 => Load1 is via chain. Note that in general it is
358 /// not allowed to fold Load1 into Op (and Store) since it will creates a
359 /// cycle. However, this is perfectly legal for the loads moved below the
360 /// TokenFactor by PreprocessForRMW. Query the map Store => Load1 (created
361 /// during preprocessing) to determine whether it's legal to introduce such
362 /// "cycle" for a moment.
363 DenseMap<SDNode*, SDNode*>::iterator I = RMWStores.find(Root);
364 if (I != RMWStores.end() && I->second == N)
365 return true;
366
367 // Proceed to 'generic' cycle finder code
368 return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
369}
370
371
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000372/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
373/// and move load below the TokenFactor. Replace store's chain operand with
374/// load's chain result.
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000375static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
376 SDValue Store, SDValue TF) {
377 SmallVector<SDValue, 4> Ops;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000378 for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i)
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000379 if (Load.getNode() == TF.getOperand(i).getNode())
380 Ops.push_back(Load.getOperand(0));
381 else
382 Ops.push_back(TF.getOperand(i));
383 SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size());
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000384 SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF,
385 Load.getOperand(1),
386 Load.getOperand(2));
387 CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1),
388 Store.getOperand(2), Store.getOperand(3));
389}
390
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000391/// MoveBelowTokenFactor2 - Replace TokenFactor operand with load's chain operand
392/// and move load below the TokenFactor. Replace store's chain operand with
393/// load's chain result. This a version which sinks two loads below token factor.
394/// Look into PreprocessForRMW comments for explanation of transform.
395static void MoveBelowTokenFactor2(SelectionDAG *CurDAG,
396 SDValue Load1, SDValue Load2,
397 SDValue Store, SDValue TF) {
398 SmallVector<SDValue, 4> Ops;
399 for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) {
400 SDNode* N = TF.getOperand(i).getNode();
401 if (Load2.getNode() == N)
402 Ops.push_back(Load2.getOperand(0));
403 else if (Load1.getNode() != N)
404 Ops.push_back(TF.getOperand(i));
405 }
406
407 SDValue NewTF = SDValue(CurDAG->MorphNodeTo(TF.getNode(),
408 TF.getOpcode(),
409 TF.getNode()->getVTList(),
410 &Ops[0], Ops.size()), TF.getResNo());
411 SDValue NewLoad2 = CurDAG->UpdateNodeOperands(Load2, NewTF,
412 Load2.getOperand(1),
413 Load2.getOperand(2));
414
415 SDValue NewLoad1 = CurDAG->UpdateNodeOperands(Load1, NewLoad2.getValue(1),
416 Load1.getOperand(1),
417 Load1.getOperand(2));
418
419 CurDAG->UpdateNodeOperands(Store,
420 NewLoad1.getValue(1),
421 Store.getOperand(1),
422 Store.getOperand(2), Store.getOperand(3));
423}
424
425/// isAllowedToSink - return true if N a load which can be moved below token
426/// factor. Basically, the load should be non-volatile and has single use.
427static bool isLoadAllowedToSink(SDValue N, SDValue Chain) {
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000428 if (N.getOpcode() == ISD::BIT_CONVERT)
429 N = N.getOperand(0);
430
431 LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
432 if (!LD || LD->isVolatile())
433 return false;
434 if (LD->getAddressingMode() != ISD::UNINDEXED)
435 return false;
436
437 ISD::LoadExtType ExtType = LD->getExtensionType();
438 if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD)
439 return false;
440
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000441 return (N.hasOneUse() &&
442 LD->hasNUsesOfValue(1, 1) &&
443 LD->isOperandOf(Chain.getNode()));
444}
445
446
447/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG.
448/// The chain produced by the load must only be used by the store's chain
449/// operand, otherwise this may produce a cycle in the DAG.
450static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
451 SDValue &Load) {
452 if (isLoadAllowedToSink(N, Chain) &&
453 N.getOperand(1) == Address) {
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000454 Load = N;
455 return true;
456 }
457 return false;
458}
459
460/// PreprocessForRMW - Preprocess the DAG to make instruction selection better.
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000461/// This is only run if not in -O0 mode.
462/// This allows the instruction selector to pick more read-modify-write
463/// instructions. This is a common case:
464///
465/// [Load chain]
466/// ^
467/// |
468/// [Load]
469/// ^ ^
470/// | |
471/// / \-
472/// / |
473/// [TokenFactor] [Op]
474/// ^ ^
475/// | |
476/// \ /
477/// \ /
478/// [Store]
479///
480/// The fact the store's chain operand != load's chain will prevent the
481/// (store (op (load))) instruction from being selected. We can transform it to:
482///
483/// [Load chain]
484/// ^
485/// |
486/// [TokenFactor]
487/// ^
488/// |
489/// [Load]
490/// ^ ^
491/// | |
492/// | \-
493/// | |
494/// | [Op]
495/// | ^
496/// | |
497/// \ /
498/// \ /
499/// [Store]
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000500///
501/// We also recognize the case where second operand of Op is load as well and
502/// move it below token factor as well creating DAG as follows:
503///
Benjamin Kramer1395d1d2009-10-22 09:28:49 +0000504/// [Load chain]
505/// ^
506/// |
507/// [TokenFactor]
508/// ^
509/// |
510/// [Load1]
511/// ^ ^
512/// / |
513/// / |
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000514/// [Load2] |
515/// ^ ^ |
516/// | | |
517/// | \-|
518/// | |
519/// | [Op]
520/// | ^
521/// | |
522/// \ /
523/// \ /
524/// [Store]
525///
526/// This allows selection of mem-mem instructions. Yay!
527
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000528void MSP430DAGToDAGISel::PreprocessForRMW() {
529 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
530 E = CurDAG->allnodes_end(); I != E; ++I) {
531 if (!ISD::isNON_TRUNCStore(I))
532 continue;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000533 SDValue Chain = I->getOperand(0);
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000534
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000535 if (Chain.getNode()->getOpcode() != ISD::TokenFactor)
536 continue;
537
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000538 SDValue N1 = I->getOperand(1);
539 SDValue N2 = I->getOperand(2);
540 if ((N1.getValueType().isFloatingPoint() &&
541 !N1.getValueType().isVector()) ||
542 !N1.hasOneUse())
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000543 continue;
544
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000545 unsigned RModW = 0;
546 SDValue Load1, Load2;
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000547 unsigned Opcode = N1.getNode()->getOpcode();
548 switch (Opcode) {
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000549 case ISD::ADD:
550 case ISD::AND:
551 case ISD::OR:
552 case ISD::XOR:
553 case ISD::ADDC:
554 case ISD::ADDE: {
555 SDValue N10 = N1.getOperand(0);
556 SDValue N11 = N1.getOperand(1);
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000557 if (isRMWLoad(N10, Chain, N2, Load1)) {
558 if (isLoadAllowedToSink(N11, Chain)) {
559 Load2 = N11;
560 RModW = 2;
561 } else
562 RModW = 1;
563 } else if (isRMWLoad(N11, Chain, N2, Load1)) {
564 if (isLoadAllowedToSink(N10, Chain)) {
565 Load2 = N10;
566 RModW = 2;
567 } else
568 RModW = 1;
569 }
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000570 break;
571 }
572 case ISD::SUB:
573 case ISD::SUBC:
574 case ISD::SUBE: {
575 SDValue N10 = N1.getOperand(0);
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000576 SDValue N11 = N1.getOperand(1);
577 if (isRMWLoad(N10, Chain, N2, Load1)) {
578 if (isLoadAllowedToSink(N11, Chain)) {
579 Load2 = N11;
580 RModW = 2;
581 } else
582 RModW = 1;
583 }
Anton Korobeynikov83fceb92009-10-21 19:17:55 +0000584 break;
585 }
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000586 }
587
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000588 NumLoadMoved += RModW;
589 if (RModW == 1)
590 MoveBelowTokenFactor(CurDAG, Load1, SDValue(I, 0), Chain);
591 else if (RModW == 2) {
592 MoveBelowTokenFactor2(CurDAG, Load1, Load2, SDValue(I, 0), Chain);
593 SDNode* Store = I;
594 RMWStores[Store] = Load2.getNode();
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000595 }
596 }
597}
598
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000599/// InstructionSelect - This callback is invoked by
600/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
Anton Korobeynikov9e123392009-05-03 12:58:40 +0000601void MSP430DAGToDAGISel::InstructionSelect() {
Anton Korobeynikova91f4c52009-10-21 19:18:28 +0000602 std::string BlockName;
603 if (ViewRMWDAGs)
604 BlockName = MF->getFunction()->getNameStr() + ":" +
605 BB->getBasicBlock()->getNameStr();
606
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000607 PreprocessForRMW();
608
Anton Korobeynikova91f4c52009-10-21 19:18:28 +0000609 if (ViewRMWDAGs) CurDAG->viewGraph("RMW preprocessed:" + BlockName);
610
Anton Korobeynikovafac8ab2009-10-11 23:03:28 +0000611 DEBUG(errs() << "Selection DAG after RMW preprocessing:\n");
612 DEBUG(CurDAG->dump());
613
Anton Korobeynikovbf8ef3f2009-05-03 13:16:37 +0000614 // Codegen the basic block.
Chris Lattner893e1c92009-08-23 06:49:22 +0000615 DEBUG(errs() << "===== Instruction selection begins:\n");
Daniel Dunbar43ed2672009-08-23 08:50:52 +0000616 DEBUG(Indent = 0);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000617 SelectRoot(*CurDAG);
Chris Lattner893e1c92009-08-23 06:49:22 +0000618 DEBUG(errs() << "===== Instruction selection ends:\n");
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000619
620 CurDAG->RemoveDeadNodes();
Anton Korobeynikovf32df4c2009-10-22 00:16:00 +0000621 RMWStores.clear();
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000622}
623
624SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000625 SDNode *Node = Op.getNode();
Anton Korobeynikov40477312009-05-03 13:10:26 +0000626 DebugLoc dl = Op.getDebugLoc();
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000627
628 // Dump information about the Node being selected
Chris Lattner893e1c92009-08-23 06:49:22 +0000629 DEBUG(errs().indent(Indent) << "Selecting: ");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000630 DEBUG(Node->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000631 DEBUG(errs() << "\n");
Daniel Dunbar43ed2672009-08-23 08:50:52 +0000632 DEBUG(Indent += 2);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000633
634 // If we have a custom node, we already have selected!
635 if (Node->isMachineOpcode()) {
Chris Lattner893e1c92009-08-23 06:49:22 +0000636 DEBUG(errs().indent(Indent-2) << "== ";
637 Node->dump(CurDAG);
638 errs() << "\n");
Daniel Dunbar43ed2672009-08-23 08:50:52 +0000639 DEBUG(Indent -= 2);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000640 return NULL;
641 }
642
Anton Korobeynikov40477312009-05-03 13:10:26 +0000643 // Few custom selection stuff.
644 switch (Node->getOpcode()) {
645 default: break;
646 case ISD::FrameIndex: {
Owen Anderson825b72b2009-08-11 20:47:22 +0000647 assert(Op.getValueType() == MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000648 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
Owen Anderson825b72b2009-08-11 20:47:22 +0000649 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000650 if (Node->hasOneUse())
Owen Anderson825b72b2009-08-11 20:47:22 +0000651 return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
652 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Dan Gohman602b0c82009-09-25 18:54:59 +0000653 return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
654 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Anton Korobeynikov40477312009-05-03 13:10:26 +0000655 }
656 }
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000657
658 // Select the default instruction
659 SDNode *ResNode = SelectCode(Op);
660
Chris Lattner893e1c92009-08-23 06:49:22 +0000661 DEBUG(errs() << std::string(Indent-2, ' ') << "=> ");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000662 if (ResNode == NULL || ResNode == Op.getNode())
663 DEBUG(Op.getNode()->dump(CurDAG));
664 else
665 DEBUG(ResNode->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000666 DEBUG(errs() << "\n");
Daniel Dunbar43ed2672009-08-23 08:50:52 +0000667 DEBUG(Indent -= 2);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000668
669 return ResNode;
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000670}