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"
27#include "llvm/IR/Intrinsics.h"
28#include "llvm/IR/Type.h"
29#include "llvm/Support/Debug.h"
33
34using 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//===----------------------------------------------------------------------===//
47namespace {
48
49class LanaiDAGToDAGISel : public SelectionDAGISel {
50public:
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
65private:
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
89private:
90 bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
91 SDValue &AluOp, bool RiMode);
92};
93
94bool 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
101char LanaiDAGToDAGISel::ID = 0;
102
103INITIALIZE_PASS(LanaiDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
104
105// Helper functions for ComplexPattern used on LanaiInstrInfo
106// Used on Lanai Load/Store instructions.
107bool 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
125bool 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
205bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
206 SDValue &Offset, SDValue &AluOp) {
207 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true);
208}
209
210bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
211 SDValue &Offset, SDValue &AluOp) {
212 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
213}
214
215bool 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
255bool 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
276void 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
319void 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}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
#define PASS_NAME
#define DEBUG_TYPE
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define R2(n)
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
DEMANGLE_DUMP_METHOD void dump() const
int64_t getSExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition: ISDOpcodes.h:40
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
@ FrameIndex
Definition: ISDOpcodes.h:80
@ TargetExternalSymbol
Definition: ISDOpcodes.h:169
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:164
static AluCode isdToLanaiAluCode(ISD::NodeType Node_type)
Definition: LanaiAluCode.h:118
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
FunctionPass * createLanaiISelDag(LanaiTargetMachine &TM)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
#define N
Extended Value Type.
Definition: ValueTypes.h:34