-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SPIR-V] Support SPV_INTEL_fp_max_error extension for !fpmath
metadata
#130619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-spir-v Author: Viktoria Maximova (vmaksimo) ChangesSpecification: Full diff: https://github.com/llvm/llvm-project/pull/130619.diff 8 Files Affected:
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 6a27e0efaec7f..ee5937f208825 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -207,6 +207,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
- Allows support for additional group operations within uniform control flow.
* - ``SPV_KHR_non_semantic_info``
- Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module.
+ * - ``SPV_INTEL_fp_max_error``
+ - Adds the ability to specify the maximum error for floating-point operations.
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:
@@ -307,6 +309,10 @@ SPIR-V backend, along with their descriptions and argument details.
- None
- `[Type, 32-bit Integer, Metadata]`
- 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.
+ * - `int_spv_assign_fpmaxerror_decoration`
+ - None
+ - `[Type, Metadata]`
+ - 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.
* - `int_spv_track_constant`
- Type
- `[Type, Metadata]`
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 7012ef3534c68..df3e137c80980 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -141,4 +141,6 @@ let TargetPrefix = "spv" in {
// Memory aliasing intrinsics
def int_spv_assign_aliasing_decoration : Intrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_metadata_ty], [ImmArg<ArgIndex<1>>]>;
+ // FPMaxErrorDecorationINTEL
+ def int_spv_assign_fpmaxerror_decoration: Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index 8d1714932c3c6..37119bf01545c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -90,7 +90,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
{"SPV_KHR_non_semantic_info",
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
{"SPV_INTEL_long_composites",
- SPIRV::Extension::Extension::SPV_INTEL_long_composites}};
+ SPIRV::Extension::Extension::SPV_INTEL_long_composites},
+ {"SPV_INTEL_fp_max_error",
+ SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}};
bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName,
llvm::StringRef ArgValue,
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 751ea5ab2dc47..00acb6aa19c9c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2016,6 +2016,19 @@ void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
processMemAliasingDecoration(LLVMContext::MD_alias_scope);
processMemAliasingDecoration(LLVMContext::MD_noalias);
}
+ // MD_fpmath
+ if (MDNode *MD = I->getMetadata("fpmath")) {
+ const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I->getFunction());
+ bool AllowFPMaxError =
+ STI->canUseExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
+ if (!AllowFPMaxError)
+ return;
+
+ setInsertPointAfterDef(B, I);
+ B.CreateIntrinsic(Intrinsic::spv_assign_fpmaxerror_decoration,
+ {I->getType()},
+ {I, MetadataAsValue::get(I->getContext(), MD)});
+ }
}
void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index e0b348f0bba10..63894acacbc73 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -888,6 +888,9 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
} else if (Dec == SPIRV::Decoration::NonUniformEXT) {
Reqs.addRequirements(SPIRV::Capability::ShaderNonUniformEXT);
+ } else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
+ Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);
+ Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index baacd58b28028..4904506f25a08 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -819,18 +819,38 @@ static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR,
insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
}
+static uint32_t convertFloatToSPIRVWord(float F) {
+ union {
+ float F;
+ uint32_t Spir;
+ } FPMaxError;
+ FPMaxError.F = F;
+ return FPMaxError.Spir;
+}
+
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MachineIRBuilder MIB) {
SmallVector<MachineInstr *, 10> ToErase;
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
- !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration))
+ !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
+ !isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
continue;
MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getMetadata());
+ } else if (isSpvIntrinsic(MI,
+ Intrinsic::spv_assign_fpmaxerror_decoration)) {
+ ConstantFP *OpV = mdconst::dyn_extract<ConstantFP>(
+ MI.getOperand(2).getMetadata()->getOperand(0));
+ uint32_t OpValue =
+ convertFloatToSPIRVWord(OpV->getValueAPF().convertToFloat());
+
+ buildOpDecorate(MI.getOperand(1).getReg(), MIB,
+ SPIRV::Decoration::FPMaxErrorDecorationINTEL,
+ {OpValue});
} else {
GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getImm(),
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index a871518e2094c..caee778eddbc4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -312,6 +312,7 @@ defm SPV_INTEL_float_controls2 : ExtensionOperand<115>;
defm SPV_INTEL_bindless_images : ExtensionOperand<116>;
defm SPV_INTEL_long_composites : ExtensionOperand<117>;
defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>;
+defm SPV_INTEL_fp_max_error : ExtensionOperand<119>;
//===----------------------------------------------------------------------===//
// 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_
defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composites], []>;
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;
+defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
//===----------------------------------------------------------------------===//
// Multiclass used to define SourceLanguage enum values and at the same time
@@ -1261,6 +1263,7 @@ defm FunctionDenormModeINTEL : DecorationOperand<5823, 0, 0, [], [FunctionFloatC
defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [FunctionFloatControlINTEL]>;
defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>;
+defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>;
//===----------------------------------------------------------------------===//
// Multiclass used to define BuiltIn enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
new file mode 100644
index 0000000000000..66070181968e2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
@@ -0,0 +1,35 @@
+; Confirm that we handle fpmath metadata correctly
+; This is a copy of https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o %t.spt
+; RUN: FileCheck %s --input-file=%t.spt
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpCapability FPMaxErrorINTEL
+; CHECK: OpExtension "SPV_INTEL_fp_max_error"
+
+; CHECK: OpName %[[#CalleeName:]] "callee"
+; CHECK: OpName %[[#F3:]] "f3"
+; CHECK: OpDecorate %[[#F3]] FPMaxErrorDecorationINTEL 1075838976
+; CHECK: OpDecorate %[[#Callee:]] FPMaxErrorDecorationINTEL 1065353216
+
+; CHECK: %[[#FloatTy:]] = OpTypeFloat 32
+; CHECK: %[[#Callee]] = OpFunctionCall %[[#FloatTy]] %[[#CalleeName]]
+
+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"
+target triple = "spir64-unknown-unknown"
+
+define float @callee(float %f1, float %f2) {
+entry:
+ret float %f1
+}
+
+define void @test_fp_max_error_decoration(float %f1, float %f2) {
+entry:
+%f3 = fdiv float %f1, %f2, !fpmath !0
+call float @callee(float %f1, float %f2), !fpmath !1
+ret void
+}
+
+!0 = !{float 2.500000e+00}
+!1 = !{float 1.000000e+00}
|
@llvm/pr-subscribers-llvm-ir Author: Viktoria Maximova (vmaksimo) ChangesSpecification: Full diff: https://github.com/llvm/llvm-project/pull/130619.diff 8 Files Affected:
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 6a27e0efaec7f..ee5937f208825 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -207,6 +207,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
- Allows support for additional group operations within uniform control flow.
* - ``SPV_KHR_non_semantic_info``
- Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module.
+ * - ``SPV_INTEL_fp_max_error``
+ - Adds the ability to specify the maximum error for floating-point operations.
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:
@@ -307,6 +309,10 @@ SPIR-V backend, along with their descriptions and argument details.
- None
- `[Type, 32-bit Integer, Metadata]`
- 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.
+ * - `int_spv_assign_fpmaxerror_decoration`
+ - None
+ - `[Type, Metadata]`
+ - 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.
* - `int_spv_track_constant`
- Type
- `[Type, Metadata]`
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 7012ef3534c68..df3e137c80980 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -141,4 +141,6 @@ let TargetPrefix = "spv" in {
// Memory aliasing intrinsics
def int_spv_assign_aliasing_decoration : Intrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_metadata_ty], [ImmArg<ArgIndex<1>>]>;
+ // FPMaxErrorDecorationINTEL
+ def int_spv_assign_fpmaxerror_decoration: Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index 8d1714932c3c6..37119bf01545c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -90,7 +90,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
{"SPV_KHR_non_semantic_info",
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
{"SPV_INTEL_long_composites",
- SPIRV::Extension::Extension::SPV_INTEL_long_composites}};
+ SPIRV::Extension::Extension::SPV_INTEL_long_composites},
+ {"SPV_INTEL_fp_max_error",
+ SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}};
bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName,
llvm::StringRef ArgValue,
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 751ea5ab2dc47..00acb6aa19c9c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2016,6 +2016,19 @@ void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
processMemAliasingDecoration(LLVMContext::MD_alias_scope);
processMemAliasingDecoration(LLVMContext::MD_noalias);
}
+ // MD_fpmath
+ if (MDNode *MD = I->getMetadata("fpmath")) {
+ const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I->getFunction());
+ bool AllowFPMaxError =
+ STI->canUseExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
+ if (!AllowFPMaxError)
+ return;
+
+ setInsertPointAfterDef(B, I);
+ B.CreateIntrinsic(Intrinsic::spv_assign_fpmaxerror_decoration,
+ {I->getType()},
+ {I, MetadataAsValue::get(I->getContext(), MD)});
+ }
}
void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index e0b348f0bba10..63894acacbc73 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -888,6 +888,9 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
} else if (Dec == SPIRV::Decoration::NonUniformEXT) {
Reqs.addRequirements(SPIRV::Capability::ShaderNonUniformEXT);
+ } else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
+ Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);
+ Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index baacd58b28028..4904506f25a08 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -819,18 +819,38 @@ static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR,
insertInlineAsmProcess(MF, GR, ST, MIRBuilder, ToProcess);
}
+static uint32_t convertFloatToSPIRVWord(float F) {
+ union {
+ float F;
+ uint32_t Spir;
+ } FPMaxError;
+ FPMaxError.F = F;
+ return FPMaxError.Spir;
+}
+
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MachineIRBuilder MIB) {
SmallVector<MachineInstr *, 10> ToErase;
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
- !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration))
+ !isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration) &&
+ !isSpvIntrinsic(MI, Intrinsic::spv_assign_fpmaxerror_decoration))
continue;
MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getMetadata());
+ } else if (isSpvIntrinsic(MI,
+ Intrinsic::spv_assign_fpmaxerror_decoration)) {
+ ConstantFP *OpV = mdconst::dyn_extract<ConstantFP>(
+ MI.getOperand(2).getMetadata()->getOperand(0));
+ uint32_t OpValue =
+ convertFloatToSPIRVWord(OpV->getValueAPF().convertToFloat());
+
+ buildOpDecorate(MI.getOperand(1).getReg(), MIB,
+ SPIRV::Decoration::FPMaxErrorDecorationINTEL,
+ {OpValue});
} else {
GR->buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getImm(),
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index a871518e2094c..caee778eddbc4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -312,6 +312,7 @@ defm SPV_INTEL_float_controls2 : ExtensionOperand<115>;
defm SPV_INTEL_bindless_images : ExtensionOperand<116>;
defm SPV_INTEL_long_composites : ExtensionOperand<117>;
defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>;
+defm SPV_INTEL_fp_max_error : ExtensionOperand<119>;
//===----------------------------------------------------------------------===//
// 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_
defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composites], []>;
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;
+defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
//===----------------------------------------------------------------------===//
// Multiclass used to define SourceLanguage enum values and at the same time
@@ -1261,6 +1263,7 @@ defm FunctionDenormModeINTEL : DecorationOperand<5823, 0, 0, [], [FunctionFloatC
defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [FunctionFloatControlINTEL]>;
defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>;
+defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>;
//===----------------------------------------------------------------------===//
// Multiclass used to define BuiltIn enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
new file mode 100644
index 0000000000000..66070181968e2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
@@ -0,0 +1,35 @@
+; Confirm that we handle fpmath metadata correctly
+; This is a copy of https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxErrorFPMath.ll
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o %t.spt
+; RUN: FileCheck %s --input-file=%t.spt
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_fp_max_error %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpCapability FPMaxErrorINTEL
+; CHECK: OpExtension "SPV_INTEL_fp_max_error"
+
+; CHECK: OpName %[[#CalleeName:]] "callee"
+; CHECK: OpName %[[#F3:]] "f3"
+; CHECK: OpDecorate %[[#F3]] FPMaxErrorDecorationINTEL 1075838976
+; CHECK: OpDecorate %[[#Callee:]] FPMaxErrorDecorationINTEL 1065353216
+
+; CHECK: %[[#FloatTy:]] = OpTypeFloat 32
+; CHECK: %[[#Callee]] = OpFunctionCall %[[#FloatTy]] %[[#CalleeName]]
+
+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"
+target triple = "spir64-unknown-unknown"
+
+define float @callee(float %f1, float %f2) {
+entry:
+ret float %f1
+}
+
+define void @test_fp_max_error_decoration(float %f1, float %f2) {
+entry:
+%f3 = fdiv float %f1, %f2, !fpmath !0
+call float @callee(float %f1, float %f2), !fpmath !1
+ret void
+}
+
+!0 = !{float 2.500000e+00}
+!1 = !{float 1.000000e+00}
|
@@ -307,6 +309,10 @@ SPIR-V backend, along with their descriptions and argument details. | |||
- None | |||
- `[Type, 32-bit Integer, Metadata]` | |||
- 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. | |||
* - `int_spv_assign_fpmaxerror_decoration` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to create a new intrinsic? I have a feeling, that this functionality can be added in handleMIFlagDecoration
function. (if it's possible) by casting instruction to FPMathOperator and calling getFPAccuracy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe FP-Math flags are not the same as !fpmath
metadata. I've added intrinsic to support the second case, but we can extend the extension usage to support your case too (we didn't have such support in Khronos though)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it is, see: https://llvm.org/doxygen/Instructions_8cpp_source.html#l02682
A valid point would be: llvm ir instruction != mir instruction, so API I'm referring above is not applicable. Yet during my recent work on aliasing metadata I've found, that information from aliasing metadata is being transferred to MachineMemOperand
class and I can access this information in the backend by calling getAAInfo
. I'm not sure, if it will work, as I'm still a novice in LLVM backend, yet I do see MO_FPImmediate
enum among MachineOperandType
class. Can we check, that it (or some other machine operand subclass) doesn't store accuracy information?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but it seems that we can't do that - handleMIFlagDecoration
is "too late" in the stack, and we don't have FP accuracy saved in BE machine instructions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll unresolve the thread just in case if other reviewers have something to say
Co-authored-by: Dmitry Sidorov <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Specification:
https://github.khronos.org/SPIRV-Registry/extensions/INTEL/SPV_INTEL_fp_max_error.html