From ae56ee948ce8cea60811b55ac129d297acf11885 Mon Sep 17 00:00:00 2001 From: Paulius Velesko Date: Mon, 15 Dec 2025 05:42:26 +0200 Subject: [PATCH 1/2] Add test for OpLoopMerge merge block conflict --- test/OpLoopMerge_mergeBlock.ll | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/OpLoopMerge_mergeBlock.ll diff --git a/test/OpLoopMerge_mergeBlock.ll b/test/OpLoopMerge_mergeBlock.ll new file mode 100644 index 0000000000..01ac1896d0 --- /dev/null +++ b/test/OpLoopMerge_mergeBlock.ll @@ -0,0 +1,28 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: spirv-val %t.spv + +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"} From dbe6a98e7a8f05314bb1492a5b4044d49f187811 Mon Sep 17 00:00:00 2001 From: Paulius Velesko Date: Mon, 15 Dec 2025 05:42:53 +0200 Subject: [PATCH 2/2] Fix merge block conflict for nested loops --- lib/SPIRV/SPIRVWriter.cpp | 10 +++++++--- test/OpLoopMerge_mergeBlock.ll | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index b6781226c2..0b468c2176 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 index 01ac1896d0..883033eb8f 100644 --- a/test/OpLoopMerge_mergeBlock.ll +++ b/test/OpLoopMerge_mergeBlock.ll @@ -1,6 +1,10 @@ ; 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"