[llvm] [TwoAddressInstruction] Drop physreg ranges after unfolding a load (PR #227538)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 29 19:48:56 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Vitaly Buka (vitalybuka)
<details>
<summary>Changes</summary>
Since #<!-- -->225174 LiveIntervals is computed before TwoAddressInstructions.
When tryInstructionTransform() unfolds a load, e.g. OR64rm into
MOV64rm + OR64rr, it calls repairIntervalsInRange(). That function
only repairs virtual registers. If the regunit range of a physreg def
of the original instruction ($eflags here) was already cached, it
keeps a value defined at the slot of the erased instruction.
The machine verifier then reports "No instruction at VNInfo def index"
and later passes hit `LR.verify()` in LiveIntervals::HMEditor. This
broke the MSan bootstrap build of clang/lib/Sema/SemaAPINotes.cpp.
Drop the cached regunit ranges for the physregs of the unfolded
instruction so they are recomputed on demand. MachineBasicBlock.cpp
already does the same after repairIntervalsInRange().
Assisted-by: Gemini
---
Full diff: https://github.com/llvm/llvm-project/pull/227538.diff
2 Files Affected:
- (modified) llvm/lib/CodeGen/TwoAddressInstructionPass.cpp (+8)
- (added) llvm/test/CodeGen/X86/twoaddr-unfold-load-eflags-liveintervals.mir (+55)
``````````diff
diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index b84391817893d..9adc5a27e223b 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -1530,6 +1530,14 @@ bool TwoAddressInstructionImpl::tryInstructionTransform(
MachineBasicBlock::iterator Begin(NewMIs[0]);
MachineBasicBlock::iterator End(NewMIs[1]);
LIS->repairIntervalsInRange(MBB, Begin, End, OrigRegs);
+
+ // repairIntervalsInRange() does not update physregs; clear their
+ // ranges since the original instruction's defs (e.g. of EFLAGS)
+ // were replaced.
+ for (Register Reg : OrigRegs) {
+ if (Reg.isPhysical())
+ LIS->removeAllRegUnitsForPhysReg(Reg.asMCReg());
+ }
}
mi = NewMIs[1];
diff --git a/llvm/test/CodeGen/X86/twoaddr-unfold-load-eflags-liveintervals.mir b/llvm/test/CodeGen/X86/twoaddr-unfold-load-eflags-liveintervals.mir
new file mode 100644
index 0000000000000..48c2aac654ed6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/twoaddr-unfold-load-eflags-liveintervals.mir
@@ -0,0 +1,55 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=x86_64-- -run-pass=liveintervals,twoaddressinstruction -verify-machineinstrs -o - %s | FileCheck %s
+
+# Unfolding the load out of OR64rm replaces the instruction defining $eflags.
+# The cached $eflags regunit live range must not keep pointing at the erased
+# instruction.
+
+---
+name: unfold_load_eflags
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: unfold_load_eflags
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: liveins: $eflags, $rdi, $rsi
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64 = COPY $rsi
+ ; CHECK-NEXT: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s64))
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64 = COPY [[MOV64rm]]
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64 = OR64rr [[COPY2]], [[COPY1]], implicit-def $eflags
+ ; CHECK-NEXT: JCC_1 %bb.2, 4, implicit $eflags
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: liveins: $eflags
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 5, implicit $eflags
+ ; CHECK-NEXT: $al = COPY [[SETCCr]]
+ ; CHECK-NEXT: $rdx = COPY [[COPY1]]
+ ; CHECK-NEXT: RET 0, implicit $al, implicit $rdx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: $rax = COPY [[COPY2]]
+ ; CHECK-NEXT: RET 0, implicit $rax
+ bb.0:
+ successors: %bb.1, %bb.2
+ liveins: $eflags, $rdi, $rsi
+
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = OR64rm %1, %0, 1, $noreg, 0, $noreg, implicit-def $eflags :: (load (s64))
+ JCC_1 %bb.2, 4, implicit $eflags
+
+ bb.1:
+ liveins: $eflags
+
+ %3:gr8 = SETCCr 5, implicit killed $eflags
+ $al = COPY %3
+ $rdx = COPY %1
+ RET 0, implicit $al, implicit $rdx
+
+ bb.2:
+ $rax = COPY %2
+ RET 0, implicit $rax
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/227538
More information about the llvm-commits
mailing list