LLVM  4.0.0
LanaiISelDAGToDAG.cpp
Go to the documentation of this file.
1 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
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 Lanai target.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Lanai.h"
16 #include "LanaiRegisterInfo.h"
17 #include "LanaiSubtarget.h"
18 #include "LanaiTargetMachine.h"
25 #include "llvm/IR/CFG.h"
26 #include "llvm/IR/GlobalValue.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Debug.h"
34 
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "lanai-isel"
38 
39 //===----------------------------------------------------------------------===//
40 // Instruction Selector Implementation
41 //===----------------------------------------------------------------------===//
42 
43 //===----------------------------------------------------------------------===//
44 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
45 // instructions for SelectionDAG operations.
46 //===----------------------------------------------------------------------===//
47 namespace {
48 
49 class LanaiDAGToDAGISel : public SelectionDAGISel {
50 public:
51  explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
52  : SelectionDAGISel(TargetMachine) {}
53 
54  bool runOnMachineFunction(MachineFunction &MF) override {
56  }
57 
58  // Pass Name
59  StringRef getPassName() const override {
60  return "Lanai DAG->DAG Pattern Instruction Selection";
61  }
62 
63  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
64  std::vector<SDValue> &OutOps) override;
65 
66 private:
67 // Include the pieces autogenerated from the target description.
68 #include "LanaiGenDAGISel.inc"
69 
70  // Instruction Selection not handled by the auto-generated tablgen
71  void Select(SDNode *N) override;
72 
73  // Support functions for the opcodes of Instruction Selection
74  // not handled by the auto-generated tablgen
75  void selectFrameIndex(SDNode *N);
76 
77  // Complex Pattern for address selection.
78  bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,
79  SDValue &AluOp);
80  bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);
81  bool selectAddrSls(SDValue Addr, SDValue &Offset);
82  bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
83  SDValue &AluOp);
84 
85  // getI32Imm - Return a target constant with the specified value, of type i32.
86  inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) {
87  return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
88  }
89 
90 private:
91  bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
92  SDValue &AluOp, bool RiMode);
93 };
94 
95 bool canBeRepresentedAsSls(const ConstantSDNode &CN) {
96  // Fits in 21-bit signed immediate and two low-order bits are zero.
97  return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);
98 }
99 
100 } // namespace
101 
102 // Helper functions for ComplexPattern used on LanaiInstrInfo
103 // Used on Lanai Load/Store instructions.
104 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
105  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
106  SDLoc DL(Addr);
107  // Loading from a constant address.
108  if (canBeRepresentedAsSls(*CN)) {
109  int32_t Imm = CN->getSExtValue();
110  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
111  return true;
112  }
113  }
114  if (Addr.getOpcode() == ISD::OR &&
115  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
116  Offset = Addr.getOperand(1).getOperand(0);
117  return true;
118  }
119  return false;
120 }
121 
122 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
123  SDValue &Offset, SDValue &AluOp,
124  bool RiMode) {
125  SDLoc DL(Addr);
126 
127  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
128  if (RiMode) {
129  // Fits in 16-bit signed immediate.
130  if (isInt<16>(CN->getSExtValue())) {
131  int16_t Imm = CN->getSExtValue();
132  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
133  Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
134  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
135  return true;
136  }
137  // Allow SLS to match if the constant doesn't fit in 16 bits but can be
138  // represented as an SLS.
139  if (canBeRepresentedAsSls(*CN))
140  return false;
141  } else {
142  // Fits in 10-bit signed immediate.
143  if (isInt<10>(CN->getSExtValue())) {
144  int16_t Imm = CN->getSExtValue();
145  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
146  Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
147  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
148  return true;
149  }
150  }
151  }
152 
153  // if Address is FI, get the TargetFrameIndex.
154  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
155  Base = CurDAG->getTargetFrameIndex(
156  FIN->getIndex(),
157  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
158  Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
159  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
160  return true;
161  }
162 
163  // Skip direct calls
164  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
166  return false;
167 
168  // Address of the form imm + reg
169  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
170  if (AluOperator == ISD::ADD) {
171  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
172  // Addresses of the form FI+const
173  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
174  if ((RiMode && isInt<16>(CN->getSExtValue())) ||
175  (!RiMode && isInt<10>(CN->getSExtValue()))) {
176  // If the first operand is a FI, get the TargetFI Node
177  if (FrameIndexSDNode *FIN =
178  dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
179  Base = CurDAG->getTargetFrameIndex(
180  FIN->getIndex(),
181  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
182  } else {
183  Base = Addr.getOperand(0);
184  }
185 
186  Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
187  return true;
188  }
189  }
190 
191  // Let SLS match SMALL instead of RI.
192  if (AluOperator == ISD::OR && RiMode &&
193  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
194  return false;
195 
196  Base = Addr;
197  Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
198  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
199  return true;
200 }
201 
202 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
203  SDValue &Offset, SDValue &AluOp) {
204  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true);
205 }
206 
207 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
208  SDValue &Offset, SDValue &AluOp) {
209  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
210 }
211 
212 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
213  SDValue &AluOp) {
214  // if Address is FI, get the TargetFrameIndex.
215  if (Addr.getOpcode() == ISD::FrameIndex)
216  return false;
217 
218  // Skip direct calls
219  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
221  return false;
222 
223  // Address of the form OP + OP
224  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
226  if (AluCode != LPAC::UNKNOWN) {
227  // Skip addresses of the form FI OP const
228  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
229  if (isInt<16>(CN->getSExtValue()))
230  return false;
231 
232  // Skip addresses with hi/lo operands
233  if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
234  Addr.getOperand(0).getOpcode() == LanaiISD::LO ||
235  Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||
236  Addr.getOperand(1).getOpcode() == LanaiISD::HI ||
237  Addr.getOperand(1).getOpcode() == LanaiISD::LO ||
238  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
239  return false;
240 
241  // Addresses of the form register OP register
242  R1 = Addr.getOperand(0);
243  R2 = Addr.getOperand(1);
244  AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
245  return true;
246  }
247 
248  // Skip addresses with zero offset
249  return false;
250 }
251 
252 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
253  const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
254  SDValue Op0, Op1, AluOp;
255  switch (ConstraintCode) {
256  default:
257  return true;
258  case InlineAsm::Constraint_m: // memory
259  if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
260  !selectAddrRi(Op, Op0, Op1, AluOp))
261  return true;
262  break;
263  }
264 
265  OutOps.push_back(Op0);
266  OutOps.push_back(Op1);
267  OutOps.push_back(AluOp);
268  return false;
269 }
270 
271 // Select instructions not customized! Used for
272 // expanded, promoted and normal instructions
273 void LanaiDAGToDAGISel::Select(SDNode *Node) {
274  unsigned Opcode = Node->getOpcode();
275 
276  // Dump information about the Node being selected
277  DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
278 
279  // If we have a custom node, we already have selected!
280  if (Node->isMachineOpcode()) {
281  DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
282  return;
283  }
284 
285  // Instruction Selection not handled by the auto-generated tablegen selection
286  // should be handled here.
287  EVT VT = Node->getValueType(0);
288  switch (Opcode) {
289  case ISD::Constant:
290  if (VT == MVT::i32) {
291  ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);
292  // Materialize zero constants as copies from R0. This allows the coalescer
293  // to propagate these into other instructions.
294  if (ConstNode->isNullValue()) {
295  SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
296  SDLoc(Node), Lanai::R0, MVT::i32);
297  return ReplaceNode(Node, New.getNode());
298  }
299  // Materialize all ones constants as copies from R1. This allows the
300  // coalescer to propagate these into other instructions.
301  if (ConstNode->isAllOnesValue()) {
302  SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
303  SDLoc(Node), Lanai::R1, MVT::i32);
304  return ReplaceNode(Node, New.getNode());
305  }
306  }
307  break;
308  case ISD::FrameIndex:
309  selectFrameIndex(Node);
310  return;
311  default:
312  break;
313  }
314 
315  // Select the default instruction
316  SelectCode(Node);
317 }
318 
319 void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {
320  SDLoc DL(Node);
321  SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);
322  int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
323  EVT VT = Node->getValueType(0);
324  SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
325  unsigned Opc = Lanai::ADD_I_LO;
326  if (Node->hasOneUse()) {
327  CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);
328  return;
329  }
330  ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm));
331 }
332 
333 // createLanaiISelDag - This pass converts a legalized DAG into a
334 // Lanai-specific DAG, ready for instruction scheduling.
336  return new LanaiDAGToDAGISel(TM);
337 }
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.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:131
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:271
#define R2(n)
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition: ISDOpcodes.h:39
bool isAllOnesValue() const
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
SDNode * getNode() const
get the SDNode which holds the desired result
const SDValue & getOperand(unsigned i) const
uint32_t Offset
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
FunctionPass * createLanaiISelDag(LanaiTargetMachine &TM)
EVT - Extended Value Type.
Definition: ValueTypes.h:31
void dump() const
Dump this node, for debugging.
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...
int64_t getSExtValue() const
#define N
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
#define DEBUG(X)
Definition: Debug.h:100
Primary interface to the complete machine description for the target machine.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static AluCode isdToLanaiAluCode(ISD::NodeType Node_type)
Definition: LanaiAluCode.h:119
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...