Skip to content

Commit 2165452

Browse files
bowenxue-inteldbudanov-cmplr
authored andcommitted
Implement SPIR-V support for max_reinvocation_delay attribute (#1594)
The attribute generates the llvm.loop.intel.max_reinvocation_delay.count metadata in LLVM IR. There is one positive integer literal operand denoting the maximum number of cycles allowed between loop invocations. Spec: KhronosGroup/SPIRV-Registry#163 Original commit: KhronosGroup/SPIRV-LLVM-Translator@d4ec010
1 parent 17e8603 commit 2165452

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,14 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM,
946946
"llvm.loop.intel.loopcount_avg", static_cast<int64_t>(LoopCountAvg)));
947947
}
948948
}
949+
if (LC & spv::internal::LoopControlMaxReinvocationDelayINTELMask) {
950+
Metadata.push_back(llvm::MDNode::get(
951+
*Context, getMetadataFromNameAndParameter(
952+
"llvm.loop.intel.max_reinvocation_delay.count",
953+
LoopControlParameters[NumParam++])));
954+
assert(NumParam <= LoopControlParameters.size() &&
955+
"Missing loop control parameter!");
956+
}
949957
llvm::MDNode *Node = llvm::MDNode::get(*Context, Metadata);
950958

951959
// Set the first operand to refer itself

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,14 @@ LLVMToSPIRVBase::getLoopControl(const BranchInst *Branch,
14851485
BM->addCapability(CapabilityFPGALoopControlsINTEL);
14861486
LoopCount.Avg = getMDOperandAsInt(Node, 1);
14871487
LoopControl |= spv::internal::LoopControlLoopCountINTELMask;
1488+
} else if (S == "llvm.loop.intel.max_reinvocation_delay.count") {
1489+
BM->addExtension(ExtensionID::SPV_INTEL_fpga_loop_controls);
1490+
BM->addCapability(CapabilityFPGALoopControlsINTEL);
1491+
size_t I = getMDOperandAsInt(Node, 1);
1492+
ParametersToSort.emplace_back(
1493+
spv::internal::LoopControlMaxReinvocationDelayINTELMask, I);
1494+
LoopControl |=
1495+
spv::internal::LoopControlMaxReinvocationDelayINTELMask;
14881496
}
14891497
}
14901498
}

llvm-spirv/lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ enum InternalExecutionMode {
8888
IExecModeStreamingInterfaceINTEL = 6154
8989
};
9090

91-
enum InternalLoopControlMask { ILoopControlLoopCountINTELMask = 0x1000000 };
91+
enum InternalLoopControlMask {
92+
ILoopControlLoopCountINTELMask = 0x1000000,
93+
ILoopControlMaxReinvocationDelayINTELMask = 0x2000000
94+
};
9295

9396
constexpr LinkageType LinkageTypeInternal =
9497
static_cast<LinkageType>(ILTInternal);
@@ -186,6 +189,8 @@ constexpr ExecutionMode ExecutionModeStreamingInterfaceINTEL =
186189

187190
static const LoopControlMask LoopControlLoopCountINTELMask =
188191
static_cast<LoopControlMask>(ILoopControlLoopCountINTELMask);
192+
static const LoopControlMask LoopControlMaxReinvocationDelayINTELMask =
193+
static_cast<LoopControlMask>(ILoopControlMaxReinvocationDelayINTELMask);
189194

190195
} // namespace internal
191196
} // namespace spv

llvm-spirv/test/transcoding/SPV_INTEL_fpga_loop_controls/FPGALoopMergeInst.ll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@
9090
; for (int i = 0; i != 10; ++i)
9191
; a[i] = 0;
9292
; }
93+
;
94+
; void max_reinvocation_delay() {
95+
; int a[10];
96+
; [[intel::max_reinvocation_delay(2)]]
97+
; for (int i = 0; i != 10; ++i)
98+
; a[i] = 0;
99+
; }
100+
93101

94102
; TODO: This source code will result in different LLVM IR after
95103
; rev [a47242e4b2c1c9] of https://github.com/intel/llvm (the
@@ -478,6 +486,40 @@ for.end: ; preds = %for.cond
478486
ret void
479487
}
480488

