LLVM  17.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 #define PASS_NAME "Lanai DAG->DAG Pattern Instruction Selection"
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  static char ID;
52 
53  LanaiDAGToDAGISel() = delete;
54 
55  explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
57 
58  bool runOnMachineFunction(MachineFunction &MF) override {
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 char LanaiDAGToDAGISel::ID = 0;
102 
103 INITIALIZE_PASS(LanaiDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
104 
105 // Helper functions for ComplexPattern used on LanaiInstrInfo
106 // Used on Lanai Load/Store instructions.
107 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
108  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
109  SDLoc DL(Addr);
110  // Loading from a constant address.
111  if (canBeRepresentedAsSls(*CN)) {
112  int32_t Imm = CN->getSExtValue();
113  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
114  return true;
115  }
116  }
117  if (Addr.getOpcode() == ISD::OR &&
118  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
119  Offset = Addr.getOperand(1).getOperand(0);
120  return true;
121  }
122  return false;
123 }
124 
125 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
126  SDValue &Offset, SDValue &AluOp,
127  bool RiMode) {
128  SDLoc DL(Addr);
129 
130  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
131  if (RiMode) {
132  // Fits in 16-bit signed immediate.
133  if (isInt<16>(CN->getSExtValue())) {
134  int16_t Imm = CN->getSExtValue();
135  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
136  Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
137  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
138  return true;
139  }
140  // Allow SLS to match if the constant doesn't fit in 16 bits but can be
141  // represented as an SLS.
142  if (canBeRepresentedAsSls(*CN))
143  return false;
144  } else {
145  // Fits in 10-bit signed immediate.
146  if (isInt<10>(CN->getSExtValue())) {
147  int16_t Imm = CN->getSExtValue();
148  Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
149  Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
150  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
151  return true;
152  }
153  }
154  }
155 
156  // if Address is FI, get the TargetFrameIndex.
157  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
158  Base = CurDAG->getTargetFrameIndex(
159  FIN->getIndex(),
160  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
161  Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
162  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
163  return true;
164  }
165 
166  // Skip direct calls
167  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
168  Addr.getOpcode() == ISD::TargetGlobalAddress))
169  return false;
170 
171  // Address of the form imm + reg
172  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
173  if (AluOperator == ISD::ADD) {
174  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
175  // Addresses of the form FI+const
176  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
177  if ((RiMode && isInt<16>(CN->getSExtValue())) ||
178  (!RiMode && isInt<10>(CN->getSExtValue()))) {
179  // If the first operand is a FI, get the TargetFI Node
180  if (FrameIndexSDNode *FIN =
181  dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
182  Base = CurDAG->getTargetFrameIndex(
183  FIN->getIndex(),
184  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
185  } else {
186  Base = Addr.getOperand(0);
187  }
188 
189  Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
190  return true;
191  }
192  }
193 
194  // Let SLS match SMALL instead of RI.
195  if (AluOperator == ISD::OR && RiMode &&
196  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
197  return false;
198 
199  Base = Addr;
200  Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
201  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
202  return true;
203 }
204 
205 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
206  SDValue &Offset, SDValue &AluOp) {
207  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true);
208 }
209 
210 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
211  SDValue &Offset, SDValue &AluOp) {
212  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
213 }
214 
215 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
216  SDValue &AluOp) {
217  // if Address is FI, get the TargetFrameIndex.
218  if (Addr.getOpcode() == ISD::FrameIndex)
219  return false;
220 
221  // Skip direct calls
222  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
223  Addr.getOpcode() == ISD::TargetGlobalAddress))
224  return false;
225 
226  // Address of the form OP + OP
227  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
229  if (AluCode != LPAC::UNKNOWN) {
230  // Skip addresses of the form FI OP const
231  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
232  if (isInt<16>(CN->getSExtValue()))
233  return false;
234 
235  // Skip addresses with hi/lo operands
236  if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
237  Addr.getOperand(0).getOpcode() == LanaiISD::LO ||
238  Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||
239  Addr.getOperand(1).getOpcode() == LanaiISD::HI ||
240  Addr.getOperand(1).getOpcode() == LanaiISD::LO ||
241  Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
242  return false;
243 
244  // Addresses of the form register OP register
245  R1 = Addr.getOperand(0);
246  R2 = Addr.getOperand(1);
247  AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
248  return true;
249  }
250 
251  // Skip addresses with zero offset
252  return false;
253 }
254 
255 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
256  const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
257  SDValue Op0, Op1, AluOp;
258  switch (ConstraintCode) {
259  default:
260  return true;
261  case InlineAsm::Constraint_m: // memory
262  if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
263  !selectAddrRi(Op, Op0, Op1, AluOp))
264  return true;
265  break;
266  }
267 
268  OutOps.push_back(Op0);
269  OutOps.push_back(Op1);
270  OutOps.push_back(AluOp);
271  return false;
272 }
273 
274 // Select instructions not customized! Used for
275 // expanded, promoted and normal instructions
276 void LanaiDAGToDAGISel::Select(SDNode *Node) {
277  unsigned Opcode = Node->getOpcode();
278 
279  // If we have a custom node, we already have selected!
280  if (Node->isMachineOpcode()) {
281  LLVM_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->isZero()) {
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->isAllOnes()) {
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 = 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 }
llvm::LPAC::ADD
@ ADD
Definition: LanaiAluCode.h:23
llvm::ConstantSDNode
Definition: SelectionDAGNodes.h:1586
LanaiAluCode.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1106
llvm::ISD::OR
@ OR
Definition: ISDOpcodes.h:667
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:824
llvm::LanaiISD::SMALL
@ SMALL
Definition: LanaiISelLowering.h:61
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:463
llvm::ConstantSDNode::isAllOnes
bool isAllOnes() const
Definition: SelectionDAGNodes.h:1613
llvm::ConstantSDNode::isZero
bool isZero() const
Definition: SelectionDAGNodes.h:1610
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
LanaiRegisterInfo.h
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
PASS_NAME
#define PASS_NAME
Definition: LanaiISelDAGToDAG.cpp:37
MachineRegisterInfo.h
R2
#define R2(n)
GlobalValue.h
TargetMachine.h
llvm::ISD::Constant
@ Constant
Definition: ISDOpcodes.h:76
llvm::EVT
Extended Value Type.
Definition: ValueTypes.h:34
Intrinsics.h
INITIALIZE_PASS
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
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:1789
llvm::ISD::TargetGlobalAddress
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:164
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Type.h
CFG.h
llvm::LanaiISD::LO
@ LO
Definition: LanaiISelLowering.h:58
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
llvm::LanaiISD::HI
@ HI
Definition: LanaiISelLowering.h:57
MachineConstantPool.h
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
llvm::MachineFunction
Definition: MachineFunction.h:258
SelectionDAGISel.h
llvm::Offset
@ Offset
Definition: DWP.cpp:406
llvm::createLanaiISelDag
FunctionPass * createLanaiISelDag(LanaiTargetMachine &TM)
Definition: LanaiISelDAGToDAG.cpp:335
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:1602
llvm::LPAC::UNKNOWN
@ UNKNOWN
Definition: LanaiAluCode.h:40
llvm::ISD::FrameIndex
@ FrameIndex
Definition: ISDOpcodes.h:80
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:165
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:354
llvm::ISD::TargetExternalSymbol
@ TargetExternalSymbol
Definition: ISDOpcodes.h:169
MachineFrameInfo.h
llvm::MVT::i32
@ i32
Definition: MachineValueType.h:48
llvm::SDValue
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
Definition: SelectionDAGNodes.h:145
llvm::InlineAsm::Constraint_m
@ Constraint_m
Definition: InlineAsm.h:259
llvm::LanaiTargetMachine
Definition: LanaiTargetMachine.h:25
LanaiMachineFunctionInfo.h
llvm::ISD::ADD
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
llvm::RISCVMatInt::Imm
@ Imm
Definition: RISCVMatInt.h:23
Instructions.h
llvm::SelectionDAGISel
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
Definition: SelectionDAGISel.h:41
MachineInstrBuilder.h
N
#define N
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:308
DEBUG_TYPE
#define DEBUG_TYPE
Definition: LanaiISelDAGToDAG.cpp:36
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:381
MachineFunction.h
LanaiSubtarget.h
Debug.h
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58