Skip to content
Open
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
10 changes: 7 additions & 3 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2512,7 +2512,11 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
Function *Fun = Branch->getFunction();
DominatorTree DomTree(*Fun);
LoopInfo LI(DomTree);
for (const auto *LoopObj : LI.getLoopsInPreorder()) {
// Find the innermost loop that contains the current basic block.
BasicBlock *CurrentBB = Branch->getParent();
const Loop *ContainingLoop = LI.getLoopFor(CurrentBB);

if (ContainingLoop) {
// Check whether SuccessorFalse or SuccessorTrue is the loop header BB.
// For example consider following LLVM IR:
// br i1 %compare, label %for.body, label %for.end
Expand All @@ -2521,12 +2525,12 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
// <- SuccessorTrue is 'for.end' aka successor(1)
// meanwhile the true successor (by definition) should be a loop header
// aka 'for.body'
if (LoopObj->getHeader() == Branch->getSuccessor(1))
if (ContainingLoop->getHeader() == Branch->getSuccessor(1))
// SuccessorFalse is the loop header BB.
BM->addLoopMergeInst(SuccessorTrue->getId(), // Merge Block
BB->getId(), // Continue Target
LoopControl, Parameters, SuccessorFalse);
else
else if (ContainingLoop->getHeader() == Branch->getSuccessor(0))
// SuccessorTrue is the loop header BB.
BM->addLoopMergeInst(SuccessorFalse->getId(), // Merge Block
BB->getId(), // Continue Target
Expand Down
32 changes: 32 additions & 0 deletions test/OpLoopMerge_mergeBlock.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; RUN: llvm-as %s -o %t.bc
; RUN: llvm-spirv %t.bc -o %t.spv
; RUN: spirv-val %t.spv
; RUN: llvm-spirv --to-text %t.spv -o - | FileCheck %s

; CHECK: LoopMerge
; CHECK-NEXT: BranchConditional

target triple = "spir64"

define spir_kernel void @test(i32 %n) {
entry:
%cmp0 = icmp sgt i32 %n, 0
br i1 %cmp0, label %outer, label %exit
outer:
%i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
%cmp1 = icmp eq i32 %i, 0
br i1 %cmp1, label %latch, label %inner
inner:
%cmp2 = icmp eq i32 %i, 1
br i1 %cmp2, label %latch, label %inner, !llvm.loop !1
latch:
%i.next = add i32 %i, 1
%cmp3 = icmp slt i32 %i.next, %n
br i1 %cmp3, label %outer, label %exit, !llvm.loop !0
exit:
ret void
}

!0 = distinct !{!0, !2}
!1 = distinct !{!1, !2}
!2 = !{!"llvm.loop.unroll.disable"}
Loading