LLVM  4.0.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/Debug.h"
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "msp430-isel"
34 
35 namespace {
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  void dump() {
65  errs() << "MSP430ISelAddressMode " << this << '\n';
66  if (BaseType == RegBase && Base.Reg.getNode() != nullptr) {
67  errs() << "Base.Reg ";
68  Base.Reg.getNode()->dump();
69  } else if (BaseType == FrameIndexBase) {
70  errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
71  }
72  errs() << " Disp " << Disp << '\n';
73  if (GV) {
74  errs() << "GV ";
75  GV->dump();
76  } else if (CP) {
77  errs() << " CP ";
78  CP->dump();
79  errs() << " Align" << Align << '\n';
80  } else if (ES) {
81  errs() << "ES ";
82  errs() << ES << '\n';
83  } else if (JT != -1)
84  errs() << " JT" << JT << " Align" << Align << '\n';
85  }
86  };
87 }
88 
89 /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
90 /// instructions for SelectionDAG operations.
91 ///
92 namespace {
93  class MSP430DAGToDAGISel : public SelectionDAGISel {
94  public:
95  MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
96  : SelectionDAGISel(TM, OptLevel) {}
97 
98  StringRef getPassName() const override {
99  return "MSP430 DAG->DAG Pattern Instruction Selection";
100  }
101 
102  bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
103  bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
104  bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
105 
106  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
107  std::vector<SDValue> &OutOps) override;
108 
109  // Include the pieces autogenerated from the target description.
110  #include "MSP430GenDAGISel.inc"
111 
112  private:
113  void Select(SDNode *N) override;
114  bool tryIndexedLoad(SDNode *Op);
115  bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8,
116  unsigned Opc16);
117 
118  bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
119  };
120 } // end anonymous namespace
121 
122 /// createMSP430ISelDag - This pass converts a legalized DAG into a
123 /// MSP430-specific DAG, ready for instruction scheduling.
124 ///
126  CodeGenOpt::Level OptLevel) {
127  return new MSP430DAGToDAGISel(TM, OptLevel);
128 }
129 
130 
131 /// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
132 /// These wrap things that will resolve down into a symbol reference. If no
133 /// match is possible, this returns true, otherwise it returns false.
134 bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
135  // If the addressing mode already has a symbol as the displacement, we can
136  // never match another symbol.
137  if (AM.hasSymbolicDisplacement())
138  return true;
139 
140  SDValue N0 = N.getOperand(0);
141 
142  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
143  AM.GV = G->getGlobal();
144  AM.Disp += G->getOffset();
145  //AM.SymbolFlags = G->getTargetFlags();
146  } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
147  AM.CP = CP->getConstVal();
148  AM.Align = CP->getAlignment();
149  AM.Disp += CP->getOffset();
150  //AM.SymbolFlags = CP->getTargetFlags();
151  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
152  AM.ES = S->getSymbol();
153  //AM.SymbolFlags = S->getTargetFlags();
154  } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
155  AM.JT = J->getIndex();
156  //AM.SymbolFlags = J->getTargetFlags();
157  } else {
158  AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
159  //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
160  }
161  return false;
162 }
163 
164 /// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
165 /// specified addressing mode without any further recursion.
166 bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
167  // Is the base register already occupied?
168  if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
169  // If so, we cannot select it.
170  return true;
171  }
172 
173  // Default, generate it as a register.
174  AM.BaseType = MSP430ISelAddressMode::RegBase;
175  AM.Base.Reg = N;
176  return false;
177 }
178 
179 bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
180  DEBUG(errs() << "MatchAddress: "; AM.dump());
181 
182  switch (N.getOpcode()) {
183  default: break;
184  case ISD::Constant: {
185  uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
186  AM.Disp += Val;
187  return false;
188  }
189 
190  case MSP430ISD::Wrapper:
191  if (!MatchWrapper(N, AM))
192  return false;
193  break;
194 
195  case ISD::FrameIndex:
196  if (AM.BaseType == MSP430ISelAddressMode::RegBase
197  && AM.Base.Reg.getNode() == nullptr) {
198  AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
199  AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
200  return false;
201  }
202  break;
203 
204  case ISD::ADD: {
205  MSP430ISelAddressMode Backup = AM;
206  if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
207  !MatchAddress(N.getNode()->getOperand(1), AM))
208  return false;
209  AM = Backup;
210  if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
211  !MatchAddress(N.getNode()->getOperand(0), AM))
212  return false;
213  AM = Backup;
214 
215  break;
216  }
217 
218  case ISD::OR:
219  // Handle "X | C" as "X + C" iff X is known to have C bits clear.
220  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
221  MSP430ISelAddressMode Backup = AM;
222  uint64_t Offset = CN->getSExtValue();
223  // Start with the LHS as an addr mode.
224  if (!MatchAddress(N.getOperand(0), AM) &&
225  // Address could not have picked a GV address for the displacement.
226  AM.GV == nullptr &&
227  // Check to see if the LHS & C is zero.
228  CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
229  AM.Disp += Offset;
230  return false;
231  }
232  AM = Backup;
233  }
234  break;
235  }
236 
237  return MatchAddressBase(N, AM);
238 }
239 
240 /// SelectAddr - returns true if it is able pattern match an addressing mode.
241 /// It returns the operands which make up the maximal addressing mode it can
242 /// match by reference.
243 bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
244  SDValue &Base, SDValue &Disp) {
245  MSP430ISelAddressMode AM;
246 
247  if (MatchAddress(N, AM))
248  return false;
249 
250  EVT VT = N.getValueType();
251  if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
252  if (!AM.Base.Reg.getNode())
253  AM.Base.Reg = CurDAG->getRegister(0, VT);
254  }
255 
256  Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
257  ? CurDAG->getTargetFrameIndex(
258  AM.Base.FrameIndex,
259  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()))
260  : AM.Base.Reg;
261 
262  if (AM.GV)
263  Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
264  MVT::i16, AM.Disp,
265  0/*AM.SymbolFlags*/);
266  else if (AM.CP)
267  Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
268  AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
269  else if (AM.ES)
270  Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
271  else if (AM.JT != -1)
272  Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
273  else if (AM.BlockAddr)
274  Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
275  0/*AM.SymbolFlags*/);
276  else
277  Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(N), MVT::i16);
278 
279  return true;
280 }
281 
282 bool MSP430DAGToDAGISel::
283 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
284  std::vector<SDValue> &OutOps) {
285  SDValue Op0, Op1;
286  switch (ConstraintID) {
287  default: return true;
288  case InlineAsm::Constraint_m: // memory
289  if (!SelectAddr(Op, Op0, Op1))
290  return true;
291  break;
292  }
293 
294  OutOps.push_back(Op0);
295  OutOps.push_back(Op1);
296  return false;
297 }
298 
299 static bool isValidIndexedLoad(const LoadSDNode *LD) {
301  if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
302  return false;
303 
304  EVT VT = LD->getMemoryVT();
305 
306  switch (VT.getSimpleVT().SimpleTy) {
307  case MVT::i8:
308  // Sanity check
309  if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
310  return false;
311 
312  break;
313  case MVT::i16:
314  // Sanity check
315  if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
316  return false;
317 
318  break;
319  default:
320  return false;
321  }
322 
323  return true;
324 }
325 
326 bool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) {
327  LoadSDNode *LD = cast<LoadSDNode>(N);
328  if (!isValidIndexedLoad(LD))
329  return false;
330 
331  MVT VT = LD->getMemoryVT().getSimpleVT();
332 
333  unsigned Opcode = 0;
334  switch (VT.SimpleTy) {
335  case MVT::i8:
336  Opcode = MSP430::MOV8rm_POST;
337  break;
338  case MVT::i16:
339  Opcode = MSP430::MOV16rm_POST;
340  break;
341  default:
342  return false;
343  }
344 
345  ReplaceNode(N,
346  CurDAG->getMachineNode(Opcode, SDLoc(N), VT, MVT::i16, MVT::Other,
347  LD->getBasePtr(), LD->getChain()));
348  return true;
349 }
350 
351 bool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
352  unsigned Opc8, unsigned Opc16) {
353  if (N1.getOpcode() == ISD::LOAD &&
354  N1.hasOneUse() &&
355  IsLegalToFold(N1, Op, Op, OptLevel)) {
356  LoadSDNode *LD = cast<LoadSDNode>(N1);
357  if (!isValidIndexedLoad(LD))
358  return false;
359 
360  MVT VT = LD->getMemoryVT().getSimpleVT();
361  unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
362  MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
363  MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
364  SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
365  SDNode *ResNode =
366  CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
367  cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
368  // Transfer chain.
369  ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
370  // Transfer writeback.
371  ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
372  return true;
373  }
374 
375  return false;
376 }
377 
378 
380  SDLoc dl(Node);
381 
382  // Dump information about the Node being selected
383  DEBUG(errs() << "Selecting: ");
384  DEBUG(Node->dump(CurDAG));
385  DEBUG(errs() << "\n");
386 
387  // If we have a custom node, we already have selected!
388  if (Node->isMachineOpcode()) {
389  DEBUG(errs() << "== ";
390  Node->dump(CurDAG);
391  errs() << "\n");
392  Node->setNodeId(-1);
393  return;
394  }
395 
396  // Few custom selection stuff.
397  switch (Node->getOpcode()) {
398  default: break;
399  case ISD::FrameIndex: {
400  assert(Node->getValueType(0) == MVT::i16);
401  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
402  SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
403  if (Node->hasOneUse()) {
404  CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16, TFI,
405  CurDAG->getTargetConstant(0, dl, MVT::i16));
406  return;
407  }
408  ReplaceNode(Node, CurDAG->getMachineNode(
409  MSP430::ADD16ri, dl, MVT::i16, TFI,
410  CurDAG->getTargetConstant(0, dl, MVT::i16)));
411  return;
412  }
413  case ISD::LOAD:
414  if (tryIndexedLoad(Node))
415  return;
416  // Other cases are autogenerated.
417  break;
418  case ISD::ADD:
419  if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
420  MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
421  return;
422  else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
423  MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
424  return;
425 
426  // Other cases are autogenerated.
427  break;
428  case ISD::SUB:
429  if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
430  MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
431  return;
432 
433  // Other cases are autogenerated.
434  break;
435  case ISD::AND:
436  if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
437  MSP430::AND8rm_POST, MSP430::AND16rm_POST))
438  return;
439  else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
440  MSP430::AND8rm_POST, MSP430::AND16rm_POST))
441  return;
442 
443  // Other cases are autogenerated.
444  break;
445  case ISD::OR:
446  if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
447  MSP430::OR8rm_POST, MSP430::OR16rm_POST))
448  return;
449  else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
450  MSP430::OR8rm_POST, MSP430::OR16rm_POST))
451  return;
452 
453  // Other cases are autogenerated.
454  break;
455  case ISD::XOR:
456  if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
457  MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
458  return;
459  else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
460  MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
461  return;
462 
463  // Other cases are autogenerated.
464  break;
465  }
466 
467  // Select the default instruction
468  SelectCode(Node);
469 }
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
The address of a basic block.
Definition: Constants.h:822
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
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
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:42
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint32_t Offset
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
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
void dump() const
Dump this node, for debugging.
const DataFlowGraph & G
Definition: RDFGraph.cpp:206
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...
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:333
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:536
#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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define DEBUG(X)
Definition: Debug.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
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:226
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:799
This class is used to represent ISD::LOAD nodes.