[llvm] FEAT: Added support for the extension SPV_INTEL_fpga_dsp_control (PR #131651)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 5 02:49:10 PDT 2025
https://github.com/sumesh-s-mcw updated https://github.com/llvm/llvm-project/pull/131651
>From 137a801a721cab64ca9f7e08e7e262fba89a52d9 Mon Sep 17 00:00:00 2001
From: sumesh-s-mcw <sumesh.suresh at multicorewareinc.com>
Date: Mon, 5 May 2025 14:34:54 +0530
Subject: [PATCH 1/2] Added support for SPV_INTEL_fpga_dsp_control
---
llvm/docs/SPIRVUsage.rst | 4 +-
llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 2 +
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 56 +++++++++++++
.../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 2 +
.../SPV_INTEL_fpga_dsp_control/prefer_dsp.ll | 78 +++++++++++++++++++
.../prefer_dsp_propagate.ll | 78 +++++++++++++++++++
6 files changed, 219 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp.ll
create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp_propagate.ll
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 6ff8034cac00c..b2a8bae7b85a4 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -212,7 +212,9 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
* - ``SPV_INTEL_ternary_bitwise_function``
- Adds a bitwise instruction on three operands and a look-up table index for specifying the bitwise operation to perform.
* - ``SPV_INTEL_subgroup_matrix_multiply_accumulate``
- - Adds an instruction to compute the matrix product of an M x K matrix with a K x N matrix and then add an M x N matrix.
+ - Adds an instruction to compute the matrix product of an M x K matrix with a K x N matrix and then add an M x N matrix.
+ * - ``SPV_INTEL_fpga_dsp_control``
+ - Enables control over whether certain floating-point operations should be implemented using DSP blocks or logic elements on FPGA hardware, allowing fine-tuned optimization of resource usage and performance.
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:
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index 56cbd9414c9ee..a6f0c1623df31 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -87,6 +87,8 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
SPIRV::Extension::Extension::SPV_KHR_shader_clock},
{"SPV_KHR_cooperative_matrix",
SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},
+ {"SPV_INTEL_fpga_dsp_control",
+ SPIRV::Extension::Extension::SPV_INTEL_fpga_dsp_control},
{"SPV_KHR_non_semantic_info",
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
{"SPV_INTEL_long_composites",
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 6d2ecd563d200..6ac3edd4ea56f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -920,6 +920,8 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
} else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
+ }else if (Dec == SPIRV::Decoration::MathOpDSPModeINTEL) {
+ Reqs.addExtension(SPIRV::Extension::Extension::SPV_INTEL_fpga_dsp_control);
}
}
@@ -1975,6 +1977,59 @@ static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST,
Register DstReg = I.getOperand(0).getReg();
buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags});
}
+static std::vector<uint32_t>
+getMetaDataValues(std::vector<llvm::MDNode *> &MetaDataList) {
+ std::vector<uint32_t> res;
+ for (auto metaDataNode : MetaDataList) {
+ if (metaDataNode->getNumOperands() > 0) {
+ if (auto *CMD = llvm::dyn_cast<llvm::ConstantAsMetadata>(
+ metaDataNode->getOperand(0))) {
+ if (auto *CI = llvm::dyn_cast<llvm::ConstantInt>(CMD->getValue())) {
+ APInt val = CI->getValue();
+ int64_t decVal = val.getZExtValue();
+ res.push_back(decVal);
+ }
+ }
+ }
+ }
+ return res;
+}
+
+static void handleFunctionDecoration(llvm::Module::const_iterator F,
+ const SPIRVInstrInfo &TII,
+ MachineModuleInfo *MMI,
+ const SPIRVSubtarget &ST) {
+
+ MachineFunction *MF = MMI->getMachineFunction(*F);
+ Register Des = Register();
+ MachineInstr *curr = nullptr;
+
+ for (auto &MBB : *MF) {
+ for (auto &MI : MBB) {
+ if (MI.getOpcode() == SPIRV::OpFunction) {
+ if (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()) {
+ Des = MI.getOperand(0).getReg();
+ curr = &MI;
+ }
+ }
+ }
+ }
+
+ // dsp controll
+ if (llvm::MDNode *Node = F->getMetadata("prefer_dsp")) {
+ std::vector<llvm::MDNode *> MetaDataList;
+ MetaDataList.push_back(Node);
+ if (llvm::MDNode *Node = F->getMetadata("propagate_dsp_preference"))
+ MetaDataList.push_back(Node);
+ if (ST.canUseExtension(
+ SPIRV::Extension::Extension::SPV_INTEL_fpga_dsp_control)) {
+ std::vector<uint32_t> params = getMetaDataValues(MetaDataList);
+ params.push_back(0);
+ buildOpDecorate(Des, *curr, TII, SPIRV::Decoration::MathOpDSPModeINTEL,
+ params);
+ }
+ }
+}
// Walk all functions and add decorations related to MI flags.
static void addDecorations(const Module &M, const SPIRVInstrInfo &TII,
@@ -1987,6 +2042,7 @@ static void addDecorations(const Module &M, const SPIRVInstrInfo &TII,
for (auto &MBB : *MF)
for (auto &MI : MBB)
handleMIFlagDecoration(MI, ST, TII, MAI.Reqs);
+ handleFunctionDecoration(F, TII, MMI, ST);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index cc32200a0a261..86a5d47a8f267 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -517,6 +517,7 @@ defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory
defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
defm TernaryBitwiseFunctionINTEL : CapabilityOperand<6241, 0, 0, [SPV_INTEL_ternary_bitwise_function], []>;
defm SubgroupMatrixMultiplyAccumulateINTEL : CapabilityOperand<6236, 0, 0, [SPV_INTEL_subgroup_matrix_multiply_accumulate], []>;
+defm FPGADSPControlINTEL : CapabilityOperand<5908, 0, 0, [SPV_INTEL_fpga_dsp_control], []>;
//===----------------------------------------------------------------------===//
// Multiclass used to define SourceLanguage enum values and at the same time
@@ -1268,6 +1269,7 @@ defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [Functio
defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>;
+defm MathOpDSPModeINTEL : DecorationOperand<5909, 0, 0, [], [FPGADSPControlINTEL]>;
//===----------------------------------------------------------------------===//
// Multiclass used to define BuiltIn enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp.ll
new file mode 100644
index 0000000000000..79df86b55b9ef
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp.ll
@@ -0,0 +1,78 @@
+; template<typename Function>
+; [[intel::prefer_dsp]]
+; void math_prefer_dsp_propagate(Function f)
+; {
+; f();
+; }
+
+; int main() {
+; math_prefer_dsp_propagate([]() {
+; int a = 0;
+; a += 1;
+; });
+
+; return 0;
+; }
+
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_fpga_dsp_control %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV
+
+
+; CHECK-SPIRV: OpCapability FPGADSPControlINTEL
+; CHECK-SPIRV: OpExtension "SPV_INTEL_fpga_dsp_control"
+; CHECK-SPIRV: OpName %[[#FuncNameId:]] "_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"
+; CHECK-SPIRV: OpDecorate %[[#FuncNameId]] MathOpDSPModeINTEL 1 0
+
+
+; ModuleID = 'prefer_dsp.cpp'
+source_filename = "prefer_dsp.cpp"
+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"
+
+%class.anon = type { i8 }
+
+; Function Attrs: noinline norecurse optnone mustprogress
+define dso_local i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ %agg.tmp = alloca %class.anon, align 1
+ store i32 0, ptr %retval, align 4
+ call spir_func void @"_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"(ptr byval(%class.anon) align 1 %agg.tmp)
+ ret i32 0
+}
+
+; Function Attrs: noinline optnone mustprogress
+define internal spir_func void @"_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"(ptr byval(%class.anon) align 1 %f) #1 !prefer_dsp !3 {
+entry:
+ call spir_func void @"_ZZ4mainENK3$_0clEv"(ptr nonnull dereferenceable(1) %f)
+ ret void
+}
+
+; Function Attrs: noinline nounwind optnone mustprogress
+define internal spir_func void @"_ZZ4mainENK3$_0clEv"(ptr nonnull dereferenceable(1) %this) #2 align 2 {
+entry:
+ %this.addr = alloca ptr, align 8
+ %a = alloca i32, align 4
+ store ptr %this, ptr %this.addr, align 8
+ %this1 = load ptr, ptr %this.addr, align 8
+ store i32 0, ptr %a, align 4
+ %0 = load i32, ptr %a, align 4
+ %add = add nsw i32 %0, 1
+ store i32 %add, ptr %a, align 4
+ ret void
+}
+
+attributes #0 = { noinline norecurse optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noinline optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { noinline nounwind optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0}
+!opencl.used.extensions = !{!1}
+!opencl.used.optional.core.features = !{!1}
+!opencl.compiler.options = !{!1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{}
+!2 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 7d09e1d7cf27ce781e83f9d388a7a3e1e6487ead)"}
+!3 = !{i32 1}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp_propagate.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp_propagate.ll
new file mode 100644
index 0000000000000..7c8bf383c9a08
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_fpga_dsp_control/prefer_dsp_propagate.ll
@@ -0,0 +1,78 @@
+; template<typename Function>
+; [[intel::prefer_dsp]]
+; [[intel::propagate_dsp_preference]]
+; void math_prefer_dsp_propagate(Function f)
+; {
+; f();
+; }
+
+; int main() {
+; math_prefer_dsp_propagate([]() {
+; int a = 0;
+; a += 1;
+; });
+
+; return 0;
+; }
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_fpga_dsp_control %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV
+
+
+; CHECK-SPIRV: OpCapability FPGADSPControlINTEL
+; CHECK-SPIRV: OpExtension "SPV_INTEL_fpga_dsp_control"
+; CHECK-SPIRV: OpName %[[#FuncNameId:]] "_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"
+; CHECK-SPIRV: OpDecorate %[[#FuncNameId]] MathOpDSPModeINTEL 1 1
+
+
+; ModuleID = 'prefer_dsp_propagate.cpp'
+source_filename = "prefer_dsp_propagate.cpp"
+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"
+
+%class.anon = type { i8 }
+
+; Function Attrs: noinline norecurse optnone mustprogress
+define dso_local i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ %agg.tmp = alloca %class.anon, align 1
+ store i32 0, ptr %retval, align 4
+ call spir_func void @"_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"(ptr byval(%class.anon) align 1 %agg.tmp)
+ ret i32 0
+}
+
+; Function Attrs: noinline optnone mustprogress
+define internal spir_func void @"_Z25math_prefer_dsp_propagateIZ4mainE3$_0EvT_"(ptr byval(%class.anon) align 1 %f) #1 !prefer_dsp !3 !propagate_dsp_preference !3 {
+entry:
+ call spir_func void @"_ZZ4mainENK3$_0clEv"(ptr nonnull dereferenceable(1) %f)
+ ret void
+}
+
+; Function Attrs: noinline nounwind optnone mustprogress
+define internal spir_func void @"_ZZ4mainENK3$_0clEv"(ptr nonnull dereferenceable(1) %this) #2 align 2 {
+entry:
+ %this.addr = alloca ptr, align 8
+ %a = alloca i32, align 4
+ store ptr %this, ptr %this.addr, align 8
+ %this1 = load ptr, ptr %this.addr, align 8
+ store i32 0, ptr %a, align 4
+ %0 = load i32, ptr %a, align 4
+ %add = add nsw i32 %0, 1
+ store i32 %add, ptr %a, align 4
+ ret void
+}
+
+attributes #0 = { noinline norecurse optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noinline optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { noinline nounwind optnone mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0}
+!opencl.used.extensions = !{!1}
+!opencl.used.optional.core.features = !{!1}
+!opencl.compiler.options = !{!1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{}
+!2 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 7d09e1d7cf27ce781e83f9d388a7a3e1e6487ead)"}
+!3 = !{i32 1}
>From 23e9533c4f65f6962a9217662a5dae12296709d6 Mon Sep 17 00:00:00 2001
From: sumesh-s-mcw <sumesh.suresh at multicorewareinc.com>
Date: Mon, 5 May 2025 14:42:10 +0530
Subject: [PATCH 2/2] fix
---
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 6ac3edd4ea56f..48b03907748d0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -920,7 +920,7 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
} else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL);
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
- }else if (Dec == SPIRV::Decoration::MathOpDSPModeINTEL) {
+ } else if (Dec == SPIRV::Decoration::MathOpDSPModeINTEL) {
Reqs.addExtension(SPIRV::Extension::Extension::SPV_INTEL_fpga_dsp_control);
}
}
@@ -2024,7 +2024,8 @@ static void handleFunctionDecoration(llvm::Module::const_iterator F,
if (ST.canUseExtension(
SPIRV::Extension::Extension::SPV_INTEL_fpga_dsp_control)) {
std::vector<uint32_t> params = getMetaDataValues(MetaDataList);
- params.push_back(0);
+ if (params.size() == 1)
+ params.push_back(0);
buildOpDecorate(Des, *curr, TII, SPIRV::Decoration::MathOpDSPModeINTEL,
params);
}
More information about the llvm-commits
mailing list