Skip to content

Commit e63fdb8

Browse files
authored
Support forward translation of fpmath metadata (#2266)
The Clang frontend uses the `fpmath` metadata to represent FP accuracy in some cases, right now for OpenCL and possibly SYCL in the near future. The long term plan is to expect the frontend to add the `fpbuiltin-max-error` attribute, but since `fpmath` is generated today and currently dropped, let's support it using the existing `SPV_INTEL_fp_max_error` extension. Upon reverse translation, we generate the same `fpbuiltin-max-error` attribute/metadata that we would generate if the frontend had added `fpbuiltin-max-error` originally, so anybody using the reverse translation result only needs to handle one case. Signed-off-by: Sarnie, Nick <[email protected]>
1 parent b891a51 commit e63fdb8

File tree

3 files changed

+81
-34
lines changed

3 files changed

+81
-34
lines changed

lib/SPIRV/SPIRVRegularizeLLVM.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ bool SPIRVRegularizeLLVMBase::regularize() {
429429

430430
// Remove metadata not supported by SPIRV
431431
static const char *MDs[] = {
432-
"fpmath",
433432
"tbaa",
434433
"range",
435434
};

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,31 @@ static bool recursiveType(const StructType *ST, const Type *Ty) {
302302
return Run(Ty);
303303
}
304304

305+
// Add decoration if needed
306+
void addFPBuiltinDecoration(SPIRVModule *BM, Instruction *Inst,
307+
SPIRVInstruction *I) {
308+
if (!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fp_max_error))
309+
return;
310+
auto *II = dyn_cast_or_null<IntrinsicInst>(Inst);
311+
if (II && II->getCalledFunction()->getName().starts_with("llvm.fpbuiltin")) {
312+
// Add a new decoration for llvm.builtin intrinsics, if needed
313+
if (II->getAttributes().hasFnAttr("fpbuiltin-max-error")) {
314+
double F = 0.0;
315+
II->getAttributes()
316+
.getFnAttr("fpbuiltin-max-error")
317+
.getValueAsString()
318+
.getAsDouble(F);
319+
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
320+
convertFloatToSPIRVWord(F));
321+
}
322+
} else if (auto *MD = Inst->getMetadata("fpmath")) {
323+
auto *MDVal = mdconst::dyn_extract<ConstantFP>(MD->getOperand(0));
324+
double ValAsDouble = MDVal->getValue().convertToFloat();
325+
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
326+
convertFloatToSPIRVWord(ValAsDouble));
327+
}
328+
}
329+
305330
SPIRVType *LLVMToSPIRVBase::transType(Type *T) {
306331
LLVMToSPIRVTypeMap::iterator Loc = TypeMap.find(T);
307332
if (Loc != TypeMap.end())
@@ -2830,6 +2855,8 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) {
28302855
transMemAliasingINTELDecorations(Inst, BV);
28312856
if (auto *IDecoMD = Inst->getMetadata(SPIRV_MD_DECORATIONS))
28322857
transMetadataDecorations(IDecoMD, BV);
2858+
if (BV->isInst())
2859+
addFPBuiltinDecoration(BM, Inst, static_cast<SPIRVInstruction *>(BV));
28332860
}
28342861

28352862
if (auto *CI = dyn_cast<CallInst>(V)) {
@@ -3626,26 +3653,6 @@ bool LLVMToSPIRVBase::isKnownIntrinsic(Intrinsic::ID Id) {
36263653
}
36273654
}
36283655

