[llvm] [RegAlloc] Fix the live range for early-clobber (PR #152895)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 17 01:14:30 PDT 2025


https://github.com/LuoYuanke updated https://github.com/llvm/llvm-project/pull/152895

>From 7baf18957d84d47479da1acf3997dc2cfb1272b8 Mon Sep 17 00:00:00 2001
From: Yuanke Luo <ykluo at birentech.com>
Date: Sun, 10 Aug 2025 10:40:51 +0800
Subject: [PATCH] [RegAlloc] Fix register's live range for early-clobber

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
---
 llvm/lib/CodeGen/LiveRangeEdit.cpp      |  7 ++-
 llvm/test/CodeGen/X86/early-clobber.mir | 75 +++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/early-clobber.mir

diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index a3858efbdc5e1..0bd9b0dad740d 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(EearlyClobber);
+  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..27c83d2a68c95
--- /dev/null
+++ b/llvm/test/CodeGen/X86/early-clobber.mir
@@ -0,0 +1,75 @@
+# RUN: llc -mtriple=i386-unknown-linux-gnu -start-before=twoaddressinstruction -verify-machineinstrs -o - %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.
+
+--- |
+  target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128"
+  target triple = "i386-unknown-linux-gnu"
+
+  @g = external constant [2 x i32], align 4
+
+  ; Function Attrs: nounwind
+  define i32 @test(i32 noundef %a) #0 {
+  entry:
+    %0 = xor i32 %a, %a
+    tail call void asm sideeffect "", "~{ebp},~{eax},~{ebx},~{ecx},~{edx},~{esi},~{edi},~{dirflag},~{fpsr},~{flags}"()
+    br i1 undef, label %if, label %else
+
+  if:                                               ; preds = %entry
+    %add = add i32 %0, 1
+    br label %exit
+
+  else:                                             ; preds = %entry
+    %shl = shl i32 %0, 1
+    br label %exit
+
+  exit:                                             ; preds = %else, %if
+    %phi = phi i32 [ %add, %if ], [ %shl, %else ]
+    ret i32 %phi
+  }
+
+  attributes #0 = { nounwind }
+
+...
+---
+name:            test
+alignment:       16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr32_abcd }
+  - { id: 1, class: gr32 }
+  - { id: 2, class: gr32 }
+  - { id: 3, class: gr32 }
+  - { id: 4, class: gr8 }
+  - { id: 5, class: gr32 }
+frameInfo:
+  maxAlignment:    4
+fixedStack:
+  - { id: 0, size: 4, alignment: 16, isImmutable: true }
+machineFunctionInfo: {}
+body:             |
+  bb.0.entry:
+    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.if:
+    %1:gr32 = MOV32ri 1
+    %5:gr32 = COPY killed %1
+    JMP_1 %bb.3
+
+  bb.2.else:
+    %5:gr32 = COPY killed %0
+
+  bb.3.exit:
+    %3:gr32 = COPY killed %5
+    $eax = COPY killed %3
+    RET 0, killed $eax
+
+...



More information about the llvm-commits mailing list