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