3629-
// Add decoration if needed
3630-
SPIRVInstruction *addFPBuiltinDecoration(SPIRVModule *BM, IntrinsicInst *II,
3631-
SPIRVInstruction *I) {
3632-
const bool AllowFPMaxError =
3633-
BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fp_max_error);
3634-
assert(II->getCalledFunction()->getName().starts_with("llvm.fpbuiltin"));
3635-
// Add a new decoration for llvm.builtin intrinsics, if needed
3636-
if (AllowFPMaxError)
3637-
if (II->getAttributes().hasFnAttr("fpbuiltin-max-error")) {
3638-
double F = 0.0;
3639-
II->getAttributes()
3640-
.getFnAttr("fpbuiltin-max-error")
3641-
.getValueAsString()
3642-
.getAsDouble(F);
3643-
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
3644-
convertFloatToSPIRVWord(F));
3645-
}
3646-
return I;
3647-
}
3648-
36493656
// Performs mapping of LLVM IR rounding mode to SPIR-V rounding mode
36503657
// Value *V is metadata <rounding mode> argument of
36513658
// llvm.experimental.constrained.* intrinsics
@@ -4758,10 +4765,9 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
47584765
.Case("fdiv", OpFDiv)
47594766
.Case("frem", OpFRem)
47604767
.Default(OpUndef);
4761-
auto *BI = BM->addBinaryInst(BinOp, transType(II->getType()),
4762-
transValue(II->getArgOperand(0), BB),
4763-
transValue(II->getArgOperand(1), BB), BB);
4764-
return addFPBuiltinDecoration(BM, II, BI);
4768+
return BM->addBinaryInst(BinOp, transType(II->getType()),
4769+
transValue(II->getArgOperand(0), BB),
4770+
transValue(II->getArgOperand(1), BB), BB);
47654771
}
47664772
case FPBuiltinType::EXT_1OPS: {
47674773
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4795,9 +4801,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
47954801
.Case("erfc", OpenCLLIB::Erfc)
47964802
.Default(SPIRVWORD_MAX);
47974803
assert(ExtOp != SPIRVWORD_MAX);
4798-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4799-
Ops, BB);
4800-
return addFPBuiltinDecoration(BM, II, BI);
4804+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4805+
BB);
48014806
}
48024807
case FPBuiltinType::EXT_2OPS: {
48034808
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4812,9 +4817,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48124817
.Case("ldexp", OpenCLLIB::Ldexp)
48134818
.Default(SPIRVWORD_MAX);
48144819
assert(ExtOp != SPIRVWORD_MAX);
4815-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4816-
Ops, BB);
4817-
return addFPBuiltinDecoration(BM, II, BI);
4820+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4821+
BB);
48184822
}
48194823
case FPBuiltinType::EXT_3OPS: {
48204824
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4827,9 +4831,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48274831
.Case("sincos", OpenCLLIB::Sincos)
48284832
.Default(SPIRVWORD_MAX);
48294833
assert(ExtOp != SPIRVWORD_MAX);
4830-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4831-
Ops, BB);
4832-
return addFPBuiltinDecoration(BM, II, BI);
4834+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4835+
BB);
48334836
}
48344837
default:
48354838
return nullptr;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
; Confirm that we handle fpmath metadata correctly
2+
3+
; RUN: llvm-as %s -o %t.bc
4+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_fp_max_error -o %t.spv
5+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
6+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
7+
8+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
9+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
10+
11+
; CHECK-SPIRV: Capability FPMaxErrorINTEL
12+
; CHECK-SPIRV: Extension "SPV_INTEL_fp_max_error"
13+
; CHECK-SPIRV: ExtInstImport [[#OCLEXTID:]] "OpenCL.std"
14+
15+
; CHECK-SPIRV: Name [[#CalleeName:]] "callee"
16+
; CHECK-SPIRV: Name [[#F3:]] "f3"
17+
; CHECK-SPIRV: Decorate [[#F3]] FPMaxErrorDecorationINTEL 1075838976
18+
; CHECK-SPIRV: Decorate [[#Callee:]] FPMaxErrorDecorationINTEL 1065353216
19+
20+
; CHECK-SPIRV: TypeFloat [[#FloatTy:]] 32
21+
22+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
23+
target triple = "spir64-unknown-unknown"
24+
25+
define float @callee(float %f1, float %f2) {
26+
entry:
27+
ret float %f1
28+
}
29+
30+
define void @test_fp_max_error_decoration(float %f1, float %f2) {
31+
entry:
32+
; CHECK-LLVM: fdiv float %f1, %f2, !fpbuiltin-max-error ![[#ME0:]]
33+
%f3 = fdiv float %f1, %f2, !fpmath !0
34+
35+
; CHECK-LLVM: call {{.*}} float @callee(float %f1, float %f2) #[[#ATTR0:]]
36+
; CHECK-SPIRV: FunctionCall [[#FloatTy]] [[#Callee]] [[#CalleeName]]
37+
call float @callee(float %f1, float %f2), !fpmath !1
38+
ret void
39+
}
40+
41+
; CHECK-LLVM: attributes #[[#ATTR0]] = {{{.*}}"fpbuiltin-max-error"="1.000000"{{.*}}}
42+
43+
; CHECK-LLVM: ![[#ME0]] = !{!"2.500000"}
44+
!0 = !{float 2.500000e+00}
45+
!1 = !{float 1.000000e+00}

0 commit comments

Comments
 (0)