Skip to content

Commit a998806

Browse files
sarnexsys-ce-bb
authored andcommitted
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]> Original commit: KhronosGroup/SPIRV-LLVM-Translator@e63fdb8
1 parent 4e7b777 commit a998806

File tree

3 files changed

+81
-34
lines changed

3 files changed

+81
-34
lines changed

llvm-spirv/lib/SPIRV/SPIRVRegularizeLLVM.cpp

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

492492
// Remove metadata not supported by SPIRV
493493
static const char *MDs[] = {
494-
"fpmath",
495494
"tbaa",
496495
"range",
497496
};

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

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

309+
// Add decoration if needed
310+
void addFPBuiltinDecoration(SPIRVModule *BM, Instruction *Inst,
311+
SPIRVInstruction *I) {
312+
if (!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fp_max_error))
313+
return;
314+
auto *II = dyn_cast_or_null<IntrinsicInst>(Inst);
315+
if (II && II->getCalledFunction()->getName().starts_with("llvm.fpbuiltin")) {
316+
// Add a new decoration for llvm.builtin intrinsics, if needed
317+
if (II->getAttributes().hasFnAttr("fpbuiltin-max-error")) {
318+
double F = 0.0;
319+
II->getAttributes()
320+
.getFnAttr("fpbuiltin-max-error")
321+
.getValueAsString()
322+
.getAsDouble(F);
323+
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
324+
convertFloatToSPIRVWord(F));
325+
}
326+
} else if (auto *MD = Inst->getMetadata("fpmath")) {
327+
auto *MDVal = mdconst::dyn_extract<ConstantFP>(MD->getOperand(0));
328+
double ValAsDouble = MDVal->getValue().convertToFloat();
329+
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
330+
convertFloatToSPIRVWord(ValAsDouble));
331+
}
332+
}
333+
309334
SPIRVType *LLVMToSPIRVBase::transType(Type *T) {
310335
LLVMToSPIRVTypeMap::iterator Loc = TypeMap.find(T);
311336
if (Loc != TypeMap.end())
@@ -2894,6 +2919,8 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) {
28942919
transMemAliasingINTELDecorations(Inst, BV);
28952920
if (auto *IDecoMD = Inst->getMetadata(SPIRV_MD_DECORATIONS))
28962921
transMetadataDecorations(IDecoMD, BV);
2922+
if (BV->isInst())
2923+
addFPBuiltinDecoration(BM, Inst, static_cast<SPIRVInstruction *>(BV));
28972924
}
28982925

28992926
if (auto *CI = dyn_cast<CallInst>(V)) {
@@ -3690,26 +3717,6 @@ bool LLVMToSPIRVBase::isKnownIntrinsic(Intrinsic::ID Id) {
36903717
}
36913718
}
36923719

3693-
// Add decoration if needed
3694-
SPIRVInstruction *addFPBuiltinDecoration(SPIRVModule *BM, IntrinsicInst *II,
3695-
SPIRVInstruction *I) {
3696-
const bool AllowFPMaxError =
3697-
BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fp_max_error);
3698-
assert(II->getCalledFunction()->getName().starts_with("llvm.fpbuiltin"));
3699-
// Add a new decoration for llvm.builtin intrinsics, if needed
3700-
if (AllowFPMaxError)
3701-
if (II->getAttributes().hasFnAttr("fpbuiltin-max-error")) {
3702-
double F = 0.0;
3703-
II->getAttributes()
3704-
.getFnAttr("fpbuiltin-max-error")
3705-
.getValueAsString()
3706-
.getAsDouble(F);
3707-
I->addDecorate(DecorationFPMaxErrorDecorationINTEL,
3708-
convertFloatToSPIRVWord(F));
3709-
}
3710-
return I;
3711-
}
3712-
37133720
// Performs mapping of LLVM IR rounding mode to SPIR-V rounding mode
37143721
// Value *V is metadata <rounding mode> argument of
37153722
// llvm.experimental.constrained.* intrinsics
@@ -4822,10 +4829,9 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48224829
.Case("fdiv", OpFDiv)
48234830
.Case("frem", OpFRem)
48244831
.Default(OpUndef);
4825-
auto *BI = BM->addBinaryInst(BinOp, transType(II->getType()),
4826-
transValue(II->getArgOperand(0), BB),
4827-
transValue(II->getArgOperand(1), BB), BB);
4828-
return addFPBuiltinDecoration(BM, II, BI);
4832+
return BM->addBinaryInst(BinOp, transType(II->getType()),
4833+
transValue(II->getArgOperand(0), BB),
4834+
transValue(II->getArgOperand(1), BB), BB);
48294835
}
48304836
case FPBuiltinType::EXT_1OPS: {
48314837
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4859,9 +4865,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48594865
.Case("erfc", OpenCLLIB::Erfc)
48604866
.Default(SPIRVWORD_MAX);
48614867
assert(ExtOp != SPIRVWORD_MAX);
4862-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4863-
Ops, BB);
4864-
return addFPBuiltinDecoration(BM, II, BI);
4868+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4869+
BB);
48654870
}
48664871
case FPBuiltinType::EXT_2OPS: {
48674872
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4876,9 +4881,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48764881
.Case("ldexp", OpenCLLIB::Ldexp)
48774882
.Default(SPIRVWORD_MAX);
48784883
assert(ExtOp != SPIRVWORD_MAX);
4879-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4880-
Ops, BB);
4881-
return addFPBuiltinDecoration(BM, II, BI);
4884+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4885+
BB);
48824886
}
48834887
case FPBuiltinType::EXT_3OPS: {
48844888
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
@@ -4891,9 +4895,8 @@ SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II,
48914895
.Case("sincos", OpenCLLIB::Sincos)
48924896
.Default(SPIRVWORD_MAX);
48934897
assert(ExtOp != SPIRVWORD_MAX);
4894-
auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp,
4895-
Ops, BB);
4896-
return addFPBuiltinDecoration(BM, II, BI);
4898+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
4899+
BB);
48974900
}
48984901
default:
48994902
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)