LLVM 22.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 "VESelectionDAGInfo.h"
15#include "VETargetMachine.h"
18using namespace llvm;
19
20#define DEBUG_TYPE "ve-isel"
21#define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"
22
23//===--------------------------------------------------------------------===//
24/// VEDAGToDAGISel - VE specific code to select VE machine
25/// instructions for SelectionDAG operations.
26///
27namespace {
28class VEDAGToDAGISel : public SelectionDAGISel {
29 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
30 /// make the right decision when generating code for different targets.
31 const VESubtarget *Subtarget;
32
33public:
34 VEDAGToDAGISel() = delete;
35
36 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
37
38 bool runOnMachineFunction(MachineFunction &MF) override {
39 Subtarget = &MF.getSubtarget<VESubtarget>();
41 }
42
43 void Select(SDNode *N) override;
44
45 // Complex Pattern Selectors.
46 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
47 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
48 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
49 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
50 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
51 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
52
53 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
54 /// inline asm expressions.
55 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
56 InlineAsm::ConstraintCode ConstraintID,
57 std::vector<SDValue> &OutOps) override;
58
59 // Include the pieces autogenerated from the target description.
60#include "VEGenDAGISel.inc"
61
62private:
63 SDNode *getGlobalBaseReg();
64
65 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
66 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
67};
68
69class VEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
70public:
71 static char ID;
72 explicit VEDAGToDAGISelLegacy(VETargetMachine &tm)
73 : SelectionDAGISelLegacy(ID, std::make_unique<VEDAGToDAGISel>(tm)) {}
74};
75} // end anonymous namespace
76
77char VEDAGToDAGISelLegacy::ID = 0;
78
79INITIALIZE_PASS(VEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
80
81bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
82 SDValue &Offset) {
83 if (Addr.getOpcode() == ISD::FrameIndex)
84 return false;
85 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
86 Addr.getOpcode() == ISD::TargetGlobalAddress ||
87 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
88 return false; // direct calls.
89
91 if (matchADDRri(Addr, LHS, RHS)) {
92 if (matchADDRrr(LHS, Base, Index)) {
93 Offset = RHS;
94 return true;
95 }
96 // Return false to try selectADDRrii.
97 return false;
98 }
99 if (matchADDRrr(Addr, LHS, RHS)) {
100 // If the input is a pair of a frame-index and a register, move a
101 // frame-index to LHS. This generates MI with following operands.
102 // %dest, #FI, %reg, offset
103 // In the eliminateFrameIndex, above MI is converted to the following.
104 // %dest, %fp, %reg, fi_offset + offset
106 std::swap(LHS, RHS);
107
108 if (matchADDRri(RHS, Index, Offset)) {
109 Base = LHS;
110 return true;
111 }
112 if (matchADDRri(LHS, Base, Offset)) {
113 Index = RHS;
114 return true;
115 }
116 Base = LHS;
117 Index = RHS;
118 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
119 return true;
120 }
121 return false; // Let the reg+imm(=0) pattern catch this!
122}
123
124bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
125 SDValue &Offset) {
126 if (matchADDRri(Addr, Base, Offset)) {
127 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
128 return true;
129 }
130
131 Base = Addr;
132 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
133 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
134 return true;
135}
136
137bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
138 SDValue &Offset) {
139 // Prefer ADDRrii.
140 return false;
141}
142
143bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
144 SDValue &Offset) {
145 if (isa<FrameIndexSDNode>(Addr))
146 return false;
147 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
150 return false; // direct calls.
151
152 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
153 if (isInt<32>(CN->getSExtValue())) {
154 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
155 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
156 Offset =
157 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
158 return true;
159 }
160 }
161 return false;
162}
163
164bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
165 SDValue &Offset) {
166 if (matchADDRri(Addr, Base, Offset))
167 return true;
168
169 Base = Addr;
170 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
171 return true;
172}
173
174bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
175 SDValue &Offset) {
176 if (isa<FrameIndexSDNode>(Addr))
177 return false;
178 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
181 return false; // direct calls.
182
183 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
184 if (isInt<32>(CN->getSExtValue())) {
185 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
186 Offset =
187 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
188 return true;
189 }
190 }
191 return false;
192}
193
194bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
195 if (isa<FrameIndexSDNode>(Addr))
196 return false;
197 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
200 return false; // direct calls.
201
202 if (Addr.getOpcode() == ISD::ADD) {
203 ; // Nothing to do here.
204 } else if (Addr.getOpcode() == ISD::OR) {
205 // We want to look through a transform in InstCombine and DAGCombiner that
206 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
207 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
208 return false;
209 } else {
210 return false;
211 }
212
213 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
214 Addr.getOperand(1).getOpcode() == VEISD::Lo)
215 return false; // Let the LEASL patterns catch this!
216
217 Base = Addr.getOperand(0);
218 Index = Addr.getOperand(1);
219 return true;
220}
221
222bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
223 auto AddrTy = Addr->getValueType(0);
224 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
225 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
226 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
227 return true;
228 }
229 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
232 return false; // direct calls.
233
234 if (CurDAG->isBaseWithConstantOffset(Addr)) {
235 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
236 if (isInt<32>(CN->getSExtValue())) {
237 if (FrameIndexSDNode *FIN =
239 // Constant offset from frame ref.
240 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
241 } else {
242 Base = Addr.getOperand(0);
243 }
244 Offset =
245 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
246 return true;
247 }
248 }
249 return false;
250}
251
252void VEDAGToDAGISel::Select(SDNode *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
266 case VEISD::VEC_BROADCAST: {
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() {
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}
return SDValue()
AMDGPU Register Bank Select
#define DEBUG_TYPE
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define PASS_NAME
Value * RHS
Value * LHS
uint64_t getZExtValue() const
int64_t getSExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
unsigned getVectorNumElements() const
MVT getVectorElementType() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
Register getGlobalBaseReg(MachineFunction *MF) const
} Optimization
const VEInstrInfo * getInstrInfo() const override
Definition VESubtarget.h:52
#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:259
@ TargetExternalSymbol
Definition ISDOpcodes.h:185
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:180
@ TargetGlobalTLSAddress
Definition ISDOpcodes.h:181
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:379
static const unsigned PackedVectorWidth
Definition VE.h:380
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
#define N