LLVM  13.0.0git
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)
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 ||
164  Addr.getOpcode() == ISD::TargetGlobalAddress))
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 ||
219  Addr.getOpcode() == ISD::TargetGlobalAddress))
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 }
llvm::LPAC::ADD
@ ADD
Definition: LanaiAluCode.h:23
llvm::ConstantSDNode
Definition: SelectionDAGNodes.h:1537
LanaiAluCode.h
llvm
Definition: AllocatorList.h:23
llvm::LPAC::AluCode
AluCode
Definition: LanaiAluCode.h:22
llvm::SDLoc
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Definition: SelectionDAGNodes.h:1078
llvm::ISD::OR
@ OR
Definition: ISDOpcodes.h:623
llvm::LPAC::isdToLanaiAluCode
static AluCode isdToLanaiAluCode(ISD::NodeType Node_type)
Definition: LanaiAluCode.h:118
ErrorHandling.h
llvm::SDNode
Represents one node in the SelectionDAG.
Definition: SelectionDAGNodes.h:455
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
LanaiRegisterInfo.h
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
MachineRegisterInfo.h
R2
#define R2(n)
GlobalValue.h
TargetMachine.h
llvm::ISD::Constant
@ Constant
Definition: ISDOpcodes.h:69
llvm::EVT
Extended Value Type.
Definition: ValueTypes.h:35
Intrinsics.h
llvm::ISD::NodeType
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition: ISDOpcodes.h:40
llvm::FrameIndexSDNode
Definition: SelectionDAGNodes.h:1719
llvm::ISD::TargetGlobalAddress
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:157
Type.h
CFG.h
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
MachineConstantPool.h
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
llvm::MachineFunction
Definition: MachineFunction.h:230
SelectionDAGISel.h
llvm::LanaiISD::HI
@ HI
Definition: LanaiISelLowering.h:57
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::createLanaiISelDag
FunctionPass * createLanaiISelDag(LanaiTargetMachine &TM)
Definition: LanaiISelDAGToDAG.cpp:331
llvm::ms_demangle::IntrinsicFunctionKind::New
@ New
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::ConstantSDNode::getSExtValue
int64_t getSExtValue() const
Definition: SelectionDAGNodes.h:1553
llvm::LPAC::UNKNOWN
@ UNKNOWN
Definition: LanaiAluCode.h:40
llvm::ISD::FrameIndex
@ FrameIndex
Definition: ISDOpcodes.h:73
llvm::LanaiISD::LO
@ LO
Definition: LanaiISelLowering.h:58
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:162
llvm::isInt< 16 >
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:370
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::ISD::TargetExternalSymbol
@ TargetExternalSymbol
Definition: ISDOpcodes.h:162
MachineFrameInfo.h
llvm::MVT::i32
@ i32
Definition: MachineValueType.h:43
llvm::SDValue
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
Definition: SelectionDAGNodes.h:138
llvm::InlineAsm::Constraint_m
@ Constraint_m
Definition: InlineAsm.h:247
llvm::LanaiTargetMachine
Definition: LanaiTargetMachine.h:24
LanaiMachineFunctionInfo.h
llvm::ISD::ADD
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:232
Instructions.h
llvm::SelectionDAGISel
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
Definition: SelectionDAGISel.h:39
MachineInstrBuilder.h
llvm::ConstantSDNode::isAllOnesValue
bool isAllOnesValue() const
Definition: SelectionDAGNodes.h:1562
N
#define N
llvm::LanaiISD::SMALL
@ SMALL
Definition: LanaiISelLowering.h:61
llvm::ConstantSDNode::isNullValue
bool isNullValue() const
Definition: SelectionDAGNodes.h:1561
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
LanaiTargetMachine.h
raw_ostream.h
llvm::SelectionDAGISel::runOnMachineFunction
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: SelectionDAGISel.cpp:415
MachineFunction.h
LanaiSubtarget.h
Debug.h
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58