LLVM: lib/Target/VE/VVPISelLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
17
18using namespace llvm;
19
20#define DEBUG_TYPE "ve-lower"
21
26 CDAG.getConstant(Op.getValueType().getVectorNumElements(), MVT::i32);
33 unsigned Opc = Op.getOpcode();
34 auto LoRes = CDAG.getNode(Opc, MVT::v256i1, {LoA, LoB});
35 auto HiRes = CDAG.getNode(Opc, MVT::v256i1, {HiA, HiB});
36 return CDAG.getPack(MVT::v512i1, LoRes, HiRes, AVL);
37}
38
40
41 const unsigned Opcode = Op->getOpcode();
43 if (!VVPOpcodeOpt)
45 unsigned VVPOpcode = *VVPOpcodeOpt;
47
48
50
51 switch (VVPOpcode) {
52 case VEISD::VVP_LOAD:
53 case VEISD::VVP_STORE:
55 case VEISD::VVP_GATHER:
56 case VEISD::VVP_SCATTER:
58 }
59
63
66
67 if (FromVP) {
68
71 if (MaskIdx)
72 Mask = Op->getOperand(*MaskIdx);
73 if (AVLIdx)
74 AVL = Op->getOperand(*AVLIdx);
75 }
76
77
78 if (!AVL)
80 if (!Mask)
82
85 return CDAG.getNode(VVPOpcode, LegalVecVT, {Op->getOperand(0), Mask, AVL});
87 return CDAG.getNode(VVPOpcode, LegalVecVT,
88 {Op->getOperand(0), Op->getOperand(1), Mask, AVL});
92 SDValue VectorV = Op->getOperand(SrcHasStart ? 1 : 0);
94 VectorV, Mask, AVL, Op->getFlags());
95 }
96
97 switch (VVPOpcode) {
98 default:
100 case VEISD::VVP_FFMA: {
101
102
103 auto X = Op->getOperand(2);
104 auto Y = Op->getOperand(0);
105 auto Z = Op->getOperand(1);
106 return CDAG.getNode(VVPOpcode, LegalVecVT, {X, Y, Z, Mask, AVL});
107 }
108 case VEISD::VVP_SELECT: {
109 auto Mask = Op->getOperand(0);
110 auto OnTrue = Op->getOperand(1);
111 auto OnFalse = Op->getOperand(2);
112 return CDAG.getNode(VVPOpcode, LegalVecVT, {OnTrue, OnFalse, Mask, AVL});
113 }
114 case VEISD::VVP_SETCC: {
116 auto LHS = Op->getOperand(0);
117 auto RHS = Op->getOperand(1);
118 auto Pred = Op->getOperand(2);
119 return CDAG.getNode(VVPOpcode, LegalResVT, {LHS, RHS, Pred, Mask, AVL});
120 }
121 }
122}
123
127 const bool IsLoad = (VVPOpc == VEISD::VVP_LOAD);
128
129
134
136
138
140
143
144
145 if (!AVL)
146 AVL = CDAG.getConstant(DataVT.getVectorNumElements(), MVT::i32);
147
148
149 if (!Mask)
151
152 if (IsLoad) {
154 Packing, DataVT.getVectorElementType().getSimpleVT());
155
156 auto NewLoadV = CDAG.getNode(VEISD::VVP_LOAD, {LegalDataVT, MVT::Other},
157 {Chain, BasePtr, StrideV, Mask, AVL});
158
159 if (!PassThru || PassThru->isUndef())
160 return NewLoadV;
161
162
163 SDValue DataV = CDAG.getNode(VEISD::VVP_SELECT, DataVT,
164 {NewLoadV, PassThru, Mask, AVL});
165 SDValue NewLoadChainV = SDValue(NewLoadV.getNode(), 1);
166
167
169 }
170
171
172 assert(VVPOpc == VEISD::VVP_STORE);
175
176
177
179 return CDAG.getNode(VEISD::VVP_STORE, Op.getNode()->getVTList(),
180 {Chain, Data, BasePtr, StrideV, Mask, AVL});
181}
182
186 assert((VVPOC == VEISD::VVP_LOAD) || (VVPOC == VEISD::VVP_STORE));
187
190 "Can only split packed load/store");
192
194 "Should have been folded in lowering to VVP layer");
195
196
202
203 unsigned ChainResIdx = PackData ? 0 : 1;
204
206
207 SDValue UpperPartAVL;
209
210
212
213
215 UpperPartAVL = SplitTM.AVL;
216
217
219
220
222
223
224 if (PackData) {
226 CDAG.getUnpack(SplitDataVT, PackData, Part, SplitTM.AVL);
228 }
229
230
231
232
233
236
237
240
241 if (PackData) {
242
243 PartOps[(int)Part] = CDAG.getNode(VVPOC, MVT::Other, OpVec);
244 } else {
245
246 PartOps[(int)Part] =
247 CDAG.getNode(VVPOC, {SplitDataVT, MVT::Other}, OpVec);
248 }
249 }
250
251
256
257
258 if (PackData)
259 return FusedChains;
260
261
262 MVT PackedVT =
266
267 return CDAG.getMergeValues({PackedVals, FusedChains});
268}
269
274 MVT LegalDataVT =
276
285 if (PassThru && PassThru->isUndef())
287
288 bool IsScatter = (bool)StoredValue;
289
290
291 if (!AVL)
293
294
295 if (!Mask)
297
300 if (IsScatter)
301 return CDAG.getNode(VEISD::VVP_SCATTER, MVT::Other,
302 {Chain, StoredValue, AddressVec, Mask, AVL});
303
304
305 SDValue NewLoadV = CDAG.getNode(VEISD::VVP_GATHER, {LegalDataVT, MVT::Other},
306 {Chain, AddressVec, Mask, AVL});
307
308 if (!PassThru)
309 return NewLoadV;
310
311
312 SDValue DataV = CDAG.getNode(VEISD::VVP_SELECT, LegalDataVT,
313 {NewLoadV, PassThru, Mask, AVL});
316}
317
320 LLVM_DEBUG(dbgs() << "::legalizeInternalLoadStoreOp\n";);
322
323
326
328}
329
332 LLVM_DEBUG(dbgs() << "::legalizeInternalVectorOp\n";);
334
335
336 switch (Op->getOpcode()) {
337 case VEISD::VVP_LOAD:
338 case VEISD::VVP_STORE:
340 }
341
342 EVT IdiomVT = Op.getValueType();
346
347
349}
350
353
354 auto AVLPos = getAVLPos(Op->getOpcode());
356
359 SDValue PackedAVL = AVLPair.first;
360 assert(!AVLPair.second && "Expecting non pack-legalized oepration");
361
362
364
365 SDValue UpperPartAVL;
367
368
370
372 UpperPartAVL = SplitTM.AVL;
373
374
376 for (unsigned i = 0; i < Op.getNumOperands(); ++i) {
377 if (AVLPos && ((int)i) == *AVLPos)
378 continue;
379 if (MaskPos && ((int)i) == *MaskPos)
380 continue;
381
382
383 auto PackedOperand = Op.getOperand(i);
384 auto UnpackedOpVT = splitVectorType(PackedOperand.getSimpleValueType());
386 CDAG.getUnpack(UnpackedOpVT, PackedOperand, Part, SplitTM.AVL);
388 }
389
390
393
394 PartOps[(int)Part] =
395 CDAG.getNode(Op.getOpcode(), ResVT, OpVec, Op->getFlags());
396 }
397
398
401}
402
406
408 return Op;
409
410
413 return Op;
414
415
420 "TODO Shift predication from EVL into Mask");
421
423 LegalAVL = CDAG.getConstant((ConstAVL->getZExtValue() + 1) / 2, MVT::i32);
424 } else {
425 auto ConstOne = CDAG.getConstant(1, MVT::i32);
426 auto PlusOne = CDAG.getNode(ISD::ADD, MVT::i32, {AVL, ConstOne});
427 LegalAVL = CDAG.getNode(ISD::SRL, MVT::i32, {PlusOne, ConstOne});
428 }
429 }
430
432
433
434 int NumOp = Op->getNumOperands();
435 auto AVLPos = getAVLPos(Op->getOpcode());
436 std::vector FixedOperands;
437 for (int i = 0; i < NumOp; ++i) {
438 if (AVLPos && (i == *AVLPos)) {
439 FixedOperands.push_back(AnnotatedLegalAVL);
440 continue;
441 }
442 FixedOperands.push_back(Op->getOperand(i));
443 }
444
445
446 auto Flags = Op->getFlags();
448 CDAG.getNode(Op->getOpcode(), Op->getVTList(), FixedOperands, Flags);
449 return NewN;
450}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
MVT getVectorElementType() const
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVMContext * getContext() const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
SDValue getSplitPtrOffset(SDValue Ptr, SDValue ByteStride, PackElem Part) const
SDValue getMergeValues(ArrayRef< SDValue > Values) const
} Packing
SDValue getConstantMask(Packing Packing, bool AllTrue) const
SDValue getGatherScatterAddress(SDValue BasePtr, SDValue Scale, SDValue Index, SDValue Mask, SDValue AVL) const
SDValue getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, SDValue StartV, SDValue VectorV, SDValue Mask, SDValue AVL, SDNodeFlags Flags) const
} getNode
SDValue getNode(unsigned OC, SDVTList VTL, ArrayRef< SDValue > OpV, std::optional< SDNodeFlags > Flags=std::nullopt) const
getNode {
SDValue annotateLegalAVL(SDValue AVL) const
SDValue getUnpack(EVT DestVT, SDValue Vec, PackElem Part, SDValue AVL) const
} Legalizing getNode
SelectionDAG * getDAG() const
SDValue getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, SDValue AVL) const
SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget=false, bool IsOpaque=false) const
SDValue getSplitPtrStride(SDValue PackStride) const
VETargetMasks getTargetSplitMask(SDValue RawMask, SDValue RawAVL, PackElem Part) const
SDValue splitMaskArithmetic(SDValue Op, SelectionDAG &DAG) const
Definition VVPISelLowering.cpp:22
SDValue lowerVVP_GATHER_SCATTER(SDValue Op, VECustomDAG &) const
Definition VVPISelLowering.cpp:270
SDValue lowerToVVP(SDValue Op, SelectionDAG &DAG) const
} Custom Inserter
Definition VVPISelLowering.cpp:39
SDValue lowerVVP_LOAD_STORE(SDValue Op, VECustomDAG &) const
Definition VVPISelLowering.cpp:124
SDValue legalizePackedAVL(SDValue Op, VECustomDAG &CDAG) const
Definition VVPISelLowering.cpp:403
SDValue splitPackedLoadStore(SDValue Op, VECustomDAG &CDAG) const
Definition VVPISelLowering.cpp:183
SDValue legalizeInternalVectorOp(SDValue Op, SelectionDAG &DAG) const
Definition VVPISelLowering.cpp:330
SDValue splitVectorOp(SDValue Op, VECustomDAG &CDAG) const
Definition VVPISelLowering.cpp:351
SDValue legalizeInternalLoadStoreOp(SDValue Op, VECustomDAG &CDAG) const
Definition VVPISelLowering.cpp:318
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADD
Simple integer binary arithmetic operators.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
This is an optimization pass for GlobalISel generic memory operations.
bool isVVPReductionOp(unsigned Opcode)
bool isPackedVectorType(EVT SomeVT)
bool supportsPackedMode(unsigned Opcode, EVT IdiomVT)
std::optional< int > getAVLPos(unsigned Opc)
The VE backend uses a two-staged process to lower and legalize vector instructions:
SDValue getGatherScatterScale(SDValue Op)
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
SDValue getStoredValue(SDValue Op)
bool isVVPBinaryOp(unsigned VVPOpcode)
std::optional< EVT > getIdiomaticVectorType(SDNode *Op)
} AVL Functions
SDValue getNodeChain(SDValue Op)
Node Properties {.
SDValue getNodeAVL(SDValue Op)
} Node Properties
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isLegalAVL(SDValue AVL)
MVT splitVectorType(MVT VT)
SDValue getNodePassthru(SDValue Op)
FunctionAddr VTableAddr uintptr_t uintptr_t Data
bool maySafelyIgnoreMask(SDValue Op)
bool isVVPOrVEC(unsigned Opcode)
MVT getLegalVectorType(Packing P, MVT ElemVT)
SDValue getMemoryPtr(SDValue Op)
std::optional< int > getMaskPos(unsigned Opc)
std::pair< SDValue, bool > getAnnotatedNodeAVL(SDValue Op)
DWARFExpression::Operation Op
bool hasReductionStartParam(unsigned OPC)
SDValue getGatherScatterIndex(SDValue Op)
Packing getTypePacking(EVT VT)
std::optional< unsigned > getVVPOpcode(unsigned Opcode)
bool isVVPUnaryOp(unsigned VVPOpcode)
SDValue getNodeMask(SDValue Op)
SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG)
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.