Skip to content

Commit f9fa4d8

Browse files
committed
[SPIR-V] Support SPV_INTEL_fp_max_error extension for !fpmath metadata
Specification: https://github.khronos.org/SPIRV-Registry/extensions/INTEL/SPV_INTEL_fp_max_error.html
1 parent d1bd1c7 commit f9fa4d8

File tree

8 files changed

+86
-2
lines changed

8 files changed

+86
-2
lines changed

llvm/docs/SPIRVUsage.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
207207
- Allows support for additional group operations within uniform control flow.
208208
* - ``SPV_KHR_non_semantic_info``
209209
- Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module.
210+
* - ``SPV_INTEL_fp_max_error``
211+
- Adds the ability to specify the maximum error for floating-point operations.
210212

211213
To enable multiple extensions, list them separated by comma. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use:
212214

@@ -307,6 +309,10 @@ SPIR-V backend, along with their descriptions and argument details.
307309
- None
308310
- `[Type, 32-bit Integer, Metadata]`
309311
- Assigns one of two memory aliasing decorations (specified by the second argument) to instructions using original aliasing metadata node. Not emitted directly but used to support SPIR-V representation in LLVM IR.
312+
* - `int_spv_assign_fpmaxerror_decoration`
313+
- None
314+
- `[Type, Metadata]`
315+
- Assigns the maximum error decoration to floating-point instructions using the original metadata node. Not emitted directly but used to support SPIR-V representation in LLVM IR.
310316
* - `int_spv_track_constant`
311317
- Type
312318
- `[Type, Metadata]`

llvm/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,6 @@ let TargetPrefix = "spv" in {
141141
// Memory aliasing intrinsics
142142
def int_spv_assign_aliasing_decoration : Intrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_metadata_ty], [ImmArg<ArgIndex<1>>]>;
143143

144+
// FPMaxErrorDecorationINTEL
145+
def int_spv_assign_fpmaxerror_decoration: Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
144146
}

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
9090
{"SPV_KHR_non_semantic_info",
9191
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
9292
{"SPV_INTEL_long_composites",
93-
SPIRV::Extension::Extension::SPV_INTEL_long_composites}};
93+
SPIRV::Extension::Extension::SPV_INTEL_long_composites},
94+
{"SPV_INTEL_fp_max_error",
95+
SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}};
9496

9597
bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName,
9698
llvm::StringRef ArgValue,

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,19 @@ void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
20162016
processMemAliasingDecoration(LLVMContext::MD_alias_scope);
20172017
processMemAliasingDecoration(LLVMContext::MD_noalias);
20182018
}
2019+
// MD_fpmath
2020+
if (MDNode *MD = I->getMetadata("fpmath")) {
2021+
const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I->getFunction());
2022+
bool AllowFPMaxError =
2023+
STI->canUseExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
2024+
if (!AllowFPMaxError)
2025+
return;
2026+
2027+
setInsertPointAfterDef(B, I);
2028+
B.CreateIntrinsic(Intrinsic::spv_assign_fpmaxerror_decoration,
2029+
{I->getType()},
2030+
{I, MetadataAsValue::get(I->getContext(), MD)});
2031+
}
20192032
}
20202033

20212034
void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,9 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
888888
SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
889889
} else if (Dec == SPIRV::Decoration::NonUniformEXT) {
890890
Reqs.addRequirements(SPIRV::Capability::ShaderNonUniformEXT);
891+
} else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
892+
Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);
893+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
891894
}
892895
}
893896

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,18 +819,38 @@ static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR,
819819
insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
820820
}
821821

