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