Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion llvm/docs/SPIRVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
54 changes: 51 additions & 3 deletions llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -1976,17 +1978,63 @@ 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<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,
MachineInstr &MI) {
Register Des = MI.getOperand(0).getReg();
MachineInstr *curr = &MI;
// dsp controll
if (llvm::MDNode *Node = F->getMetadata("prefer_dsp")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets not use internal to intel/llvm metadata, see discussion in #131593

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);
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) {
for (auto F = M.begin(), E = M.end(); F != E; ++F) {
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);
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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}
Original file line number Diff line number Diff line change
@@ -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}