diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index b6781226c..0b468c217 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -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 @@ -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 diff --git a/test/OpLoopMerge_mergeBlock.ll b/test/OpLoopMerge_mergeBlock.ll new file mode 100644 index 000000000..883033eb8 --- /dev/null +++ b/test/OpLoopMerge_mergeBlock.ll @@ -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"}