1414#include " SPIRV.h"
1515#include " SPIRVGlobalRegistry.h"
1616#include " SPIRVSubtarget.h"
17+ #include " llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
1718#include " llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1819#include " llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1920#include " llvm/CodeGen/MachineInstr.h"
2021#include " llvm/CodeGen/MachineRegisterInfo.h"
2122#include " llvm/CodeGen/TargetOpcodes.h"
23+ #include " llvm/IR/IntrinsicsSPIRV.h"
2224
2325using namespace llvm ;
2426using namespace llvm ::LegalizeActions;
@@ -101,6 +103,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
101103 v4s64, v8s1, v8s8, v8s16, v8s32, v8s64, v16s1,
102104 v16s8, v16s16, v16s32, v16s64};
103105
106+ auto allShaderVectors = {v2s1, v2s8, v2s16, v2s32, v2s64,
107+ v3s1, v3s8, v3s16, v3s32, v3s64,
108+ v4s1, v4s8, v4s16, v4s32, v4s64};
109+
104110 auto allScalarsAndVectors = {
105111 s1, s8, s16, s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64,
106112 v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64,
@@ -126,6 +132,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
126132
127133 auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11, p12};
128134
135+ auto &allowedVectorTypes = ST.isShader () ? allShaderVectors : allVectors;
136+
129137 bool IsExtendedInts =
130138 ST.canUseExtension (
131139 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
@@ -148,14 +156,63 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
148156 return IsExtendedInts && Ty.isValid ();
149157 };
150158
151- for (auto Opc : getTypeFoldingSupportedOpcodes ())
152- getActionDefinitionsBuilder (Opc).custom ();
159+ uint32_t MaxVectorSize = ST.isShader () ? 4 : 16 ;
160+
161+ for (auto Opc : getTypeFoldingSupportedOpcodes ()) {
162+ if (Opc != G_EXTRACT_VECTOR_ELT)
163+ getActionDefinitionsBuilder (Opc).custom ();
164+ }
153165
154- getActionDefinitionsBuilder (G_GLOBAL_VALUE).alwaysLegal ();
166+ getActionDefinitionsBuilder (G_SHUFFLE_VECTOR)
167+ .legalForCartesianProduct (allowedVectorTypes, allowedVectorTypes)
168+ .moreElementsToNextPow2 (0 )
169+ .lowerIf (vectorElementCountIsGreaterThan (0 , MaxVectorSize))
170+ .moreElementsToNextPow2 (1 )
171+ .lowerIf (vectorElementCountIsGreaterThan (1 , MaxVectorSize))
172+ .alwaysLegal ();
155173
156- // TODO: add proper rules for vectors legalization.
157- getActionDefinitionsBuilder (
158- {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR})
174+ getActionDefinitionsBuilder (G_EXTRACT_VECTOR_ELT)
175+ .legalIf (vectorElementCountIsLessThanOrEqualTo (1 , MaxVectorSize))
176+ .moreElementsToNextPow2 (1 )
177+ .fewerElementsIf (vectorElementCountIsGreaterThan (1 , MaxVectorSize),
178+ LegalizeMutations::changeElementCountTo (
179+ 1 , ElementCount::getFixed (MaxVectorSize)))
180+ .custom ();
181+
182+ // Illegal G_UNMERGE_VALUES instructions should be handled
183+ // during the combine phase.
184+ getActionDefinitionsBuilder (G_BUILD_VECTOR)
185+ .legalIf (vectorElementCountIsLessThanOrEqualTo (0 , MaxVectorSize))
186+ .fewerElementsIf (vectorElementCountIsGreaterThan (0 , MaxVectorSize),
187+ LegalizeMutations::changeElementCountTo (
188+ 0 , ElementCount::getFixed (MaxVectorSize)));
189+
190+ // When entering the legalizer, there should be no G_BITCAST instructions.
191+ // They should all be calls to the `spv_bitcast` intrinsic. The call to
192+ // the intrinsic will be converted to a G_BITCAST during legalization if
193+ // the vectors are not legal. After using the rules to legalize a G_BITCAST,
194+ // we turn it back into a call to the intrinsic with a custom ruel to avoid
195+ // potential machines verifier failures.
196+ getActionDefinitionsBuilder (G_BITCAST)
197+ .moreElementsToNextPow2 (0 )
198+ .moreElementsToNextPow2 (1 )
199+ .fewerElementsIf (vectorElementCountIsGreaterThan (0 , MaxVectorSize),
200+ LegalizeMutations::changeElementCountTo (
201+ 0 , ElementCount::getFixed (MaxVectorSize)))
202+ .lowerIf (vectorElementCountIsGreaterThan (1 , MaxVectorSize))
203+ .custom ();
204+
205+ getActionDefinitionsBuilder (G_CONCAT_VECTORS)
206+ .legalIf (vectorElementCountIsLessThanOrEqualTo (0 , MaxVectorSize))
207+ .moreElementsToNextPow2 (0 )
208+ .lowerIf (vectorElementCountIsGreaterThan (0 , MaxVectorSize))
209+ .alwaysLegal ();
210+
211+ getActionDefinitionsBuilder (G_SPLAT_VECTOR)
212+ .legalIf (vectorElementCountIsLessThanOrEqualTo (0 , MaxVectorSize))
213+ .moreElementsToNextPow2 (0 )
214+ .fewerElementsIf (vectorElementCountIsGreaterThan (0 , MaxVectorSize),
215+ LegalizeMutations::changeElementSizeTo (0 , MaxVectorSize))
159216 .alwaysLegal ();
160217
161218 // Vector Reduction Operations
@@ -164,17 +221,18 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
164221 G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
165222 G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
166223 G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
167- .legalFor (allVectors )
224+ .legalFor (allowedVectorTypes )
168225 .scalarize (1 )
169226 .lower ();
170227
171228 getActionDefinitionsBuilder ({G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL})
172229 .scalarize (2 )
173230 .lower ();
174231
175- // Merge/Unmerge
176- // TODO: add proper legalization rules.
177- getActionDefinitionsBuilder (G_UNMERGE_VALUES).alwaysLegal ();
232+ // Illegal G_UNMERGE_VALUES instructions should be handled
233+ // during the combine phase.
234+ getActionDefinitionsBuilder (G_UNMERGE_VALUES)
235+ .legalIf (vectorElementCountIsLessThanOrEqualTo (1 , MaxVectorSize));
178236
179237 getActionDefinitionsBuilder ({G_MEMCPY, G_MEMMOVE})
180238 .legalIf (all (typeInSet (0 , allPtrs), typeInSet (1 , allPtrs)));
@@ -287,6 +345,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
287345 // Pointer-handling.
288346 getActionDefinitionsBuilder (G_FRAME_INDEX).legalFor ({p0});
289347
348+ getActionDefinitionsBuilder (G_GLOBAL_VALUE).legalFor (allPtrs);
349+
290350 // Control-flow. In some cases (e.g. constants) s1 may be promoted to s32.
291351 getActionDefinitionsBuilder (G_BRCOND).legalFor ({s1, s32});
292352
@@ -374,6 +434,11 @@ bool SPIRVLegalizerInfo::legalizeCustom(
374434 default :
375435 // TODO: implement legalization for other opcodes.
376436 return true ;
437+ case TargetOpcode::G_BITCAST:
438+ return legalizeBitcast (Helper, MI);
439+ case TargetOpcode::G_INTRINSIC:
440+ return legalizeIntrinsic (Helper, MI);
441+
377442 case TargetOpcode::G_IS_FPCLASS:
378443 return legalizeIsFPClass (Helper, MI, LocObserver);
379444 case TargetOpcode::G_ICMP: {
@@ -400,6 +465,44 @@ bool SPIRVLegalizerInfo::legalizeCustom(
400465 }
401466}
402467
468+ bool SPIRVLegalizerInfo::legalizeIntrinsic (LegalizerHelper &Helper,
469+ MachineInstr &MI) const {
470+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder ;
471+ MachineRegisterInfo &MRI = *MIRBuilder.getMRI ();
472+ const SPIRVSubtarget &ST = MI.getMF ()->getSubtarget <SPIRVSubtarget>();
473+
474+ auto IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID ();
475+ if (IntrinsicID == Intrinsic::spv_bitcast) {
476+ Register DstReg = MI.getOperand (0 ).getReg ();
477+ Register SrcReg = MI.getOperand (2 ).getReg ();
478+ LLT DstTy = MRI.getType (DstReg);
479+ LLT SrcTy = MRI.getType (SrcReg);
480+
481+ int32_t MaxVectorSize = ST.isShader () ? 4 : 16 ;
482+ bool isLongVector =
483+ (DstTy.isVector () && DstTy.getNumElements () > MaxVectorSize) ||
484+ (SrcTy.isVector () && SrcTy.getNumElements () > MaxVectorSize);
485+
486+ if (isLongVector) {
487+ MIRBuilder.buildBitcast (DstReg, SrcReg);
488+ MI.eraseFromParent ();
489+ }
490+ return true ;
491+ }
492+ return true ;
493+ }
494+
495+ bool SPIRVLegalizerInfo::legalizeBitcast (LegalizerHelper &Helper,
496+ MachineInstr &MI) const {
497+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder ;
498+ Register DstReg = MI.getOperand (0 ).getReg ();
499+ Register SrcReg = MI.getOperand (1 ).getReg ();
500+ SmallVector<Register, 1 > DstRegs = {DstReg};
501+ MIRBuilder.buildIntrinsic (Intrinsic::spv_bitcast, DstRegs).addUse (SrcReg);
502+ MI.eraseFromParent ();
503+ return true ;
504+ }
505+
403506// Note this code was copied from LegalizerHelper::lowerISFPCLASS and adjusted
404507// to ensure that all instructions created during the lowering have SPIR-V types
405508// assigned to them.
0 commit comments