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