@@ -3179,11 +3179,26 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) {
31793179 ((Opcode == Instruction::FNeg || Opcode == Instruction::FCmp ||
31803180 BV->isExtInst ()) &&
31813181 BM->isAllowedToUseVersion (VersionNumber::SPIRV_1_6))) {
3182+ bool AllowFloatControls2 =
3183+ BM->isAllowedToUseExtension (ExtensionID::SPV_KHR_float_controls2);
3184+ bool AllowIntelFpFastMathMode =
3185+ BM->isAllowedToUseExtension (ExtensionID::SPV_INTEL_fp_fast_math_mode);
31823186 FastMathFlags FMF = BVF->getFastMathFlags ();
31833187 SPIRVWord M{0 };
3184- if (FMF.isFast ())
3185- M |= FPFastMathModeFastMask;
3186- else {
3188+ if (FMF.isFast ()) {
3189+ if (AllowFloatControls2) {
3190+ // When SPV_KHR_float_controls2 is used, setting the fast math flag
3191+ // bit is deprecated. Set the rest of the bits instead.
3192+ M |= FPFastMathModeNotNaNMask | FPFastMathModeNotInfMask |
3193+ FPFastMathModeNSZMask | FPFastMathModeAllowRecipMask |
3194+ FPFastMathModeAllowTransformMask |
3195+ FPFastMathModeAllowReassocMask | FPFastMathModeAllowContractMask;
3196+ BM->addCapability (CapabilityFloatControls2);
3197+ BM->addExtension (ExtensionID::SPV_KHR_float_controls2);
3198+ } else {
3199+ M |= FPFastMathModeFastMask;
3200+ }
3201+ } else {
31873202 if (FMF.noNaNs ())
31883203 M |= FPFastMathModeNotNaNMask;
31893204 if (FMF.noInfs ())
@@ -3192,14 +3207,31 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) {
31923207 M |= FPFastMathModeNSZMask;
31933208 if (FMF.allowReciprocal ())
31943209 M |= FPFastMathModeAllowRecipMask;
3195- if (BM->isAllowedToUseExtension (
3196- ExtensionID::SPV_INTEL_fp_fast_math_mode)) {
3197- if (FMF.allowContract ()) {
3198- M |= FPFastMathModeAllowContractFastINTELMask;
3199- BM->addCapability (CapabilityFPFastMathModeINTEL);
3200- BM->addExtension (ExtensionID::SPV_INTEL_fp_fast_math_mode);
3210+ if (FMF.allowContract ()) {
3211+ if (AllowFloatControls2 || AllowIntelFpFastMathMode) {
3212+ static_assert (FPFastMathModeAllowContractFastINTELMask ==
3213+ FPFastMathModeAllowContractMask);
3214+ M |= FPFastMathModeAllowContractMask;
3215+ BM->addCapability (AllowFloatControls2
3216+ ? CapabilityFloatControls2
3217+ : CapabilityFPFastMathModeINTEL);
3218+ BM->addExtension (AllowFloatControls2
3219+ ? ExtensionID::SPV_KHR_float_controls2
3220+ : ExtensionID::SPV_INTEL_fp_fast_math_mode);
32013221 }
3202- if (FMF.allowReassoc ()) {
3222+ }
3223+ if (FMF.allowReassoc ()) {
3224+ if (AllowFloatControls2) {
3225+ // LLVM reassoc maps to SPIRV transform, see
3226+ // https://github.com/KhronosGroup/SPIRV-Registry/issues/326 for
3227+ // details. Because we are enabling AllowTransform, we must enable
3228+ // AllowReassoc and AllowContract too, as required by SPIRV spec.
3229+ M |= FPFastMathModeAllowTransformMask |
3230+ FPFastMathModeAllowReassocMask |
3231+ FPFastMathModeAllowContractMask;
3232+ BM->addCapability (CapabilityFloatControls2);
3233+ BM->addExtension (ExtensionID::SPV_KHR_float_controls2);
3234+ } else if (AllowIntelFpFastMathMode) {
32033235 M |= FPFastMathModeAllowReassocINTELMask;
32043236 BM->addCapability (CapabilityFPFastMathModeINTEL);
32053237 BM->addExtension (ExtensionID::SPV_INTEL_fp_fast_math_mode);
@@ -6421,8 +6453,10 @@ bool LLVMToSPIRVBase::transExecutionMode() {
64216453
64226454 switch (EMode) {
64236455 case spv::ExecutionModeContractionOff:
6424- BF->addExecutionMode (BM->add (new SPIRVExecutionMode (
6425- OpExecutionMode, BF, static_cast <ExecutionMode>(EMode))));
6456+ // With SPV_KHR_float_controls2 this is deprecated
6457+ if (!BM->hasCapability (CapabilityFloatControls2))
6458+ BF->addExecutionMode (BM->add (new SPIRVExecutionMode (
6459+ OpExecutionMode, BF, static_cast <ExecutionMode>(EMode))));
64266460 break ;
64276461 case spv::ExecutionModeInitializer:
64286462 case spv::ExecutionModeFinalizer:
@@ -6509,9 +6543,13 @@ bool LLVMToSPIRVBase::transExecutionMode() {
65096543 BM->addCapability (CapabilityVectorComputeINTEL);
65106544 } break ;
65116545
6546+ case spv::ExecutionModeSignedZeroInfNanPreserve:
6547+ // With SPV_KHR_float_controls2 this is deprecated
6548+ if (BM->hasCapability (CapabilityFloatControls2))
6549+ break ;
6550+ [[fallthrough]];
65126551 case spv::ExecutionModeDenormPreserve:
65136552 case spv::ExecutionModeDenormFlushToZero:
6514- case spv::ExecutionModeSignedZeroInfNanPreserve:
65156553 case spv::ExecutionModeRoundingModeRTE:
65166554 case spv::ExecutionModeRoundingModeRTZ: {
65176555 if (BM->isAllowedToUseVersion (VersionNumber::SPIRV_1_4)) {
@@ -6550,6 +6588,10 @@ bool LLVMToSPIRVBase::transExecutionMode() {
65506588}
65516589
65526590void LLVMToSPIRVBase::transFPContract () {
6591+ // SPV_KHR_float_controls2 deprecates ContractionOff.
6592+ if (BM->hasCapability (CapabilityFloatControls2))
6593+ return ;
6594+
65536595 FPContractMode Mode = BM->getFPContractMode ();
65546596
65556597 for (Function &F : *M) {
0 commit comments