489+
; Function Attrs: noinline nounwind optnone
490+
define spir_func void @max_reinvocation_delay() #3 {
491+
entry:
492+
%a = alloca [10 x i32], align 4
493+
%i = alloca i32, align 4
494+
store i32 0, i32* %i, align 4
495+
br label %for.cond
496+
497+
; Per SPIR-V spec, LoopControlMaxReinvocationDelayINTELMask = 0x2000000 (33554432)
498+
; CHECK-SPIRV: 5 LoopMerge {{[0-9]+}} {{[0-9]+}} 33554432 2
499+
; CHECK-SPIRV-NEXT: 4 BranchConditional {{[0-9]+}} {{[0-9]+}} {{[0-9]+}}
500+
; CHECK-SPIRV-NEGATIVE-NOT: 5 LoopMerge {{[0-9]+}} {{[0-9]+}} 33554432 2
501+
for.cond: ; preds = %for.inc, %entry
502+
%0 = load i32, i32* %i, align 4
503+
%cmp = icmp ne i32 %0, 10
504+
br i1 %cmp, label %for.body, label %for.end
505+
506+
for.body: ; preds = %for.cond
507+
%1 = load i32, i32* %i, align 4
508+
%idxprom = sext i32 %1 to i64
509+
%arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %a, i64 0, i64 %idxprom
510+
store i32 0, i32* %arrayidx, align 4
511+
br label %for.inc
512+
513+
for.inc: ; preds = %for.body
514+
%2 = load i32, i32* %i, align 4
515+
%inc = add nsw i32 %2, 1
516+
store i32 %inc, i32* %i, align 4
517+
br label %for.cond, !llvm.loop !31
518+
519+
for.end: ; preds = %for.cond
520+
ret void
521+
}
522+
481523
attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "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"="false" "stack-protector-buffer-size"="8" "sycl-module-id"="FPGALoopMergeInst.cpp" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" }
482524
attributes #1 = { argmemonly nounwind willreturn }
483525
attributes #2 = { inlinehint nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "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"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
@@ -520,6 +562,8 @@ attributes #4 = { nounwind }
520562
!28 = !{!"llvm.loop.intel.speculated.iterations.count", i32 4}
521563
!29 = distinct !{!29, !30}
522564
!30 = !{!"llvm.loop.fusion.disable"}
565+
!31 = distinct !{!31, !32}
566+
!32 = !{!"llvm.loop.intel.max_reinvocation_delay.count", i32 2}
523567

524568
; CHECK-LLVM: br label %while.cond, !llvm.loop ![[MD_A:[0-9]+]]
525569
; CHECK-LLVM: br label %while.cond{{[0-9]+}}, !llvm.loop ![[MD_B:[0-9]+]]
@@ -531,6 +575,7 @@ attributes #4 = { nounwind }
531575
; CHECK-LLVM: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_H:[0-9]+]]
532576
; CHECK-LLVM: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_I:[0-9]+]]
533577
; CHECK-LLVM: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_NF:[0-9]+]]
578+
; CHECK-LLVM: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_MRD:[0-9]+]]
534579

535580
; CHECK-LLVM: ![[MD_A]] = distinct !{![[MD_A]], ![[MD_ivdep_enable:[0-9]+]]}
536581
; CHECK-LLVM: ![[MD_ivdep_enable]] = !{!"llvm.loop.ivdep.enable"}
@@ -553,3 +598,5 @@ attributes #4 = { nounwind }
553598
; CHECK-LLVM: ![[MD_spec_iterations]] = !{!"llvm.loop.intel.speculated.iterations.count", i32 4}
554599
; CHECK-LLVM: ![[MD_NF]] = distinct !{![[MD_NF]], ![[MD_nofusion:[0-9]+]]}
555600
; CHECK-LLVM: ![[MD_nofusion]] = !{!"llvm.loop.fusion.disable"}
601+
; CHECK-LLVM: ![[MD_MRD]] = distinct !{![[MD_MRD]], ![[MD_max_reinvocation_delay:[0-9]+]]}
602+
; CHECK-LLVM: ![[MD_max_reinvocation_delay]] = !{!"llvm.loop.intel.max_reinvocation_delay.count", i32 2}

0 commit comments

Comments
 (0)