LLVM 19.0.0git
VEISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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 VE target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "VE.h"
14#include "VETargetMachine.h"
17#include "llvm/IR/Intrinsics.h"
18#include "llvm/Support/Debug.h"
21using namespace llvm;
22
23#define DEBUG_TYPE "ve-isel"
24#define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"
25
26//===--------------------------------------------------------------------===//
27/// VEDAGToDAGISel - VE specific code to select VE machine
28/// instructions for SelectionDAG operations.
29///
30namespace {
31class VEDAGToDAGISel : public SelectionDAGISel {
32 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
33 /// make the right decision when generating code for different targets.
34 const VESubtarget *Subtarget;
35
36public:
37 static char ID;
38
39 VEDAGToDAGISel() = delete;
40
41 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(ID, tm) {}
42
43 bool runOnMachineFunction(MachineFunction &MF) override {
44 Subtarget = &MF.getSubtarget<VESubtarget>();
46 }
47
48 void Select(SDNode *N) override;
49
50 // Complex Pattern Selectors.
51 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
52 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
53 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
54 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
55 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
56 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
57
58 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
59 /// inline asm expressions.
61 InlineAsm::ConstraintCode ConstraintID,
62 std::vector<SDValue> &OutOps) override;
63
64 // Include the pieces autogenerated from the target description.
65#include "VEGenDAGISel.inc"
66
67private:
68 SDNode *getGlobalBaseReg();
69
70 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
71 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
72};
73} // end anonymous namespace
74
75char VEDAGToDAGISel::ID = 0;
76
77INITIALIZE_PASS(VEDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
78
79bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
80 SDValue &Offset) {
81 if (Addr.getOpcode() == ISD::FrameIndex)
82 return false;
83 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
84 Addr.getOpcode() == ISD::TargetGlobalAddress ||
85 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
86 return false; // direct calls.
87
89 if (matchADDRri(Addr, LHS, RHS)) {
90 if (matchADDRrr(LHS, Base, Index)) {
91 Offset = RHS;
92 return true;
93 }
94 // Return false to try selectADDRrii.
95 return false;
96 }
97 if (matchADDRrr(Addr, LHS, RHS)) {
98 // If the input is a pair of a frame-index and a register, move a
99 // frame-index to LHS. This generates MI with following operands.
100 // %dest, #FI, %reg, offset
101 // In the eliminateFrameIndex, above MI is converted to the following.
102 // %dest, %fp, %reg, fi_offset + offset
103 if (isa<FrameIndexSDNode>(RHS))
104 std::swap(LHS, RHS);
105
106 if (matchADDRri(RHS, Index, Offset)) {
107 Base = LHS;
108 return true;
109 }
110 if (matchADDRri(LHS, Base, Offset)) {
111 Index = RHS;
112 return true;
113 }
114 Base = LHS;
115 Index = RHS;
116 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
117 return true;
118 }
119 return false; // Let the reg+imm(=0) pattern catch this!
120}
121
122bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
123 SDValue &Offset) {
124 if (matchADDRri(Addr, Base, Offset)) {
125 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
126 return true;
127 }
128
129 Base = Addr;
130 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
131 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
132 return true;
133}
134
135bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
136 SDValue &Offset) {
137 // Prefer ADDRrii.
138 return false;
139}
140
141bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
142 SDValue &Offset) {
143 if (isa<FrameIndexSDNode>(Addr))
144 return false;
145 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
146 Addr.getOpcode() == ISD::TargetGlobalAddress ||
147 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
148 return false; // direct calls.
149
150 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
151 if (isInt<32>(CN->getSExtValue())) {
152 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
153 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
154 Offset =
155 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
156 return true;
157 }
158 }
159 return false;
160}
161
162bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
163 SDValue &Offset) {
164 if (matchADDRri(Addr, Base, Offset))
165 return true;
166
167 Base = Addr;
168 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
169 return true;
170}
171
172bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
173 SDValue &Offset) {
174 if (isa<FrameIndexSDNode>(Addr))
175 return false;
176 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
177 Addr.getOpcode() == ISD::TargetGlobalAddress ||
178 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
179 return false; // direct calls.
180
181 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
182 if (isInt<32>(CN->getSExtValue())) {
183 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
184 Offset =
185 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
186 return true;
187 }
188 }
189 return false;
190}
191
192bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
193 if (isa<FrameIndexSDNode>(Addr))
194 return false;
195 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
196 Addr.getOpcode() == ISD::TargetGlobalAddress ||
197 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
198 return false; // direct calls.
199
200 if (Addr.getOpcode() == ISD::ADD) {
201 ; // Nothing to do here.
202 } else if (Addr.getOpcode() == ISD::OR) {
203 // We want to look through a transform in InstCombine and DAGCombiner that
204 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
205 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
206 return false;
207 } else {
208 return false;
209 }
210
211 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
212 Addr.getOperand(1).getOpcode() == VEISD::Lo)
213 return false; // Let the LEASL patterns catch this!
214
215 Base = Addr.getOperand(0);
216 Index = Addr.getOperand(1);
217 return true;
218}
219
220bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
221 auto AddrTy = Addr->getValueType(0);
222 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
223 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
224 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
225 return true;
226 }
227 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
228 Addr.getOpcode() == ISD::TargetGlobalAddress ||
229 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
230 return false; // direct calls.
231
232 if (CurDAG->isBaseWithConstantOffset(Addr)) {
233 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
234 if (isInt<32>(CN->getSExtValue())) {
235 if (FrameIndexSDNode *FIN =
236 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
237 // Constant offset from frame ref.
238 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
239 } else {
240 Base = Addr.getOperand(0);
241 }
242 Offset =
243 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
244 return true;
245 }
246 }
247 return false;
248}
249
250void VEDAGToDAGISel::Select(SDNode *N) {
251 SDLoc dl(N);
252 if (N->isMachineOpcode()) {
253 N->setNodeId(-1);
254 return; // Already selected.
255 }
256
257 switch (N->getOpcode()) {
258
259 // Late eliminate the LEGALAVL wrapper
260 case VEISD::LEGALAVL:
261 ReplaceNode(N, N->getOperand(0).getNode());
262 return;
263
264 // Lower (broadcast 1) and (broadcast 0) to VM[P]0
266 MVT SplatResTy = N->getSimpleValueType(0);
267 if (SplatResTy.getVectorElementType() != MVT::i1)
268 break;
269
270 // Constant non-zero broadcast.
271 auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));
272 if (!BConst)
273 break;
274 bool BCTrueMask = (BConst->getSExtValue() != 0);
275 if (!BCTrueMask)
276 break;
277
278 // Packed or non-packed.
279 SDValue New;
280 if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {
281 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,
282 MVT::v256i1);
283 } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {
284 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,
285 MVT::v512i1);
286 } else
287 break;
288
289 // Replace.
290 ReplaceNode(N, New.getNode());
291 return;
292 }
293
295 ReplaceNode(N, getGlobalBaseReg());
296 return;
297 }
298
299 SelectCode(N);
300}
301
302/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
303/// inline asm expressions.
304bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(
305 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
306 std::vector<SDValue> &OutOps) {
307 SDValue Op0, Op1;
308 switch (ConstraintID) {
309 default:
310 llvm_unreachable("Unexpected asm memory constraint");
311 case InlineAsm::ConstraintCode::o:
312 case InlineAsm::ConstraintCode::m: // memory
313 // Try to match ADDRri since reg+imm style is safe for all VE instructions
314 // with a memory operand.
315 if (selectADDRri(Op, Op0, Op1)) {
316 OutOps.push_back(Op0);
317 OutOps.push_back(Op1);
318 return false;
319 }
320 // Otherwise, require the address to be in a register and immediate 0.
321 OutOps.push_back(Op);
322 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
323 return false;
324 }
325 return true;
326}
327
328SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
329 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
330 return CurDAG
331 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
332 .getNode();
333}
334
335/// createVEISelDag - This pass converts a legalized DAG into a
336/// VE-specific DAG, ready for instruction scheduling.
337///
339 return new VEDAGToDAGISel(TM);
340}
amdgpu AMDGPU Register Bank Select
uint64_t Addr
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
#define PASS_NAME
#define DEBUG_TYPE
Value * RHS
Value * LHS
uint64_t getZExtValue() const
int64_t getSExtValue() const
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
Machine Value Type.
unsigned getVectorNumElements() const
MVT getVectorElementType() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
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...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ 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
@ TargetGlobalTLSAddress
Definition: ISDOpcodes.h:165
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
FunctionPass * createVEISelDag(VETargetMachine &TM)
createVEISelDag - This pass converts a legalized DAG into a VE-specific DAG, ready for instruction sc...
static const unsigned StandardVectorWidth
Definition: VE.h:378
static const unsigned PackedVectorWidth
Definition: VE.h:379
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
#define N