LLVM  3.7.0
MSP430ISelDAGToDAG.cpp
Go to the documentation of this file.
1 //===-- 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 "MSP430TargetMachine.h"
22 #include "llvm/IR/CallingConv.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/DerivedTypes.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/Intrinsics.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/Debug.h"
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "msp430-isel"
35 
36 namespace {
37  struct MSP430ISelAddressMode {
38  enum {
39  RegBase,
40  FrameIndexBase
41  } BaseType;
42 
43  struct { // This is really a union, discriminated by BaseType!
44  SDValue Reg;
45  int FrameIndex;
46  } Base;
47 
48  int16_t Disp;
49  const GlobalValue *GV;
50  const Constant *CP;
51  const BlockAddress *BlockAddr;
52  const char *ES;
53  int JT;
54  unsigned Align; // CP alignment.
55 
56  MSP430ISelAddressMode()
57  : BaseType(RegBase), Disp(0), GV(nullptr), CP(nullptr),
58  BlockAddr(nullptr), ES(nullptr), JT(-1), Align(0) {
59  }
60 
61  bool hasSymbolicDisplacement() const {
62  return GV != nullptr || CP != nullptr || ES != nullptr || JT != -1;
63  }
64 
65  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  };
88 }
89 
90 /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
91 /// instructions for SelectionDAG operations.
92 ///
93 namespace {
94  class MSP430DAGToDAGISel : public SelectionDAGISel {
95  public:
96  MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
97  : SelectionDAGISel(TM, OptLevel) {}
98 
99  const char *getPassName() const override {
100  return "MSP430 DAG->DAG Pattern Instruction Selection";
101  }
102 
103  bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
104  bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
105  bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
106 
107  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
108  std::vector<SDValue> &OutOps) override;
109 
110  // Include the pieces autogenerated from the target description.
111  #include "MSP430GenDAGISel.inc"
112 
113  private:
114  SDNode *Select(SDNode *N) override;
115  SDNode *SelectIndexedLoad(SDNode *Op);
116  SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
117  unsigned Opc8, unsigned Opc16);
118 
119  bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
120  };
121 } // end anonymous namespace
122 
123 /// createMSP430ISelDag - This pass converts a legalized DAG into a
124 /// MSP430-specific DAG, ready for instruction scheduling.
125 ///
127  CodeGenOpt::Level OptLevel) {
128  return new MSP430DAGToDAGISel(TM, OptLevel);
129 }
130 
131 
132 /// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
133 /// These wrap things that will resolve down into a symbol reference. If no
134 /// match is possible, this returns true, otherwise it returns false.
135 bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
136  // If the addressing mode already has a symbol as the displacement, we can
137  // never match another symbol.
138  if (AM.hasSymbolicDisplacement())
139  return true;
140 
141  SDValue N0 = N.getOperand(0);
142 
143  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
144  AM.GV = G->getGlobal();
145  AM.Disp += G->getOffset();
146  //AM.SymbolFlags = G->getTargetFlags();
147  } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
148  AM.CP = CP->getConstVal();
149  AM.Align = CP->getAlignment();
150  AM.Disp += CP->getOffset();
151  //AM.SymbolFlags = CP->getTargetFlags();
152  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
153  AM.ES = S->getSymbol();
154  //AM.SymbolFlags = S->getTargetFlags();
155  } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
156  AM.JT = J->getIndex();
157  //AM.SymbolFlags = J->getTargetFlags();
158  } else {
159  AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
160  //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
161  }
162  return false;
163 }
164 
165 /// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
166 /// specified addressing mode without any further recursion.
167 bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
168  // Is the base register already occupied?
169  if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
170  // If so, we cannot select it.
171  return true;
172  }
173 
174  // Default, generate it as a register.
175  AM.BaseType = MSP430ISelAddressMode::RegBase;
176  AM.Base.Reg = N;
177  return false;
178 }
179 
180 bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
181  DEBUG(errs() << "MatchAddress: "; AM.dump());
182 
183  switch (N.getOpcode()) {
184  default: break;
185  case ISD::Constant: {
186  uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
187  AM.Disp += Val;
188  return false;
189  }
190 
191  case MSP430ISD::Wrapper:
192  if (!MatchWrapper(N, AM))
193  return false;
194  break;
195 
196  case ISD::FrameIndex:
197  if (AM.BaseType == MSP430ISelAddressMode::RegBase
198  && AM.Base.Reg.getNode() == nullptr) {
199  AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
200  AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
201  return false;
202  }
203  break;
204 
205  case ISD::ADD: {
206  MSP430ISelAddressMode Backup = AM;
207  if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
208  !MatchAddress(N.getNode()->getOperand(1), AM))
209  return false;
210  AM = Backup;
211  if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
212  !MatchAddress(N.getNode()->getOperand(0), AM))
213  return false;
214  AM = Backup;
215 
216  break;
217  }
218 
219  case ISD::OR:
220  // Handle "X | C" as "X + C" iff X is known to have C bits clear.
221  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
222  MSP430ISelAddressMode Backup = AM;
223  uint64_t Offset = CN->getSExtValue();
224  // Start with the LHS as an addr mode.
225  if (!MatchAddress(N.getOperand(0), AM) &&
226  // Address could not have picked a GV address for the displacement.
227  AM.GV == nullptr &&
228  // Check to see if the LHS & C is zero.
229  CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
230  AM.Disp += Offset;
231  return false;
232  }
233  AM = Backup;
234  }
235  break;
236  }
237 
238  return MatchAddressBase(N, AM);
239 }
240 
241 /// SelectAddr - returns true if it is able pattern match an addressing mode.
242 /// It returns the operands which make up the maximal addressing mode it can
243 /// match by reference.
244 bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
245  SDValue &Base, SDValue &Disp) {
246  MSP430ISelAddressMode AM;
247 
248  if (MatchAddress(N, AM))
249  return false;
250 
251  EVT VT = N.getValueType();
252  if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
253  if (!AM.Base.Reg.getNode())
254  AM.Base.Reg = CurDAG->getRegister(0, VT);
255  }
256 
257  Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
258  ? CurDAG->getTargetFrameIndex(
259  AM.Base.FrameIndex,
260  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()))
261  : AM.Base.Reg;
262 
263  if (AM.GV)
264  Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
265  MVT::i16, AM.Disp,
266  0/*AM.SymbolFlags*/);
267  else if (AM.CP)
268  Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
269  AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
270  else if (AM.ES)
271  Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
272  else if (AM.JT != -1)
273  Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
274  else if (AM.BlockAddr)
275  Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
276  0/*AM.SymbolFlags*/);
277  else
278  Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(N), MVT::i16);
279 
280  return true;
281 }
282 
283 bool MSP430DAGToDAGISel::
284 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
285  std::vector<SDValue> &OutOps) {
286  SDValue Op0, Op1;
287  switch (ConstraintID) {
288  default: return true;
289  case InlineAsm::Constraint_m: // memory
290  if (!SelectAddr(Op, Op0, Op1))
291  return true;
292  break;
293  }
294 
295  OutOps.push_back(Op0);
296  OutOps.push_back(Op1);
297  return false;
298 }
299 
300 static bool isValidIndexedLoad(const LoadSDNode *LD) {
302  if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
303  return false;
304 
305  EVT VT = LD->getMemoryVT();
306 
307  switch (VT.getSimpleVT().SimpleTy) {
308  case MVT::i8:
309  // Sanity check
310  if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
311  return false;
312 
313  break;
314  case MVT::i16:
315  // Sanity check
316  if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
317  return false;
318 
319  break;
320  default:
321  return false;
322  }
323 
324  return true;
325 }
326 
327 SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) {
328  LoadSDNode *LD = cast<LoadSDNode>(N);
329  if (!isValidIndexedLoad(LD))
330  return nullptr;
331 
332  MVT VT = LD->getMemoryVT().getSimpleVT();
333 
334  unsigned Opcode = 0;
335  switch (VT.SimpleTy) {
336  case MVT::i8:
337  Opcode = MSP430::MOV8rm_POST;
338  break;
339  case MVT::i16:
340  Opcode = MSP430::MOV16rm_POST;
341  break;
342  default:
343  return nullptr;
344  }
345 
346  return CurDAG->getMachineNode(Opcode, SDLoc(N),
347  VT, MVT::i16, MVT::Other,
348  LD->getBasePtr(), LD->getChain());
349 }
350 
351 SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
352  SDValue N1, SDValue N2,
353  unsigned Opc8, unsigned Opc16) {
354  if (N1.getOpcode() == ISD::LOAD &&
355  N1.hasOneUse() &&
356  IsLegalToFold(N1, Op, Op, OptLevel)) {
357  LoadSDNode *LD = cast<LoadSDNode>(N1);
358  if (!isValidIndexedLoad(LD))
359  return nullptr;
360 
361  MVT VT = LD->getMemoryVT().getSimpleVT();
362  unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
363  MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
364  MemRefs0[0] = 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  cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
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 ResNode;
374  }
375 
376  return nullptr;
377 }
378 
379 
381  SDLoc dl(Node);
382 
383  // Dump information about the Node being selected
384  DEBUG(errs() << "Selecting: ");
385  DEBUG(Node->dump(CurDAG));
386  DEBUG(errs() << "\n");
387 
388  // If we have a custom node, we already have selected!
389  if (Node->isMachineOpcode()) {
390  DEBUG(errs() << "== ";
391  Node->dump(CurDAG);
392  errs() << "\n");
393  Node->setNodeId(-1);
394  return nullptr;
395  }
396 
397  // Few custom selection stuff.
398  switch (Node->getOpcode()) {
399  default: break;
400  case ISD::FrameIndex: {
401  assert(Node->getValueType(0) == MVT::i16);
402  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
403  SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
404  if (Node->hasOneUse())
405  return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16, TFI,
406  CurDAG->getTargetConstant(0, dl, MVT::i16));
407  return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16, TFI,
408  CurDAG->getTargetConstant(0, dl, MVT::i16));
409  }
410  case ISD::LOAD:
411  if (SDNode *ResNode = SelectIndexedLoad(Node))
412  return ResNode;
413  // Other cases are autogenerated.
414  break;
415  case ISD::ADD:
416  if (SDNode *ResNode =
417  SelectIndexedBinOp(Node,
418  Node->getOperand(0), Node->getOperand(1),
419  MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
420  return ResNode;
421  else if (SDNode *ResNode =
422  SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
423  MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
424  return ResNode;
425 
426  // Other cases are autogenerated.
427  break;
428  case ISD::SUB:
429  if (SDNode *ResNode =
430  SelectIndexedBinOp(Node,
431  Node->getOperand(0), Node->getOperand(1),
432  MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
433  return ResNode;
434 
435  // Other cases are autogenerated.
436  break;
437  case ISD::AND:
438  if (SDNode *ResNode =
439  SelectIndexedBinOp(Node,
440  Node->getOperand(0), Node->getOperand(1),
441  MSP430::AND8rm_POST, MSP430::AND16rm_POST))
442  return ResNode;
443  else if (SDNode *ResNode =
444  SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
445  MSP430::AND8rm_POST, MSP430::AND16rm_POST))
446  return ResNode;
447 
448  // Other cases are autogenerated.
449  break;
450  case ISD::OR:
451  if (SDNode *ResNode =
452  SelectIndexedBinOp(Node,
453  Node->getOperand(0), Node->getOperand(1),
454  MSP430::OR8rm_POST, MSP430::OR16rm_POST))
455  return ResNode;
456  else if (SDNode *ResNode =
457  SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
458  MSP430::OR8rm_POST, MSP430::OR16rm_POST))
459  return ResNode;
460 
461  // Other cases are autogenerated.
462  break;
463  case ISD::XOR:
464  if (SDNode *ResNode =
465  SelectIndexedBinOp(Node,
466  Node->getOperand(0), Node->getOperand(1),
467  MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
468  return ResNode;
469  else if (SDNode *ResNode =
470  SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
471  MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
472  return ResNode;
473 
474  // Other cases are autogenerated.
475  break;
476  }
477 
478  // Select the default instruction
479  SDNode *ResNode = SelectCode(Node);
480 
481  DEBUG(errs() << "=> ");
482  if (ResNode == nullptr || ResNode == Node)
483  DEBUG(Node->dump(CurDAG));
484  else
485  DEBUG(ResNode->dump(CurDAG));
486  DEBUG(errs() << "\n");
487 
488  return ResNode;
489 }
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void dump() const
Dump this node, for debugging.
bool hasOneUse() const
Return true if there is exactly one use of this node.
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
const SDValue & getOperand(unsigned Num) const
void setNodeId(int Id)
Set unique node id.
const SDValue & getBasePtr() const
FunctionPass * createMSP430ISelDag(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
createMSP430ISelDag - This pass converts a legalized DAG into a MSP430-specific DAG, ready for instruction scheduling.
BlockAddress - The address of a basic block.
Definition: Constants.h:802
MachineMemOperand - A description of a memory reference used in the backend.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Reg
All possible values of the reg field in the ModR/M byte.
SimpleValueType SimpleTy
#define G(x, y, z)
Definition: MD5.cpp:52
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:191
EVT getMemoryVT() const
Return the type of the in-memory value.
SDNode * getNode() const
get the SDNode which holds the desired result
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MVT - Machine Value Type.
const SDValue & getOperand(unsigned i) const
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
EVT - Extended Value Type.
Definition: ValueTypes.h:31
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc, or post-dec.
MSP430TargetMachine.
const SDValue & getOffset() const
const SDValue & getChain() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:321
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:518
#define N
static bool isValidIndexedLoad(const LoadSDNode *LD)
Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol, and TargetGlobalAddress.
EVT getValueType() const
Return the ValueType of the referenced return value.
#define DEBUG(X)
Definition: Debug.h:92
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
MVT getSimpleVT() const
getSimpleVT - Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:203
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
This file describes how to lower LLVM code to machine code.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Definition: ISDOpcodes.h:761
This class is used to represent ISD::LOAD nodes.