@@ -296,7 +296,22 @@ class SPIRVInstructionSelector : public InstructionSelector {
296296 bool selectImageWriteIntrinsic (MachineInstr &I) const ;
297297 bool selectResourceGetPointer (Register &ResVReg, const SPIRVType *ResType,
298298 MachineInstr &I) const ;
299-
299+ bool selectGetSpecializationConstant (Register &ResVReg,
300+ const SPIRVType *ResType,
301+ MachineInstr &I) const ;
302+
303+ bool buildSpecConstant (llvm::MachineInstr &I, llvm::Register &ResVReg,
304+ llvm::SPIRVType *ResType,
305+ llvm::APInt &DefaultValue) const ;
306+
307+ APInt getSpecConstantDefaultValue (llvm::MachineInstr &I) const ;
308+
309+ bool buildBoolSpecConstant (Register &ResVReg, const SPIRVType *ResType,
310+ bool DefaultValue, MachineInstr &I) const ;
311+ bool buildIntegerSpecConstant (Register &ResVReg, const SPIRVType *ResType,
312+ uint32_t DefaultValue, MachineInstr &I) const ;
313+ bool buildIntegerSpecConstant (Register &ResVReg, const SPIRVType *ResType,
314+ uint64_t DefaultValue, MachineInstr &I) const ;
300315 // Utilities
301316 std::pair<Register, bool >
302317 buildI32Constant (uint32_t Val, MachineInstr &I,
@@ -3192,6 +3207,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
31923207 case Intrinsic::spv_resource_getpointer: {
31933208 return selectResourceGetPointer (ResVReg, ResType, I);
31943209 }
3210+ case Intrinsic::spv_get_specialization_constant: {
3211+ return selectGetSpecializationConstant (ResVReg, ResType, I);
3212+ }
31953213 case Intrinsic::spv_discard: {
31963214 return selectDiscard (ResVReg, ResType, I);
31973215 }
@@ -3309,6 +3327,84 @@ bool SPIRVInstructionSelector::selectResourceGetPointer(
33093327 .constrainAllUses (TII, TRI, RBI);
33103328}
33113329
3330+ bool SPIRVInstructionSelector::buildBoolSpecConstant (Register &ResVReg,
3331+ const SPIRVType *ResType,
3332+ bool DefaultValue,
3333+ MachineInstr &I) const {
3334+ uint32_t Opc =
3335+ DefaultValue ? SPIRV::OpSpecConstantTrue : SPIRV::OpSpecConstantFalse;
3336+ return BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (Opc))
3337+ .addDef (ResVReg)
3338+ .addUse (GR.getSPIRVTypeID (ResType))
3339+ .constrainAllUses (TII, TRI, RBI);
3340+ }
3341+
3342+ bool SPIRVInstructionSelector::buildIntegerSpecConstant (
3343+ Register &ResVReg, const SPIRVType *ResType, uint32_t DefaultValue,
3344+ MachineInstr &I) const {
3345+ return BuildMI (*I.getParent (), I, I.getDebugLoc (),
3346+ TII.get (SPIRV::OpSpecConstant))
3347+ .addDef (ResVReg)
3348+ .addUse (GR.getSPIRVTypeID (ResType))
3349+ .addImm (DefaultValue)
3350+ .constrainAllUses (TII, TRI, RBI);
3351+ }
3352+
3353+ bool SPIRVInstructionSelector::buildIntegerSpecConstant (
3354+ Register &ResVReg, const SPIRVType *ResType, uint64_t DefaultValue,
3355+ MachineInstr &I) const {
3356+ return BuildMI (*I.getParent (), I, I.getDebugLoc (),
3357+ TII.get (SPIRV::OpSpecConstant))
3358+ .addDef (ResVReg)
3359+ .addUse (GR.getSPIRVTypeID (ResType))
3360+ .addImm (DefaultValue & 0xFFFFFFFF )
3361+ .addImm (DefaultValue >> 32 )
3362+ .constrainAllUses (TII, TRI, RBI);
3363+ }
3364+
3365+ bool SPIRVInstructionSelector::selectGetSpecializationConstant (
3366+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
3367+ uint32_t Id = foldImm (I.getOperand (2 ), MRI);
3368+ bool R = false ;
3369+ APInt DefaultValue = getSpecConstantDefaultValue (I);
3370+ if (ResType->getOpcode () == SPIRV::OpTypeBool) {
3371+ R = buildBoolSpecConstant (ResVReg, ResType, DefaultValue.getBoolValue (), I);
3372+ } else {
3373+ R = buildSpecConstant (I, ResVReg, ResType, DefaultValue);
3374+ }
3375+ if (!R) {
3376+ return false ;
3377+ }
3378+ buildOpDecorate (ResVReg, I, TII, SPIRV::Decoration::SpecId, {Id});
3379+ return R;
3380+ }
3381+
3382+ bool SPIRVInstructionSelector::buildSpecConstant (
3383+ llvm::MachineInstr &I, llvm::Register &ResVReg, llvm::SPIRVType *ResType,
3384+ llvm::APInt &DefaultValue) const {
3385+ auto MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (),
3386+ TII.get (SPIRV::OpSpecConstant))
3387+ .addDef (ResVReg)
3388+ .addUse (GR.getSPIRVTypeID (ResType));
3389+ addNumImm (DefaultValue, MIB);
3390+ return MIB.constrainAllUses (TII, TRI, RBI);
3391+ }
3392+
3393+ APInt SPIRVInstructionSelector::getSpecConstantDefaultValue (
3394+ llvm::MachineInstr &I) const {
3395+ APInt DefaultValue;
3396+ Register DefaultValueReg = I.getOperand (3 ).getReg ();
3397+ auto *D = getDefInstrMaybeConstant (DefaultValueReg, MRI);
3398+ const auto &MO = D->getOperand (1 );
3399+ if (MO.isCImm ()) {
3400+ DefaultValue = MO.getCImm ()->getValue ();
3401+ } else {
3402+ assert (MO.isFPImm () && " " );
3403+ DefaultValue = MO.getFPImm ()->getValue ().bitcastToAPInt ();
3404+ }
3405+ return DefaultValue;
3406+ }
3407+
33123408bool SPIRVInstructionSelector::extractSubvector (
33133409 Register &ResVReg, const SPIRVType *ResType, Register &ReadReg,
33143410 MachineInstr &InsertionPoint) const {
0 commit comments