[llvm] CodeGen: Clear physreg ranges after SplitCriticalEdge (PR #223172)

via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 12 13:39:47 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

After critical edge spliting replaces a terminator, clear referenced
physreg ranges. The block's terminators may be replaced, and may
reference physical registers (e.g. WebAssebly's ARGUMENTS. When
LiveIntervals is available, repairIntervalsInRange only repairs virtual
registers, so the tracked physreg units were stale.

It feels like a bug that repairIntervalsInRange doesn't touch physregs,
but I've left that for a future change.

Co-Authored-By: Claude claude-opus-4.8 <noreply@<!-- -->anthropic.com>

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


2 Files Affected:

- (modified) llvm/lib/CodeGen/MachineBasicBlock.cpp (+7) 
- (added) llvm/test/CodeGen/WebAssembly/splitcriticaledge-physreg-liveness.mir (+60) 


``````````diff
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 736e455740547..fe9f9a52c3d7b 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -1388,6 +1388,13 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
     // Update all intervals for registers whose uses may have been modified by
     // updateTerminator().
     LIS->repairIntervalsInRange(this, getFirstTerminator(), end(), UsedRegs);
+
+    // repairIntervalsInRange() does not update physregs; clear their ranges
+    // since updateTerminator() may have replaced defs.
+    for (Register Reg : UsedRegs) {
+      if (Reg.isPhysical())
+        LIS->removeAllRegUnitsForPhysReg(Reg.asMCReg());
+    }
   }
 
   if (MDTU)
diff --git a/llvm/test/CodeGen/WebAssembly/splitcriticaledge-physreg-liveness.mir b/llvm/test/CodeGen/WebAssembly/splitcriticaledge-physreg-liveness.mir
new file mode 100644
index 0000000000000..e3b4b7d966f6d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/splitcriticaledge-physreg-liveness.mir
@@ -0,0 +1,60 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm32-unknown-unknown \
+# RUN:     -run-pass=liveintervals,phi-node-elimination \
+# RUN:     -precompute-phys-liveness -verify-machineinstrs %s -o - | FileCheck %s
+
+# Splitting the critical edge bb.0 -> bb.2 rewrites terminators that
+# def the ARGUMENTS physreg. Its regunit ranges must be recomputed.
+
+---
+name:            split_physreg_terminator
+tracksRegLiveness: true
+liveins:
+  - { reg: '$arguments' }
+body: |
+  ; CHECK-LABEL: name: split_physreg_terminator
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.3(0x40000000)
+  ; CHECK-NEXT:   liveins: $arguments
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+  ; CHECK-NEXT:   [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 -1, implicit-def dead $arguments
+  ; CHECK-NEXT:   [[GT_S_I32_:%[0-9]+]]:i32 = GT_S_I32 [[ARGUMENT_i32_]], [[CONST_I32_]], implicit-def dead $arguments
+  ; CHECK-NEXT:   BR_UNLESS %bb.1, [[GT_S_I32_]], implicit-def $arguments
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:i32 = COPY [[ARGUMENT_i32_]]
+  ; CHECK-NEXT:   BR %bb.2, implicit-def $arguments
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[CONST_I32_1:%[0-9]+]]:i32 = CONST_I32 3, implicit-def dead $arguments
+  ; CHECK-NEXT:   [[DIV_S_I32_:%[0-9]+]]:i32 = DIV_S_I32 [[ARGUMENT_i32_]], [[CONST_I32_1]], implicit-def dead $arguments
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:i32 = COPY [[DIV_S_I32_]]
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:i32 = COPY [[COPY]]
+  ; CHECK-NEXT:   RETURN [[COPY1]], implicit-def dead $arguments
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $arguments
+
+    %0:i32 = ARGUMENT_i32 0, implicit killed $arguments
+    %1:i32 = CONST_I32 -1, implicit-def dead $arguments
+    %2:i32 = GT_S_I32 %0, killed %1, implicit-def dead $arguments
+    BR_IF %bb.2, killed %2, implicit-def dead $arguments
+    BR %bb.1, implicit-def dead $arguments
+
+  bb.1:
+    successors: %bb.2
+
+    %3:i32 = CONST_I32 3, implicit-def dead $arguments
+    %4:i32 = DIV_S_I32 killed %0, killed %3, implicit-def dead $arguments
+
+  bb.2:
+    %5:i32 = PHI %0, %bb.0, %4, %bb.1
+    RETURN killed %5, implicit-def dead $arguments
+...

``````````

</details>


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


More information about the llvm-commits mailing list