Skip to content

Conversation

@LuoYuanke
Copy link
Contributor

@LuoYuanke LuoYuanke commented Aug 10, 2025

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

@LuoYuanke LuoYuanke changed the title [RA] Fix the live range for early-clobber [RegAlloc] Fix the live range for early-clobber Aug 17, 2025
@LuoYuanke LuoYuanke changed the title [RegAlloc] Fix the live range for early-clobber [RegAlloc] Fix register's live range for early-clobber Aug 17, 2025
@LuoYuanke LuoYuanke marked this pull request as ready for review August 17, 2025 08:18
@llvmbot
Copy link
Member

llvmbot commented Aug 17, 2025

@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-llvm-regalloc

Author: Luo, Yuanke (LuoYuanke)

Changes

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


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/LiveRangeEdit.cpp (+5-2)
  • (added) llvm/test/CodeGen/X86/early-clobber.mir (+75)
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
+
+...

Copy link
Contributor

@phoebewang phoebewang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Yuanke Luo added 4 commits August 19, 2025 08:48
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
@LuoYuanke
Copy link
Contributor Author

All the comments have been addressed. If there is no new comment, I'd like to land the patch.

Copy link
Contributor

@KanRobert KanRobert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@phoebewang phoebewang merged commit ba6bb69 into llvm:main Aug 20, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants