Skip to content

Commit 394d9f2

Browse files
committed
Implement extension SPV_KHR_float_controls2
With this extension, the execution modes `ContractionOff and `SignedZeroInfNanPreserve` are deprecated and we should use `FPFastMathDefault` instead. Additionally, the `FPFastMathMode` mode `Fast` bit is also deprecated.
1 parent fedea4b commit 394d9f2

File tree

14 files changed

+303
-56
lines changed

14 files changed

+303
-56
lines changed

include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,4 @@ EXT(SPV_INTEL_predicated_io)
8989
EXT(SPV_INTEL_sigmoid)
9090
EXT(SPV_INTEL_float4)
9191
EXT(SPV_INTEL_fp_conversions)
92+
EXT(SPV_KHR_float_controls2)

lib/SPIRV/SPIRVReader.cpp

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,26 +1218,22 @@ static void applyNoIntegerWrapDecorations(const SPIRVValue *BV,
12181218
}
12191219
}
12201220

1221-
static void applyFPFastMathModeDecorations(const SPIRVValue *BV,
1222-
Instruction *Inst) {
1223-
SPIRVWord V;
1224-
FastMathFlags FMF;
1221+
void SPIRVToLLVM::applyFPFastMathModeDecorations(const SPIRVValue *BV,
1222+
Instruction *Inst) {
1223+
if (!isa<FPMathOperator>(Inst))
1224+
return;
1225+
1226+
SPIRVWord V{0};
12251227
if (BV->hasDecorate(DecorationFPFastMathMode, 0, &V)) {
1226-
if (V & FPFastMathModeNotNaNMask)
1227-
FMF.setNoNaNs();
1228-
if (V & FPFastMathModeNotInfMask)
1229-
FMF.setNoInfs();
1230-
if (V & FPFastMathModeNSZMask)
1231-
FMF.setNoSignedZeros();
1232-
if (V & FPFastMathModeAllowRecipMask)
1233-
FMF.setAllowReciprocal();
1234-
if (V & FPFastMathModeAllowContractFastINTELMask)
1235-
FMF.setAllowContract();
1236-
if (V & FPFastMathModeAllowReassocINTELMask)
1237-
FMF.setAllowReassoc();
1238-
if (V & FPFastMathModeFastMask)
1239-
FMF.setFast();
1228+
FastMathFlags FMF = translateFastMathFlags(V);
12401229
Inst->setFastMathFlags(FMF);
1230+
return;
1231+
}
1232+
1233+
SPIRVWord TypeId = BV->getType()->getId();
1234+
auto Func2FMF = Func2FastMathFlags.find({Inst->getFunction(), TypeId});
1235+
if (Func2FMF != Func2FastMathFlags.end()) {
1236+
Inst->setFastMathFlags(Func2FMF->second);
12411237
}
12421238
}
12431239

@@ -3443,6 +3439,58 @@ static void validatePhiPredecessors(Function *F) {
34433439
}
34443440
} // namespace
34453441

3442+
FastMathFlags SPIRVToLLVM::translateFastMathFlags(SPIRVWord V) const {
3443+
FastMathFlags FMF;
3444+
if (V & FPFastMathModeNotNaNMask)
3445+
FMF.setNoNaNs();
3446+
if (V & FPFastMathModeNotInfMask)
3447+
FMF.setNoInfs();
3448+
if (V & FPFastMathModeNSZMask)
3449+
FMF.setNoSignedZeros();
3450+
if (V & FPFastMathModeAllowRecipMask)
3451+
FMF.setAllowReciprocal();
3452+
static_assert(FPFastMathModeAllowContractFastINTELMask ==
3453+
FPFastMathModeAllowContractMask);
3454+
if (V & FPFastMathModeAllowContractFastINTELMask)
3455+
FMF.setAllowContract();
3456+
static_assert(FPFastMathModeAllowReassocINTELMask ==
3457+
FPFastMathModeAllowReassocMask);
3458+
if (V & FPFastMathModeAllowReassocINTELMask)
3459+
FMF.setAllowReassoc();
3460+
// There is no FPFastMathMode flag that represents LLVM approxiamte functions
3461+
// flag `afn`. Even the FPFastMathMode Fast flag should not imply it, but to
3462+
// avoid changing the previous behaviour we make it equivalent to LLVM's.
3463+
if (V & FPFastMathModeFastMask)
3464+
FMF.setFast();
3465+
if (V & FPFastMathModeAllowTransformMask) {
3466+
// AllowTransform requires the AllowContract and AllowReassoc bits to be
3467+
// set.
3468+
assert(FMF.allowContract() && FMF.allowReassoc() &&
3469+
"The FPFastMathMode AllowTransform requires AllowContract and "
3470+
"AllowReassoc to be set");
3471+
}
3472+
3473+
return FMF;
3474+
}
3475+
3476+
void SPIRVToLLVM::parseFloatControls2ExecutionModeId(SPIRVFunction *BF,
3477+
Function *F) {
3478+
3479+
auto [Begin, End] =
3480+
BF->getExecutionModeRange(spv::ExecutionModeFPFastMathDefault);
3481+
if (Begin == End)
3482+
return;
3483+
3484+
for (auto [_, EM] : make_range(Begin, End)) {
3485+
const auto &Literals = EM->getLiterals();
3486+
assert(Literals.size() == 2);
3487+
SPIRVWord FloatTyId = Literals[0];
3488+
SPIRVWord FlagsId = *transIdAsConstant(Literals[1]);
3489+
Func2FastMathFlags.try_emplace({F, FloatTyId},
3490+
translateFastMathFlags(FlagsId));
3491+
}
3492+
}
3493+
34463494
Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF, unsigned AS) {
34473495
auto Loc = FuncMap.find(BF);
34483496
if (Loc != FuncMap.end())
@@ -3494,6 +3542,8 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF, unsigned AS) {
34943542
: CallingConv::SPIR_FUNC);
34953543
transFunctionAttrs(BF, F);
34963544

3545+
parseFloatControls2ExecutionModeId(BF, F);
3546+
34973547
// Creating all basic blocks before creating instructions.
34983548
for (size_t I = 0, E = BF->getNumBasicBlock(); I != E; ++I) {
34993549
transValue(BF->getBasicBlock(I), F, nullptr);

lib/SPIRV/SPIRVReader.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,14 @@ class SPIRVToLLVM : private BuiltinCallHelper {
274274
void
275275
transFunctionPointerCallArgumentAttributes(SPIRVValue *BV, CallInst *CI,
276276
SPIRVTypeFunction *CalledFnTy);
277+
278+
using FunctionAndTypeIdPair = std::pair<Function *, SPIRVWord>;
279+
using FunctionToFastMathFlagsMap =
280+
DenseMap<FunctionAndTypeIdPair, FastMathFlags>;
281+
FunctionToFastMathFlagsMap Func2FastMathFlags;
282+
FastMathFlags translateFastMathFlags(SPIRVWord V) const;
283+
void parseFloatControls2ExecutionModeId(SPIRVFunction *BF, Function *F);
284+
void applyFPFastMathModeDecorations(const SPIRVValue *BV, Instruction *Inst);
277285
}; // class SPIRVToLLVM
278286

279287
} // namespace SPIRV

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

65526590
void 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) {

lib/SPIRV/libSPIRV/SPIRVEntry.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,9 @@ void SPIRVExecutionMode::decode(std::istream &I) {
659659
case ExecutionModeMaxWorkgroupSizeINTEL:
660660
WordLiterals.resize(3);
661661
break;
662+
case ExecutionModeFPFastMathDefault:
663+
WordLiterals.resize(2);
664+
break;
662665
case ExecutionModeInvocations:
663666
case ExecutionModeOutputVertices:
664667
case ExecutionModeVecTypeHint:

lib/SPIRV/libSPIRV/SPIRVEntry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,9 @@ class SPIRVCapability : public SPIRVEntryNoId<OpCapability> {
893893
case CapabilityGroupNonUniformClustered:
894894
return VersionNumber::SPIRV_1_3;
895895

896+
case CapabilityFloatControls2:
897+
return VersionNumber::SPIRV_1_2;
898+
896899
case CapabilityNamedBarrier:
897900
case CapabilitySubgroupDispatch:
898901
case CapabilityPipeStorage:
@@ -923,6 +926,8 @@ class SPIRVCapability : public SPIRVEntryNoId<OpCapability> {
923926
return ExtensionID::SPV_INTEL_bfloat16_arithmetic;
924927
case internal::CapabilityDeviceBarrierINTEL:
925928
return ExtensionID::SPV_INTEL_device_barrier;
929+
case CapabilityFloatControls2:
930+
return ExtensionID::SPV_KHR_float_controls2;
926931
default:
927932
return {};
928933
}

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
703703
add(internal::CapabilityInt16AtomicsINTEL, "Int16AtomicsINTEL");
704704
add(internal::CapabilityAtomicBFloat16LoadStoreINTEL,
705705
"AtomicBFloat16LoadStoreINTEL");
706+
add(CapabilityFloatControls2, "FloatControls2");
706707
}
707708
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
708709

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
; REQUIRES: spirv-as, spirv-dis
2+
; RUN: spirv-as -o %t.spv %s
3+
; RUN: spirv-val %t.spv
4+
; RUN: llvm-spirv -r -o %t.bc %t.spv
5+
; RUN: llvm-dis %t.bc -o - | FileCheck %s --check-prefix=LLVM
6+
; RUN: llvm-spirv --spirv-ext=+SPV_KHR_float_controls2 %t.bc -o - --spirv-text | FileCheck %s --check-prefix=SPIRV
7+
; RUN: llvm-spirv --spirv-ext=+SPV_KHR_float_controls2 %t.bc -o %t.back.spv
8+
; RUN: spirv-val %t.back.spv
9+
;
10+
; Check that the FPFastMathDefault set to "contract" on a function is honored
11+
; when translating from SPIRV to LLVM-IR
12+
;
13+
; However, when generating SPIRV back again from LLVM-IR set FPFastMathMode
14+
; decorations on the instructions.
15+
;
16+
; LLVM: %add.i = fadd contract float %{{[0-9]+}}, %{{[0-9]+}}
17+
;
18+
; SPIRV-DAG: 5 FAdd [[FLOAT:[0-9]+]] [[ADD_ID:[0-9]+]] {{[0-9]+}} {{[0-9]+}}
19+
; SPIRV-DAG: 3 TypeFloat [[FLOAT]] 32
20+
; SPIRV-DAG: 4 Decorate [[ADD_ID]] FPFastMathMode 65536
21+
; SPIRV-DAG: 4 Name [[ADD_ID]] "add.i"
22+
23+
OpCapability Kernel
24+
OpCapability Addresses
25+
OpCapability FloatControls2
26+
OpExtension "SPV_KHR_float_controls2"
27+
%1 = OpExtInstImport "OpenCL.std"
28+
OpMemoryModel Physical64 OpenCL
29+
OpEntryPoint Kernel %foo "foo" %11
30+
OpExecutionModeId %foo FPFastMathDefault %float %10
31+
OpSource OpenCL_C 102000
32+
OpName %a "a"
33+
OpName %b "b"
34+
OpName %c "c"
35+
OpName %foo "foo"
36+
OpName %add_i "add.i"
37+
OpName %entry "entry"
38+
OpDecorate %11 Constant
39+
%float = OpTypeFloat 32
40+
%ptr_float = OpTypePointer CrossWorkgroup %float
41+
%void = OpTypeVoid
42+
%7 = OpTypeFunction %void %ptr_float %ptr_float %ptr_float
43+
%uint = OpTypeInt 32 0
44+
%ptr_uint = OpTypePointer CrossWorkgroup %uint
45+
%10 = OpConstant %uint 65536
46+
%11 = OpVariable %ptr_uint CrossWorkgroup %10
47+
%foo = OpFunction %void None %7
48+
%a = OpFunctionParameter %ptr_float
49+
%b = OpFunctionParameter %ptr_float
50+
%c = OpFunctionParameter %ptr_float
51+
%entry = OpLabel
52+
%16 = OpLoad %float %a
53+
%17 = OpLoad %float %b
54+
%add_i = OpFAdd %float %17 %16
55+
OpStore %c %add_i
56+
OpReturn
57+
OpFunctionEnd

test/transcoding/fadd.ll

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV
2+
; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-DEFAULT
3+
; RUN: llvm-spirv -spirv-text %t.bc --spirv-ext=+SPV_KHR_float_controls2 -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-FC2
34
; RUN: llvm-spirv %t.bc -o %t.spv
5+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_float_controls2 -o %t.fc2.spv
46
; RUN: spirv-val %t.spv
5-
; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM
7+
; RUN: spirv-val %t.fc2.spv
8+
; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefixes=CHECK-LLVM,CHECK-LLVM-DEFAULT
9+
; RUN: llvm-spirv -r %t.fc2.spv -o - | llvm-dis -o - | FileCheck %s --check-prefixes=CHECK-LLVM,CHECK-LLVM-FC2
610

711
; CHECK-SPIRV: 3 Name [[#r1:]] "r1"
812
; CHECK-SPIRV: 3 Name [[#r2:]] "r2"
@@ -11,13 +15,17 @@
1115
; CHECK-SPIRV: 3 Name [[#r5:]] "r5"
1216
; CHECK-SPIRV: 3 Name [[#r6:]] "r6"
1317
; CHECK-SPIRV: 3 Name [[#r7:]] "r7"
18+
; CHECK-SPIRV: 3 Name [[#r8:]] "r8"
1419
; CHECK-SPIRV-NOT: 4 Decorate [[#r1]] FPFastMathMode
1520
; CHECK-SPIRV-DAG: 4 Decorate [[#r2]] FPFastMathMode 1
1621
; CHECK-SPIRV-DAG: 4 Decorate [[#r3]] FPFastMathMode 2
1722
; CHECK-SPIRV-DAG: 4 Decorate [[#r4]] FPFastMathMode 4
1823
; CHECK-SPIRV-DAG: 4 Decorate [[#r5]] FPFastMathMode 8
19-
; CHECK-SPIRV-DAG: 4 Decorate [[#r6]] FPFastMathMode 16
24+
; CHECK-SPIRV-DEFAULT-DAG: 4 Decorate [[#r6]] FPFastMathMode 16
25+
; CHECK-SPIRV-FC2-DAG: 4 Decorate [[#r6]] FPFastMathMode 458767
2026
; CHECK-SPIRV-DAG: 4 Decorate [[#r7]] FPFastMathMode 3
27+
; CHECK-SPIRV-DEFAULT-NOT: 4 Decorate [[#r8]] FPFastMathMode
28+
; CHECK-SPIRV-FC2-DAG: 4 Decorate [[#r8]] FPFastMathMode 65536
2129
; CHECK-SPIRV: 3 TypeFloat [[float:[0-9]+]] 32
2230
; CHECK-SPIRV: 5 FAdd [[float]] [[#r1]]
2331
; CHECK-SPIRV: 5 FAdd [[float]] [[#r2]]
@@ -26,14 +34,18 @@
2634
; CHECK-SPIRV: 5 FAdd [[float]] [[#r5]]
2735
; CHECK-SPIRV: 5 FAdd [[float]] [[#r6]]
2836
; CHECK-SPIRV: 5 FAdd [[float]] [[#r7]]
37+
; CHECK-SPIRV: 5 FAdd [[float]] [[#r8]]
2938

3039
; CHECK-LLVM: %r1 = fadd float %a, %b
3140
; CHECK-LLVM: %r2 = fadd nnan float %a, %b
3241
; CHECK-LLVM: %r3 = fadd ninf float %a, %b
3342
; CHECK-LLVM: %r4 = fadd nsz float %a, %b
3443
; CHECK-LLVM: %r5 = fadd arcp float %a, %b
35-
; CHECK-LLVM: %r6 = fadd fast float %a, %b
44+
; CHECK-LLVM-DEFAULT: %r6 = fadd fast float %a, %b
45+
; CHECK-LLVM-FC2: %r6 = fadd reassoc nnan ninf nsz arcp contract float %a, %b
3646
; CHECK-LLVM: %r7 = fadd nnan ninf float %a, %b
47+
; CHECK-LLVM-DEFAULT: %r8 = fadd float %a, %b
48+
; CHECK-LLVM-FC2: %r8 = fadd contract float %a, %b
3749

3850
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
3951
target triple = "spir-unknown-unknown"
@@ -48,6 +60,7 @@ entry:
4860
%r5 = fadd arcp float %a, %b
4961
%r6 = fadd fast float %a, %b
5062
%r7 = fadd nnan ninf float %a, %b
63+
%r8 = fadd contract float %a, %b
5164
ret void
5265
}
5366

0 commit comments

Comments
 (0)