[llvm] ba6bb69 - [RegAlloc] Fix register's live range for early-clobber (#152895)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 19 18:03:02 PDT 2025


Author: Luo, Yuanke
Date: 2025-08-20T09:02:59+08:00
New Revision: ba6bb6929e7eb934f86adb1a942d2d274d18b1dd

URL: https://github.com/llvm/llvm-project/commit/ba6bb6929e7eb934f86adb1a942d2d274d18b1dd
DIFF: https://github.com/llvm/llvm-project/commit/ba6bb6929e7eb934f86adb1a942d2d274d18b1dd.diff

LOG: [RegAlloc] Fix register's live range for early-clobber (#152895)

When rematerialize a virtual register the register may be early
clobbered.
However rematerializeAt(...) just return the slot index of Slot_Register
which cause mis-calculating live range for the register

---------

Co-authored-by: Yuanke Luo <ykluo at birentech.com>

Added: 
    llvm/test/CodeGen/X86/early-clobber.mir

Modified: 
    llvm/lib/CodeGen/LiveRangeEdit.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index a3858efbdc5e1..5514e4eb6cf3e 100644
--- a/llvm/lib/CodeGen/LiveRangeEdit.cpp
+++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp
@@ -190,9 +190,12 @@ SlotIndex LiveRangeEdit::rematerializeAt(MachineBasicBlock &MBB,
   Rematted.insert(RM.ParentVNI);
   ++NumReMaterialization;
 
+  bool EarlyClobber = MI->getOperand(0).isEarlyClobber();
   if (ReplaceIndexMI)
-    return LIS.ReplaceMachineInstrInMaps(*ReplaceIndexMI, *MI).getRegSlot();
-  return LIS.getSlotIndexes()->insertMachineInstrInMaps(*MI, Late).getRegSlot();
+    return LIS.ReplaceMachineInstrInMaps(*ReplaceIndexMI, *MI)
+        .getRegSlot(EarlyClobber);
+  return LIS.getSlotIndexes()->insertMachineInstrInMaps(*MI, Late).getRegSlot(
+      EarlyClobber);
 }
 
 void LiveRangeEdit::eraseVirtReg(Register Reg) {

diff  --git a/llvm/test/CodeGen/X86/early-clobber.mir b/llvm/test/CodeGen/X86/early-clobber.mir
new file mode 100644
index 0000000000000..429331524d177
--- /dev/null
+++ b/llvm/test/CodeGen/X86/early-clobber.mir
@@ -0,0 +1,76 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=i386-unknown-linux-gnu -start-before=twoaddressinstruction -stop-after=postrapseudos -verify-machineinstrs -o - %s | FileCheck %s
+
+# Test register live range that is split from rematerializing. The live range should
+# start with Slot_EarlyClobber instead of Slot_Register. Machineverifer can check it.
+
+--- |
+
+  define void @test() nounwind {
+    ret void
+  }
+
+...
+---
+name:            test
+alignment:       16
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    4
+fixedStack:
+  - { id: 0, size: 4, alignment: 16, isImmutable: true }
+machineFunctionInfo: {}
+body:             |
+  ; CHECK-LABEL: name: test
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $ebp, $ebx, $edi, $esi
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   frame-setup PUSH32r killed $ebp, implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   frame-setup PUSH32r killed $ebx, implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   frame-setup PUSH32r killed $edi, implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   frame-setup PUSH32r killed $esi, implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   $esp = frame-setup SUB32ri $esp, 12, implicit-def dead $eflags
+  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $ebp, 12 /* clobber */, implicit-def dead early-clobber $eax, 12 /* clobber */, implicit-def dead early-clobber $ebx, 12 /* clobber */, implicit-def dead early-clobber $ecx, 12 /* clobber */, implicit-def dead early-clobber $edx, 12 /* clobber */, implicit-def dead early-clobber $esi, 12 /* clobber */, implicit-def dead early-clobber $edi, 12 /* clobber */, implicit-def dead early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def dead early-clobber $eflags
+  ; CHECK-NEXT:   early-clobber renamable $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags
+  ; CHECK-NEXT:   TEST8rr renamable $al, renamable $al, implicit-def $eflags
+  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit $eflags
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   renamable $eax = MOV32ri 1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   liveins: $eax
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $esp = frame-destroy ADD32ri $esp, 12, implicit-def dead $eflags
+  ; CHECK-NEXT:   $esi = frame-destroy POP32r implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   $edi = frame-destroy POP32r implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   $ebx = frame-destroy POP32r implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   $ebp = frame-destroy POP32r implicit-def $esp, implicit $esp
+  ; CHECK-NEXT:   RET 0, $eax
+  bb.0:
+    successors: %bb.1, %bb.2
+
+    early-clobber %0:gr32_abcd = MOV32r0 implicit-def dead $eflags
+    INLINEASM &"", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $ebp, 12 /* clobber */, implicit-def dead early-clobber $eax, 12 /* clobber */, implicit-def dead early-clobber $ebx, 12 /* clobber */, implicit-def dead early-clobber $ecx, 12 /* clobber */, implicit-def dead early-clobber $edx, 12 /* clobber */, implicit-def dead early-clobber $esi, 12 /* clobber */, implicit-def dead early-clobber $edi, 12 /* clobber */, implicit-def dead early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def dead early-clobber $eflags
+    %4:gr8 = COPY %0.sub_8bit
+    TEST8rr killed %4, %4, implicit-def $eflags
+    JCC_1 %bb.2, 5, implicit killed $eflags
+    JMP_1 %bb.1
+
+  bb.1:
+    %1:gr32 = MOV32ri 1
+    %5:gr32 = COPY killed %1
+    JMP_1 %bb.3
+
+  bb.2:
+    %5:gr32 = COPY killed %0
+
+  bb.3:
+    %3:gr32 = COPY killed %5
+    $eax = COPY killed %3
+    RET 0, killed $eax
+
+...


        


More information about the llvm-commits mailing list