Skip to content

Commit a0e5c9f

Browse files
vmaksimofrederik-h
authored andcommitted
[SPIR-V] Support SPV_INTEL_fp_max_error extension for !fpmath metadata (llvm#130619)
Specification: https://github.khronos.org/SPIRV-Registry/extensions/INTEL/SPV_INTEL_fp_max_error.html
1 parent ec58734 commit a0e5c9f

File tree

8 files changed

+83
-2
lines changed

8 files changed

+83
-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(LLVMContext::MD_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
@@ -820,18 +820,38 @@ static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR,
820820
insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
821821
}
822822

823+
static uint32_t convertFloatToSPIRVWord(float F) {
824+
union {
825+
float F;
826+
uint32_t Spir;
827+
} FPMaxError;
828+
FPMaxError.F = F;
829+
return FPMaxError.Spir;
830+
}
831+
823832
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR,
824833
MachineIRBuilder MIB) {
825834
SmallVector<MachineInstr *, 10> ToErase;
826835
for (MachineBasicBlock &MBB : MF) {
827836
for (MachineInstr &MI : MBB) {
828837
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
829-
!isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration))
838+
!isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
839+
!isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
830840
continue;
831841
MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
832842
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
833843
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
834844
MI.getOperand(2).getMetadata());
845+
} else if (isSpvIntrinsic(MI,
846+
Intrinsic::spv_assign_fpmaxerror_decoration)) {
847+
ConstantFP *OpV = mdconst::dyn_extract<ConstantFP>(
848+
MI.getOperand(2).getMetadata()->getOperand(0));
849+
uint32_t OpValue =
850+
convertFloatToSPIRVWord(OpV->getValueAPF().convertToFloat());
851+
852+
buildOpDecorate(MI.getOperand(1).getReg(), MIB,
853+
SPIRV::Decoration::FPMaxErrorDecorationINTEL,
854+
{OpValue});
835855
} else {
836856
GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
837857
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: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
define float @callee(float %f1, float %f2) {
20+
entry:
21+
ret float %f1
22+
}
23+
24+
define void @test_fp_max_error_decoration(float %f1, float %f2) {
25+
entry:
26+
%f3 = fdiv float %f1, %f2, !fpmath !0
27+
call float @callee(float %f1, float %f2), !fpmath !1
28+
ret void
29+
}
30+
31+
!0 = !{float 2.500000e+00}
32+
!1 = !{float 1.000000e+00}

0 commit comments

Comments
 (0)