LLVM: lib/Target/SPIRV/SPIRVLegalizerInfo.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
22
23using namespace llvm;
26
27
29 TargetOpcode::G_ADD,
30 TargetOpcode::G_FADD,
31 TargetOpcode::G_STRICT_FADD,
32 TargetOpcode::G_SUB,
33 TargetOpcode::G_FSUB,
34 TargetOpcode::G_STRICT_FSUB,
35 TargetOpcode::G_MUL,
36 TargetOpcode::G_FMUL,
37 TargetOpcode::G_STRICT_FMUL,
38 TargetOpcode::G_SDIV,
39 TargetOpcode::G_UDIV,
40 TargetOpcode::G_FDIV,
41 TargetOpcode::G_STRICT_FDIV,
42 TargetOpcode::G_SREM,
43 TargetOpcode::G_UREM,
44 TargetOpcode::G_FREM,
45 TargetOpcode::G_STRICT_FREM,
46 TargetOpcode::G_FNEG,
47 TargetOpcode::G_CONSTANT,
48 TargetOpcode::G_FCONSTANT,
49 TargetOpcode::G_AND,
50 TargetOpcode::G_OR,
51 TargetOpcode::G_XOR,
52 TargetOpcode::G_SHL,
53 TargetOpcode::G_ASHR,
54 TargetOpcode::G_LSHR,
55 TargetOpcode::G_SELECT,
56 TargetOpcode::G_EXTRACT_VECTOR_ELT,
57};
58
59
62}
63
65 return [IsExtendedInts, TypeIdx](const LegalityQuery &Query) {
66 const LLT Ty = Query.Types[TypeIdx];
68 };
69}
70
72 using namespace TargetOpcode;
73
74 this->ST = &ST;
75 GR = ST.getSPIRVGlobalRegistry();
76
82
88
94
100
106
112
113 const unsigned PSize = ST.getPointerSize();
116 const LLT p2 = LLT::pointer(2, PSize);
119 const LLT p5 =
120 LLT::pointer(5, PSize);
121 const LLT p6 = LLT::pointer(6, PSize);
125
126
127 auto allPtrsScalarsAndVectors = {
128 p0, p1, p2, p3, p4, p5, p6, p7, p8, p10,
129 s1, s8, s16, s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64,
130 v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64,
131 v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
132
133 auto allVectors = {v2s1, v2s8, v2s16, v2s32, v2s64, v3s1, v3s8,
134 v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32,
135 v4s64, v8s1, v8s8, v8s16, v8s32, v8s64, v16s1,
136 v16s8, v16s16, v16s32, v16s64};
137
138 auto allScalarsAndVectors = {
139 s1, s8, s16, s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64,
140 v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64,
141 v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
142
143 auto allIntScalarsAndVectors = {s8, s16, s32, s64, v2s8, v2s16,
144 v2s32, v2s64, v3s8, v3s16, v3s32, v3s64,
145 v4s8, v4s16, v4s32, v4s64, v8s8, v8s16,
146 v8s32, v8s64, v16s8, v16s16, v16s32, v16s64};
147
148 auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1};
149
150 auto allIntScalars = {s8, s16, s32, s64};
151
152 auto allFloatScalars = {s16, s32, s64};
153
154 auto allFloatScalarsAndVectors = {
155 s16, s32, s64, v2s16, v2s32, v2s64, v3s16, v3s32, v3s64,
156 v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
157
158 auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2,
159 p3, p4, p5, p6, p7, p8, p10};
160
161 auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10};
162
163 bool IsExtendedInts =
164 ST.canUseExtension(
165 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
166 ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
167 auto extendedScalarsAndVectors =
169 const LLT Ty = Query.Types[0];
171 };
172 auto extendedScalarsAndVectorsProduct = [IsExtendedInts](
174 const LLT Ty1 = Query.Types[0], Ty2 = Query.Types[1];
175 return IsExtendedInts && Ty1.isValid() && Ty2.isValid() &&
177 };
178 auto extendedPtrsScalarsAndVectors =
180 const LLT Ty = Query.Types[0];
181 return IsExtendedInts && Ty.isValid();
182 };
183
186
188
189
191 {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR})
192 .alwaysLegal();
193
194
196 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
197 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
198 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
199 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
200 .legalFor(allVectors)
203
206 .lower();
207
208
209
211
214
217
220
222
224 G_BITREVERSE, G_SADDSAT, G_UADDSAT, G_SSUBSAT,
225 G_USUBSAT, G_SCMP, G_UCMP})
226 .legalFor(allIntScalarsAndVectors)
227 .legalIf(extendedScalarsAndVectors);
228
230 .legalFor(allFloatScalarsAndVectors);
231
234
236 .legalForCartesianProduct(allIntScalarsAndVectors,
237 allFloatScalarsAndVectors);
238
240 .legalForCartesianProduct(allFloatScalarsAndVectors,
241 allScalarsAndVectors);
242
245 .legalIf(extendedScalarsAndVectorsProduct);
246
247
249 .legalForCartesianProduct(allScalarsAndVectors)
250 .legalIf(extendedScalarsAndVectorsProduct);
251
253 .legalFor(allPtrsScalarsAndVectors)
254 .legalIf(extendedPtrsScalarsAndVectors);
255
258 typeInSet(1, allPtrsScalarsAndVectors)));
259
261
263
276
277
278
281 typeInSet(1, allPtrsScalarsAndVectors)));
282
285 typeInSet(1, allFloatScalarsAndVectors)));
286
288 G_ATOMICRMW_MAX, G_ATOMICRMW_MIN,
289 G_ATOMICRMW_SUB, G_ATOMICRMW_XOR,
290 G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN})
291 .legalForCartesianProduct(allIntScalars, allPtrs);
292
294 {G_ATOMICRMW_FADD, G_ATOMICRMW_FSUB, G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
295 .legalForCartesianProduct(allFloatScalars, allPtrs);
296
299
301
303
305 {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO})
306 .alwaysLegal();
307
308
310 .legalForCartesianProduct(allFloatScalarsAndVectors);
311
312
314
315
317
318
319
320
321
323 G_FPOW,
324 G_FEXP,
325 G_FEXP2,
326 G_FLOG,
327 G_FLOG2,
328 G_FLOG10,
329 G_FABS,
330 G_FMINNUM,
331 G_FMAXNUM,
332 G_FCEIL,
333 G_FCOS,
334 G_FSIN,
335 G_FTAN,
336 G_FACOS,
337 G_FASIN,
338 G_FATAN,
339 G_FATAN2,
340 G_FCOSH,
341 G_FSINH,
342 G_FTANH,
343 G_FSQRT,
344 G_FFLOOR,
345 G_FRINT,
346 G_FNEARBYINT,
347 G_INTRINSIC_ROUND,
348 G_INTRINSIC_TRUNC,
349 G_FMINIMUM,
350 G_FMAXIMUM,
351 G_INTRINSIC_ROUNDEVEN})
352 .legalFor(allFloatScalarsAndVectors);
353
356 allFloatScalarsAndVectors);
357
359 allFloatScalarsAndVectors, allIntScalarsAndVectors);
360
361 if (ST.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
363 {G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTLZ, G_CTLZ_ZERO_UNDEF})
364 .legalForCartesianProduct(allIntScalarsAndVectors,
365 allIntScalarsAndVectors);
366
367
369 }
370
372 verify(*ST.getInstrInfo());
373}
374
379 Register ConvReg = MRI.createGenericVirtualRegister(ConvTy);
385 return ConvReg;
386}
387
391 auto Opc = MI.getOpcode();
394 assert(Opc == TargetOpcode::G_ICMP);
396 auto &Op0 = MI.getOperand(2);
397 auto &Op1 = MI.getOperand(3);
398 Register Reg0 = Op0.getReg();
399 Register Reg1 = Op1.getReg();
404 MRI.getType(Reg0).isPointer() && MRI.getType(Reg1).isPointer()) {
411 }
412 return true;
413 }
414
415 return true;
416}
unsigned const MachineRegisterInfo * MRI
static void scalarize(BinaryOperator *BO, SmallVectorImpl< BinaryOperator * > &Replace)
This file declares the MachineIRBuilder class.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isTypeFoldingSupported(unsigned Opcode)
static const std::set< unsigned > TypeFoldingSupportingOpcs
static Register convertPtrToInt(Register Reg, LLT ConvTy, SPIRVType *SpvType, LegalizerHelper &Helper, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR)
bool isTypeFoldingSupported(unsigned Opcode)
LegalityPredicate typeOfExtendedScalars(unsigned TypeIdx, bool IsExtendedInts)
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert = Opcode .
MachineFunction & getMF()
Getter for the function we currently build.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVLegalizerInfo(const SPIRVSubtarget &ST)
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
unsigned getPointerSize() const
bool canDirectlyComparePointers() const
The instances of the Type class are immutable: once they are created, they are never changed.
LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
This is an optimization pass for GlobalISel generic memory operations.
std::function< bool(const LegalityQuery &)> LegalityPredicate
The LegalityQuery object bundles together all the information that's needed to decide whether a given...