@@ -325,6 +325,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
325325 MachineInstr &I) const ;
326326 bool selectFrexp (Register ResVReg, const SPIRVType *ResType,
327327 MachineInstr &I) const ;
328+ bool selectDpdCoarse (Register ResVReg, const SPIRVType *ResType,
329+ MachineInstr &I, const unsigned DPdOpCode) const ;
328330 // Utilities
329331 std::pair<Register, bool >
330332 buildI32Constant (uint32_t Val, MachineInstr &I,
@@ -3099,6 +3101,59 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
30993101 return Result;
31003102}
31013103
3104+ bool SPIRVInstructionSelector::selectDpdCoarse (Register ResVReg,
3105+ const SPIRVType *ResType,
3106+ MachineInstr &I,
3107+ const unsigned DPdOpCode) const {
3108+ // If the arg/result types are half then we need to wrap the instr in
3109+ // conversions to float
3110+ // This case occurs because a half arg/result is legal in HLSL but not spirv.
3111+ Register SrcReg = I.getOperand (2 ).getReg ();
3112+ SPIRVType *SrcType = GR.getSPIRVTypeForVReg (SrcReg);
3113+ unsigned BitWidth = std::min (GR.getScalarOrVectorBitWidth (SrcType),
3114+ GR.getScalarOrVectorBitWidth (ResType));
3115+ if (BitWidth == 32 ) {
3116+ return BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (DPdOpCode))
3117+ .addDef (ResVReg)
3118+ .addUse (GR.getSPIRVTypeID (ResType))
3119+ .addUse (I.getOperand (2 ).getReg ());
3120+ } else {
3121+ MachineIRBuilder MIRBuilder (I);
3122+ unsigned componentCount = GR.getScalarOrVectorComponentCount (SrcType);
3123+ SPIRVType *Float32Ty = GR.getOrCreateSPIRVFloatType (32 , I, TII);
3124+ SPIRVType *F32ConvertTy;
3125+ if (componentCount == 1 ) {
3126+ F32ConvertTy = Float32Ty;
3127+ } else {
3128+ F32ConvertTy = GR.getOrCreateSPIRVVectorType (Float32Ty, componentCount,
3129+ MIRBuilder, false );
3130+ }
3131+
3132+ const TargetRegisterClass *RegClass = GR.getRegClass (SrcType);
3133+ Register ConvertToVReg = MRI->createVirtualRegister (RegClass);
3134+ Register DpdOpVReg = MRI->createVirtualRegister (RegClass);
3135+
3136+ bool Result =
3137+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpFConvert))
3138+ .addDef (ConvertToVReg)
3139+ .addUse (GR.getSPIRVTypeID (F32ConvertTy))
3140+ .addUse (SrcReg)
3141+ .constrainAllUses (TII, TRI, RBI);
3142+ Result &= BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (DPdOpCode))
3143+ .addDef (DpdOpVReg)
3144+ .addUse (GR.getSPIRVTypeID (F32ConvertTy))
3145+ .addUse (ConvertToVReg)
3146+ .constrainAllUses (TII, TRI, RBI);
3147+ Result &=
3148+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpFConvert))
3149+ .addDef (ResVReg)
3150+ .addUse (GR.getSPIRVTypeID (ResType))
3151+ .addUse (DpdOpVReg)
3152+ .constrainAllUses (TII, TRI, RBI);
3153+ return Result;
3154+ }
3155+ }
3156+
31023157bool SPIRVInstructionSelector::selectIntrinsic (Register ResVReg,
31033158 const SPIRVType *ResType,
31043159 MachineInstr &I) const {
@@ -3473,18 +3528,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
34733528 return selectResourceNonUniformIndex (ResVReg, ResType, I);
34743529 }
34753530 case Intrinsic::spv_ddx_coarse: {
3476- return BuildMI (*I.getParent (), I, I.getDebugLoc (),
3477- TII.get (SPIRV::OpDPdxCoarse))
3478- .addDef (ResVReg)
3479- .addUse (GR.getSPIRVTypeID (ResType))
3480- .addUse (I.getOperand (2 ).getReg ());
3531+ return selectDpdCoarse (ResVReg, ResType, I, SPIRV::OpDPdxCoarse);
34813532 }
34823533 case Intrinsic::spv_ddy_coarse: {
3483- return BuildMI (*I.getParent (), I, I.getDebugLoc (),
3484- TII.get (SPIRV::OpDPdyCoarse))
3485- .addDef (ResVReg)
3486- .addUse (GR.getSPIRVTypeID (ResType))
3487- .addUse (I.getOperand (2 ).getReg ());
3534+ return selectDpdCoarse (ResVReg, ResType, I, SPIRV::OpDPdyCoarse);
34883535 }
34893536 default : {
34903537 std::string DiagMsg;
0 commit comments