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> 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..29efdb1038f5f 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); } } @@ -1976,7 +1978,49 @@ static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags}); } -// Walk all functions and add decorations related to MI flags. +static std::vector +getMetaDataValues(std::vector &MetaDataList) { + std::vector res; + for (auto metaDataNode : MetaDataList) { + if (metaDataNode->getNumOperands() > 0) { + if (auto *CMD = llvm::dyn_cast( + metaDataNode->getOperand(0))) { + if (auto *CI = llvm::dyn_cast(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, + MachineInstr &MI) { + Register Des = MI.getOperand(0).getReg(); + MachineInstr *curr = &MI; + // dsp controll + if (llvm::MDNode *Node = F->getMetadata("prefer_dsp")) { + std::vector 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 params = getMetaDataValues(MetaDataList); + if (params.size() == 1) + params.push_back(0); + buildOpDecorate(Des, *curr, TII, SPIRV::Decoration::MathOpDSPModeINTEL, + params); + } + } +} + +// Walk all functions and add decorations related to MI flags and function metadata. static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI) { @@ -1984,9 +2028,13 @@ static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineFunction *MF = MMI->getMachineFunction(*F); if (!MF) continue; - for (auto &MBB : *MF) - for (auto &MI : MBB) + for (auto &MBB : *MF) { + for (auto &MI : MBB) { + if (MI.getOpcode() == SPIRV::OpFunction) + handleFunctionDecoration(F, TII, MMI, ST, MI); handleMIFlagDecoration(MI, ST, TII, MAI.Reqs); + } + } } } 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 +; [[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 +; [[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}