LLVM 20.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 VEDAGToDAGISel() = delete;
38
39 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
40
41 bool runOnMachineFunction(MachineFunction &MF) override {
42 Subtarget = &MF.getSubtarget<VESubtarget>();
44 }
45
46 void Select(SDNode *N) override;
47
48 // Complex Pattern Selectors.
49 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
50 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
51 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
52 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
53 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
54 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
55
56 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
57 /// inline asm expressions.
59 InlineAsm::ConstraintCode ConstraintID,
60 std::vector<SDValue> &OutOps) override;
61
62 // Include the pieces autogenerated from the target description.
63#include "VEGenDAGISel.inc"
64
65private:
66 SDNode *getGlobalBaseReg();
67
68 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
69 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
70};
71
72class VEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
73public:
74 static char ID;
75 explicit VEDAGToDAGISelLegacy(VETargetMachine &tm)
76 : SelectionDAGISelLegacy(ID, std::make_unique<VEDAGToDAGISel>(tm)) {}
77};
78} // end anonymous namespace
79
80char VEDAGToDAGISelLegacy::ID = 0;
81
82INITIALIZE_PASS(VEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
83
84bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
85 SDValue &Offset) {
86 if (Addr.getOpcode() == ISD::FrameIndex)
87 return false;
88 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
89 Addr.getOpcode() == ISD::TargetGlobalAddress ||
90 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
91 return false; // direct calls.
92
94 if (matchADDRri(Addr, LHS, RHS)) {
95 if (matchADDRrr(LHS, Base, Index)) {
96 Offset = RHS;
97 return true;
98 }
99 // Return false to try selectADDRrii.
100 return false;
101 }
102 if (matchADDRrr(Addr, LHS, RHS)) {
103 // If the input is a pair of a frame-index and a register, move a
104 // frame-index to LHS. This generates MI with following operands.
105 // %dest, #FI, %reg, offset
106 // In the eliminateFrameIndex, above MI is converted to the following.
107 // %dest, %fp, %reg, fi_offset + offset
108 if (isa<FrameIndexSDNode>(RHS))
109 std::swap(LHS, RHS);
110
111 if (matchADDRri(RHS, Index, Offset)) {
112 Base = LHS;
113 return true;
114 }
115 if (matchADDRri(LHS, Base, Offset)) {
116 Index = RHS;
117 return true;
118 }
119 Base = LHS;
120 Index = RHS;
121 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
122 return true;
123 }
124 return false; // Let the reg+imm(=0) pattern catch this!
125}
126
127bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
128 SDValue &Offset) {
129 if (matchADDRri(Addr, Base, Offset)) {
130 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
131 return true;
132 }
133
134 Base = Addr;
135 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
136 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
137 return true;
138}
139
140bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
141 SDValue &Offset) {
142 // Prefer ADDRrii.
143 return false;
144}
145
146bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
147 SDValue &Offset) {
148 if (isa<FrameIndexSDNode>(Addr))
149 return false;
150 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
151 Addr.getOpcode() == ISD::TargetGlobalAddress ||
152 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
153 return false; // direct calls.
154
155 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
156 if (isInt<32>(CN->getSExtValue())) {
157 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
158 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
159 Offset =
160 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
161 return true;
162 }
163 }
164 return false;
165}
166
167bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
168 SDValue &Offset) {
169 if (matchADDRri(Addr, Base, Offset))
170 return true;
171
172 Base = Addr;
173 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
174 return true;
175}
176
177bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
178 SDValue &Offset) {
179 if (isa<FrameIndexSDNode>(Addr))
180 return false;
181 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
182 Addr.getOpcode() == ISD::TargetGlobalAddress ||
183 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
184 return false; // direct calls.
185
186 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
187 if (isInt<32>(CN->getSExtValue())) {
188 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
189 Offset =
190 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
191 return true;
192 }
193 }
194 return false;
195}
196
197bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
198 if (isa<FrameIndexSDNode>(Addr))
199 return false;
200 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
201 Addr.getOpcode() == ISD::TargetGlobalAddress ||
202 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
203 return false; // direct calls.
204
205 if (Addr.getOpcode() == ISD::ADD) {
206 ; // Nothing to do here.
207 } else if (Addr.getOpcode() == ISD::OR) {
208 // We want to look through a transform in InstCombine and DAGCombiner that
209 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
210 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
211 return false;
212 } else {
213 return false;
214 }
215
216 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
217 Addr.getOperand(1).getOpcode() == VEISD::Lo)
218 return false; // Let the LEASL patterns catch this!
219
220 Base = Addr.getOperand(0);
221 Index = Addr.getOperand(1);
222 return true;
223}
224
225bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
226 auto AddrTy = Addr->getValueType(0);
227 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
228 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
229 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
230 return true;
231 }
232 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
233 Addr.getOpcode() == ISD::TargetGlobalAddress ||
234 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
235 return false; // direct calls.
236
237 if (CurDAG->isBaseWithConstantOffset(Addr)) {
238 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
239 if (isInt<32>(CN->getSExtValue())) {
240 if (FrameIndexSDNode *FIN =
241 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
242 // Constant offset from frame ref.
243 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
244 } else {
245 Base = Addr.getOperand(0);
246 }
247 Offset =
248 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
249 return true;
250 }
251 }
252 return false;
253}
254
255void VEDAGToDAGISel::Select(SDNode *N) {
256 SDLoc dl(N);
257 if (N->isMachineOpcode()) {
258 N->setNodeId(-1);
259 return; // Already selected.
260 }
261
262 switch (N->getOpcode()) {
263
264 // Late eliminate the LEGALAVL wrapper
265 case VEISD::LEGALAVL:
266 ReplaceNode(N, N->getOperand(0).getNode());
267 return;
268
269 // Lower (broadcast 1) and (broadcast 0) to VM[P]0
271 MVT SplatResTy = N->getSimpleValueType(0);
272 if (SplatResTy.getVectorElementType() != MVT::i1)
273 break;
274
275 // Constant non-zero broadcast.
276 auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));
277 if (!BConst)
278 break;
279 bool BCTrueMask = (BConst->getSExtValue() != 0);
280 if (!BCTrueMask)
281 break;
282
283 // Packed or non-packed.
284 SDValue New;
285 if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {
286 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,
287 MVT::v256i1);
288 } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {
289 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,
290 MVT::v512i1);
291 } else
292 break;
293
294 // Replace.
295 ReplaceNode(N, New.getNode());
296 return;
297 }
298
300 ReplaceNode(N, getGlobalBaseReg());
301 return;
302 }
303
304 SelectCode(N);
305}
306
307/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
308/// inline asm expressions.
309bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(
310 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
311 std::vector<SDValue> &OutOps) {
312 SDValue Op0, Op1;
313 switch (ConstraintID) {
314 default:
315 llvm_unreachable("Unexpected asm memory constraint");
316 case InlineAsm::ConstraintCode::o:
317 case InlineAsm::ConstraintCode::m: // memory
318 // Try to match ADDRri since reg+imm style is safe for all VE instructions
319 // with a memory operand.
320 if (selectADDRri(Op, Op0, Op1)) {
321 OutOps.push_back(Op0);
322 OutOps.push_back(Op1);
323 return false;
324 }
325 // Otherwise, require the address to be in a register and immediate 0.
326 OutOps.push_back(Op);
327 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
328 return false;
329 }
330 return true;
331}
332
333SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
334 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
335 return CurDAG
336 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
337 .getNode();
338}
339
340/// createVEISelDag - This pass converts a legalized DAG into a
341/// VE-specific DAG, ready for instruction scheduling.
342///
344 return new VEDAGToDAGISelLegacy(TM);
345}
amdgpu AMDGPU Register Bank Select
uint64_t Addr
#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:310
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,...
virtual bool runOnMachineFunction(MachineFunction &mf)
#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:246
@ FrameIndex
Definition: ISDOpcodes.h:80
@ TargetExternalSymbol
Definition: ISDOpcodes.h:175
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:170
@ TargetGlobalTLSAddress
Definition: ISDOpcodes.h:171
@ 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:480
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