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