822+
static uint32_t convertFloatToSPIRVWord(float F) {
823+
union {
824+
float F;
825+
uint32_t Spir;
826+
} FPMaxError;
827+
FPMaxError.F = F;
828+
return FPMaxError.Spir;
829+
}
830+
822831
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR,
823832
MachineIRBuilder MIB) {
824833
SmallVector<MachineInstr *, 10> ToErase;
825834
for (MachineBasicBlock &MBB : MF) {
826835
for (MachineInstr &MI : MBB) {
827836
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
828-
!isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration))
837+
!isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
838+
!isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
829839
continue;
830840
MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
831841
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
832842
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
833843
MI.getOperand(2).getMetadata());
844+
} else if (isSpvIntrinsic(MI,
845+
Intrinsic::spv_assign_fpmaxerror_decoration)) {
846+
ConstantFP *OpV = mdconst::dyn_extract<ConstantFP>(
847+
MI.getOperand(2).getMetadata()->getOperand(0));
848+
uint32_t OpValue =
849+
convertFloatToSPIRVWord(OpV->getValueAPF().convertToFloat());
850+
851+
buildOpDecorate(MI.getOperand(1).getReg(), MIB,
852+
SPIRV::Decoration::FPMaxErrorDecorationINTEL,
853+
{OpValue});
834854
} else {
835855
GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
836856
MI.getOperand(2).getImm(),

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ defm SPV_INTEL_float_controls2 : ExtensionOperand<115>;
312312
defm SPV_INTEL_bindless_images : ExtensionOperand<116>;
313313
defm SPV_INTEL_long_composites : ExtensionOperand<117>;
314314
defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>;
315+
defm SPV_INTEL_fp_max_error : ExtensionOperand<119>;
315316

316317
//===----------------------------------------------------------------------===//
317318
// Multiclass used to define Capabilities enum values and at the same time
@@ -511,6 +512,7 @@ defm FunctionFloatControlINTEL : CapabilityOperand<5821, 0, 0, [SPV_INTEL_float_
511512
defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composites], []>;
512513
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
513514
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;
515+
defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
514516

515517
//===----------------------------------------------------------------------===//
516518
// Multiclass used to define SourceLanguage enum values and at the same time
@@ -1261,6 +1263,7 @@ defm FunctionDenormModeINTEL : DecorationOperand<5823, 0, 0, [], [FunctionFloatC
12611263
defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [FunctionFloatControlINTEL]>;
12621264
defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>;
12631265
defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>;
1266+
defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>;
12641267

12651268
//===----------------------------------------------------------------------===//
12661269
// Multiclass used to define BuiltIn enum values and at the same time
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; Confirm that we handle fpmath metadata correctly
2+
; This is a copy of https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
3+
4+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o %t.spt
5+
; RUN: FileCheck %s --input-file=%t.spt
6+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o - -filetype=obj | spirv-val %}
7+
8+
; CHECK: OpCapability FPMaxErrorINTEL
9+
; CHECK: OpExtension "SPV_INTEL_fp_max_error"
10+
11+
; CHECK: OpName %[[#CalleeName:]] "callee"
12+
; CHECK: OpName %[[#F3:]] "f3"
13+
; CHECK: OpDecorate %[[#F3]] FPMaxErrorDecorationINTEL 1075838976
14+
; CHECK: OpDecorate %[[#Callee:]] FPMaxErrorDecorationINTEL 1065353216
15+
16+
; CHECK: %[[#FloatTy:]] = OpTypeFloat 32
17+
; CHECK: %[[#Callee]] = OpFunctionCall %[[#FloatTy]] %[[#CalleeName]]
18+
19+
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"
20+
target triple = "spir64-unknown-unknown"
21+
22+
define float @callee(float %f1, float %f2) {
23+
entry:
24+
ret float %f1
25+
}
26+
27+
define void @test_fp_max_error_decoration(float %f1, float %f2) {
28+
entry:
29+
%f3 = fdiv float %f1, %f2, !fpmath !0
30+
call float @callee(float %f1, float %f2), !fpmath !1
31+
ret void
32+
}
33+
34+
!0 = !{float 2.500000e+00}
35+
!1 = !{float 1.000000e+00}

0 commit comments

Comments
 (0)