[llvm] [RegAlloc] Avoid split past block-prologue interference (PR #209704)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 02:15:53 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Lukas Sommer (sommerlukas)

<details>
<summary>Changes</summary>

`leaveIntvAtTop` skips the target-specific block prologue when determining the insertion point.

If the block prologue itself contains an instruction that interferes with the interval, we must leave the interval before the block, otherwise we will hit an assertion in `splitLiveThroughBlock`.

---
Full diff: https://github.com/llvm/llvm-project/pull/209704.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/RegAllocGreedy.cpp (+8-1) 
- (added) llvm/test/CodeGen/AMDGPU/greedy-wwm-copy-prologue-assert.mir (+107) 


``````````diff
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index 6b8a9b8190f9a..799816191eca1 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -843,8 +843,15 @@ bool RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf,
         SlotIndex::isEarlierInstr(LIS->getInstructionIndex(*FirstNonDebugInstr),
                                   SA->getFirstSplitPoint(Number)))
       return false;
+
     // Interference for the live-in value.
-    if (Intf.first() <= Indexes->getMBBStartIdx(Number))
+    Register Reg = SA->getParent().reg();
+    auto InsertPt = MBB->SkipPHIsLabelsAndDebug(MBB->begin(), Reg);
+    SlotIndex InsertIdx = InsertPt == MBB->end()
+                              ? Indexes->getMBBEndIdx(Number)
+                              : LIS->getInstructionIndex(*InsertPt);
+    if (Intf.first() <= Indexes->getMBBStartIdx(Number) ||
+        SlotIndex::isEarlierInstr(Intf.first(), InsertIdx))
       BCS[B].Entry = SpillPlacement::MustSpill;
     else
       BCS[B].Entry = SpillPlacement::PrefSpill;
diff --git a/llvm/test/CodeGen/AMDGPU/greedy-wwm-copy-prologue-assert.mir b/llvm/test/CodeGen/AMDGPU/greedy-wwm-copy-prologue-assert.mir
new file mode 100644
index 0000000000000..0c59d92012e35
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/greedy-wwm-copy-prologue-assert.mir
@@ -0,0 +1,107 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=greedy -o - %s | FileCheck %s
+
+# Check that splitting doesn't attempt to split after the prologue, if the first
+# interference is in the prologue. The hot loop in bb.1 keeps %0 in $vgpr0.
+# On the cold exit, the pre-existing WWM_COPY in bb.2 is a block prologue and
+# also occupies $vgpr0. Therefore, we can't split in bb.2. In this case,
+# spilling is chosen instead.
+# This is a regression test for the SplitKit interference assertion in 
+# 'leaveIntvAtTop'.
+#
+--- |
+  define amdgpu_kernel void @wwm_copy_prologue_assert() #0 {
+    ret void
+  }
+
+  attributes #0 = { "amdgpu-num-vgpr"="2" }
+...
+---
+name:            wwm_copy_prologue_assert
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: vgpr_32, flags: [ WWM_REG ] }
+  - { id: 1, class: vgpr_32, flags: [ WWM_REG ] }
+machineFunctionInfo:
+  isEntryFunction: true
+  scratchRSrcReg:  '$sgpr0_sgpr1_sgpr2_sgpr3'
+  stackPtrOffsetReg: '$sgpr32'
+  sgprForEXECCopy: '$sgpr100_sgpr101'
+body:             |
+  ; CHECK-LABEL: name: wwm_copy_prologue_assert
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[V_ADD_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e32 $vgpr1, $vgpr1, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit [[V_ADD_U32_e32_]], implicit $vgpr1
+  ; CHECK-NEXT:   S_BRANCH %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.1(0x7fffffff), %bb.2(0x00000001)
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_NOP 0, implicit [[V_ADD_U32_e32_]], implicit $vgpr1
+  ; CHECK-NEXT:   S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
+  ; CHECK-NEXT:   S_BRANCH %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   SI_SPILL_WWM_V32_SAVE [[V_ADD_U32_e32_]], %stack.0, $sgpr32, 0, implicit $exec :: (store (s32) into %stack.0, addrspace 5)
+  ; CHECK-NEXT:   [[WWM_COPY:%[0-9]+]]:vgpr_32 = lr-split WWM_COPY $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4:
+  ; CHECK-NEXT:   successors: %bb.5(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_NOP 0, implicit [[WWM_COPY]], implicit $vgpr1
+  ; CHECK-NEXT:   [[SI_SPILL_WWM_V32_RESTORE:%[0-9]+]]:vgpr_32 = SI_SPILL_WWM_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load (s32) from %stack.0, addrspace 5)
+  ; CHECK-NEXT:   S_NOP 0, implicit [[SI_SPILL_WWM_V32_RESTORE]], implicit $vgpr1
+  ; CHECK-NEXT:   S_BRANCH %bb.5
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5:
+  ; CHECK-NEXT:   liveins: $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_NOP 0, implicit [[SI_SPILL_WWM_V32_RESTORE]], implicit $vgpr1
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1
+    liveins: $vgpr1
+    %0:vgpr_32 = V_ADD_U32_e32 $vgpr1, $vgpr1, implicit $exec
+    S_NOP 0, implicit %0, implicit $vgpr1
+    S_BRANCH %bb.1
+
+  bb.1:
+    successors: %bb.1(0x7fffffff), %bb.2(0x00000001)
+    liveins: $vgpr1
+    S_NOP 0, implicit %0, implicit $vgpr1
+    S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
+    S_BRANCH %bb.2
+
+  bb.2:
+    successors: %bb.3
+    liveins: $vgpr1
+    %1:vgpr_32 = lr-split WWM_COPY $vgpr1
+
+  bb.3:
+    successors: %bb.4
+    liveins: $vgpr1
+
+  bb.4:
+    successors: %bb.5
+    liveins: $vgpr1
+    S_NOP 0, implicit killed %1, implicit $vgpr1
+    S_NOP 0, implicit %0, implicit $vgpr1
+    S_BRANCH %bb.5
+
+  bb.5:
+    liveins: $vgpr1
+    S_NOP 0, implicit %0, implicit $vgpr1
+    S_ENDPGM 0
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/209704


More information about the llvm-commits mailing list