LLVM  8.0.1
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  // If we have a custom node, we already have selected!
277  if (Node->isMachineOpcode()) {
278  LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
279  return;
280  }
281 
282  // Instruction Selection not handled by the auto-generated tablegen selection
283  // should be handled here.
284  EVT VT = Node->getValueType(0);
285  switch (Opcode) {
286  case ISD::Constant:
287  if (VT == MVT::i32) {
288  ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);
289  // Materialize zero constants as copies from R0. This allows the coalescer
290  // to propagate these into other instructions.
291  if (ConstNode->isNullValue()) {
292  SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
293  SDLoc(Node), Lanai::R0, MVT::i32);
294  return ReplaceNode(Node, New.getNode());
295  }
296  // Materialize all ones constants as copies from R1. This allows the
297  // coalescer to propagate these into other instructions.
298  if (ConstNode->isAllOnesValue()) {
299  SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
300  SDLoc(Node), Lanai::R1, MVT::i32);
301  return ReplaceNode(Node, New.getNode());
302  }
303  }
304  break;
305  case ISD::FrameIndex:
306  selectFrameIndex(Node);
307  return;
308  default:
309  break;
310  }
311 
312  // Select the default instruction
313  SelectCode(Node);
314 }
315 
316 void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {
317  SDLoc DL(Node);
318  SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);
319  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
320  EVT VT = Node->getValueType(0);
321  SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
322  unsigned Opc = Lanai::ADD_I_LO;
323  if (Node->hasOneUse()) {
324  CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);
325  return;
326  }
327  ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm));
328 }
329 
330 // createLanaiISelDag - This pass converts a legalized DAG into a
331 // Lanai-specific DAG, ready for instruction scheduling.
333  return new LanaiDAGToDAGISel(TM);
334 }
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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:306
SDNode * getNode() const
get the SDNode which holds the desired result
#define R2(n)
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition: ISDOpcodes.h:39
bool hasOneUse() const
Return true if there is exactly one use of this node.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
int64_t getSExtValue() const
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:201
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
FunctionPass * createLanaiISelDag(LanaiTargetMachine &TM)
Extended Value Type.
Definition: ValueTypes.h:34
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
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...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
#define N
unsigned getOpcode() const
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const SDValue & getOperand(unsigned i) const
static AluCode isdToLanaiAluCode(ISD::NodeType Node_type)
Definition: LanaiAluCode.h:119
#define LLVM_DEBUG(X)
Definition: Debug.h:123
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...