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