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