[llvm] [RegAlloc] Trace through COPYs to find rematerializable definitions (PR #190955)

Romanov Vlad via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 08:05:35 PDT 2026


https://github.com/romanovvlad updated https://github.com/llvm/llvm-project/pull/190955

>From 05021378c811615d04c33752e35649af62ea376b Mon Sep 17 00:00:00 2001
From: Vlad <Vladislav.Romanov at amd.com>
Date: Tue, 7 Apr 2026 09:20:17 -0500
Subject: [PATCH 1/2] [RegAlloc] Trace through COPYs to find rematerializable
 definitions

After live range splitting, successful rematerialization in one split
interval can remove the original defining instruction, leaving only
COPY instructions in other split intervals. When attempting to
rematerialize uses in those intervals, the code fails to find the
original definition and gives up.

This patch traces backwards through COPY chains to recover the original
rematerializable definition instead of giving up.
---
 llvm/lib/CodeGen/InlineSpiller.cpp            | 34 +++++++-
 .../CodeGen/AMDGPU/remat-through-copy.mir     | 82 +++++++++++++++++++
 llvm/test/CodeGen/RISCV/rvv/remat.ll          | 38 ++-------
 llvm/test/CodeGen/X86/pr38539.ll              | 29 ++++---
 4 files changed, 136 insertions(+), 47 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/remat-through-copy.mir

diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp
index 668c7c0a78098..ca086f21566a0 100644
--- a/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -680,10 +680,36 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, MachineInstr &MI) {
   // live interval; this happens if we rematted to all uses, and
   // then further split one of those live ranges.
   if (!DefMI) {
-    markValueUsed(&VirtReg, ParentVNI);
-    LLVM_DEBUG(dbgs() << "\tcannot remat missing def for " << UseIdx << '\t'
-                      << MI);
-    return false;
+    // Try to find the rematerializable definition by tracing through COPY
+    // chains.
+    MachineInstr *CurDef = MRI.getUniqueVRegDef(VirtReg.reg());
+    LLVM_DEBUG(dbgs() << "\ttracing COPY chain from "
+                      << printReg(VirtReg.reg(), &TRI) << ", initial def: "
+                      << (CurDef ? TII.getName(CurDef->getOpcode()) : "null")
+                      << "\n");
+    while (CurDef && CurDef->isCopy() && !CurDef->getOperand(0).getSubReg() &&
+           !CurDef->getOperand(1).getSubReg()) {
+      Register SrcReg = CurDef->getOperand(1).getReg();
+      if (!SrcReg.isVirtual())
+        break;
+      LLVM_DEBUG(dbgs() << "\t -> tracing through COPY to "
+                        << printReg(SrcReg, &TRI) << "\n");
+      CurDef = MRI.getUniqueVRegDef(SrcReg);
+      LLVM_DEBUG(dbgs() << "\t -> def: "
+                        << (CurDef ? TII.getName(CurDef->getOpcode()) : "null")
+                        << "\n");
+    }
+    if (CurDef && TII.isReMaterializable(*CurDef)) {
+      DefMI = CurDef;
+      LLVM_DEBUG(dbgs() << "\tFound remat possibility through COPY chain: "
+                        << *DefMI);
+    }
+    if (!DefMI) {
+      markValueUsed(&VirtReg, ParentVNI);
+      LLVM_DEBUG(dbgs() << "\tcannot remat missing def for " << UseIdx << '\t'
+                        << MI);
+      return false;
+    }
   }
 
   LiveRangeEdit::Remat RM(ParentVNI);
diff --git a/llvm/test/CodeGen/AMDGPU/remat-through-copy.mir b/llvm/test/CodeGen/AMDGPU/remat-through-copy.mir
new file mode 100644
index 0000000000000..44cedf20640d6
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/remat-through-copy.mir
@@ -0,0 +1,82 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgcn -mcpu=gfx900 --stress-regalloc=3 -run-pass=greedy,virtregrewriter -o - %s | FileCheck %s
+
+# Test that remat is successful when there are artificial COPY instructions due to live ranges splitting
+
+---
+name: test_remat_s_add_i32
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: test_remat_s_add_i32
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT:   liveins: $sgpr0, $sgpr1, $vgpr0, $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   renamable $vgpr2 = V_OR_B32_e32 $vgpr0, $vgpr1, implicit $exec
+  ; CHECK-NEXT:   renamable $vgpr0 = V_XOR_B32_e32 killed $vgpr0, killed $vgpr1, implicit $exec
+  ; CHECK-NEXT:   renamable $sgpr2 = S_MOV_B32 0
+  ; CHECK-NEXT:   S_BRANCH %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $sgpr2, $vgpr0, $vgpr2, $sgpr0_sgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr4_sgpr5 = V_CMP_EQ_U32_e64 $vgpr0, $vgpr2, implicit $exec
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $sgpr4_sgpr5, implicit renamable $sgpr0_sgpr1
+  ; CHECK-NEXT:   renamable $sgpr2 = S_ADD_U32 killed renamable $sgpr2, 1, implicit-def $scc
+  ; CHECK-NEXT:   S_CMP_LT_U32 renamable $sgpr2, 10, implicit-def $scc
+  ; CHECK-NEXT:   S_CBRANCH_SCC1 %bb.1, implicit $scc
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   liveins: $vgpr0, $vgpr2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_NOP 0, implicit killed renamable $vgpr2, implicit killed renamable $vgpr0
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    liveins: $vgpr0, $vgpr1, $sgpr0, $sgpr1
+
+    %in1:vgpr_32 = COPY $vgpr0
+    %in2:vgpr_32 = COPY $vgpr1
+    %vec0:vgpr_32 = V_OR_B32_e32 %in1, %in2, implicit $exec
+    %vec1:vgpr_32 = V_XOR_B32_e32 %in1, %in2, implicit $exec
+    %17:sgpr_64 = COPY $sgpr0_sgpr1
+
+    %new_var:sreg_64 = V_CMP_EQ_U32_e64 %vec1:vgpr_32, %vec0:vgpr_32, implicit $exec
+    %new_var2:sreg_64 = V_CMP_EQ_U32_e64 %vec1:vgpr_32, %vec0:vgpr_32, implicit $exec
+
+    %i:sgpr_32 = S_MOV_B32 0
+    S_BRANCH %bb.1
+
+  bb.1:
+
+    S_NOP 0, implicit %new_var, implicit %17
+
+    S_NOP 0, implicit %new_var2, implicit %17
+
+    S_NOP 0, implicit %new_var, implicit %17
+
+    S_NOP 0, implicit %new_var2, implicit %17
+
+    S_NOP 0, implicit %new_var, implicit %17
+
+    S_NOP 0, implicit %new_var2, implicit %17
+
+    %i:sgpr_32 = S_ADD_U32 %i:sgpr_32, 1, implicit-def $scc
+    S_CMP_LT_U32 %i:sgpr_32, 10, implicit-def $scc
+    S_CBRANCH_SCC1 %bb.1, implicit $scc
+
+  bb.2:
+    S_NOP 0, implicit %vec0, implicit %vec1
+    S_ENDPGM 0
+...
+
diff --git a/llvm/test/CodeGen/RISCV/rvv/remat.ll b/llvm/test/CodeGen/RISCV/rvv/remat.ll
index 57f1977c27b82..430db5b1290fb 100644
--- a/llvm/test/CodeGen/RISCV/rvv/remat.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/remat.ll
@@ -314,13 +314,10 @@ define i64 @dual_remat(i64 %0, <vscale x 16 x i64> %1, <vscale x 16 x i64> %2, p
 ; CHECK-NEXT:    addi sp, sp, -16
 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
 ; CHECK-NEXT:    csrr a1, vlenb
-; CHECK-NEXT:    mv a2, a1
-; CHECK-NEXT:    slli a1, a1, 3
-; CHECK-NEXT:    add a2, a2, a1
-; CHECK-NEXT:    slli a1, a1, 1
-; CHECK-NEXT:    add a1, a1, a2
+; CHECK-NEXT:    slli a2, a1, 4
+; CHECK-NEXT:    add a1, a2, a1
 ; CHECK-NEXT:    sub sp, sp, a1
-; CHECK-NEXT:    .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x19, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 25 * vlenb
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x11, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 17 * vlenb
 ; CHECK-NEXT:    csrr a1, vlenb
 ; CHECK-NEXT:    slli a1, a1, 3
 ; CHECK-NEXT:    add a1, sp, a1
@@ -338,12 +335,6 @@ define i64 @dual_remat(i64 %0, <vscale x 16 x i64> %1, <vscale x 16 x i64> %2, p
 ; CHECK-NEXT:  .LBB8_1: # %vector.body
 ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    vmv.v.x v8, a0
-; CHECK-NEXT:    csrr a4, vlenb
-; CHECK-NEXT:    slli a5, a4, 4
-; CHECK-NEXT:    add a4, a5, a4
-; CHECK-NEXT:    add a4, sp, a4
-; CHECK-NEXT:    addi a4, a4, 16
-; CHECK-NEXT:    vs8r.v v8, (a4) # vscale x 64-byte Folded Spill
 ; CHECK-NEXT:    vand.vv v16, v0, v8
 ; CHECK-NEXT:    vmv8r.v v8, v24
 ; CHECK-NEXT:    vmsne.vi v24, v16, 0
@@ -353,12 +344,7 @@ define i64 @dual_remat(i64 %0, <vscale x 16 x i64> %1, <vscale x 16 x i64> %2, p
 ; CHECK-NEXT:    addi a4, a4, 16
 ; CHECK-NEXT:    vs1r.v v24, (a4) # vscale x 8-byte Folded Spill
 ; CHECK-NEXT:    vmv8r.v v24, v8
-; CHECK-NEXT:    csrr a4, vlenb
-; CHECK-NEXT:    slli a5, a4, 4
-; CHECK-NEXT:    add a4, a5, a4
-; CHECK-NEXT:    add a4, sp, a4
-; CHECK-NEXT:    addi a4, a4, 16
-; CHECK-NEXT:    vl8r.v v8, (a4) # vscale x 64-byte Folded Reload
+; CHECK-NEXT:    vmv.v.x v8, a0
 ; CHECK-NEXT:    vand.vv v16, v24, v8
 ; CHECK-NEXT:    vmsne.vi v8, v16, 0
 ; CHECK-NEXT:    csrr a4, vlenb
@@ -370,17 +356,12 @@ define i64 @dual_remat(i64 %0, <vscale x 16 x i64> %1, <vscale x 16 x i64> %2, p
 ; CHECK-NEXT:    vslideup.vx v9, v8, a1
 ; CHECK-NEXT:    vsetvli a4, zero, e8, m2, ta, ma
 ; CHECK-NEXT:    vcpop.m a4, v9
-; CHECK-NEXT:    csrr a5, vlenb
-; CHECK-NEXT:    slli a6, a5, 4
-; CHECK-NEXT:    add a5, a6, a5
-; CHECK-NEXT:    add a5, sp, a5
-; CHECK-NEXT:    addi a5, a5, 16
-; CHECK-NEXT:    vl8r.v v8, (a5) # vscale x 64-byte Folded Reload
+; CHECK-NEXT:    vsetvli a5, zero, e64, m8, ta, ma
+; CHECK-NEXT:    vmv.v.x v8, a0
 ; CHECK-NEXT:    vs8r.v v8, (a3)
 ; CHECK-NEXT:    vs8r.v v8, (a2)
 ; CHECK-NEXT:    addi a5, sp, 16
 ; CHECK-NEXT:    vl8r.v v8, (a5) # vscale x 64-byte Folded Reload
-; CHECK-NEXT:    vsetvli a5, zero, e64, m8, ta, ma
 ; CHECK-NEXT:    vor.vv v0, v0, v8
 ; CHECK-NEXT:    csrr a5, vlenb
 ; CHECK-NEXT:    slli a5, a5, 3
@@ -392,11 +373,8 @@ define i64 @dual_remat(i64 %0, <vscale x 16 x i64> %1, <vscale x 16 x i64> %2, p
 ; CHECK-NEXT:  # %bb.2: # %middle.block
 ; CHECK-NEXT:    andi a0, a0, 1
 ; CHECK-NEXT:    csrr a1, vlenb
-; CHECK-NEXT:    mv a2, a1
-; CHECK-NEXT:    slli a1, a1, 3
-; CHECK-NEXT:    add a2, a2, a1
-; CHECK-NEXT:    slli a1, a1, 1
-; CHECK-NEXT:    add a1, a1, a2
+; CHECK-NEXT:    slli a2, a1, 4
+; CHECK-NEXT:    add a1, a2, a1
 ; CHECK-NEXT:    add sp, sp, a1
 ; CHECK-NEXT:    .cfi_def_cfa sp, 16
 ; CHECK-NEXT:    addi sp, sp, 16
diff --git a/llvm/test/CodeGen/X86/pr38539.ll b/llvm/test/CodeGen/X86/pr38539.ll
index eecd15dd2afe9..3f1c0d58b542f 100644
--- a/llvm/test/CodeGen/X86/pr38539.ll
+++ b/llvm/test/CodeGen/X86/pr38539.ll
@@ -22,7 +22,7 @@ define void @f() nounwind {
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
 ; X86-NEXT:    andl $-16, %esp
-; X86-NEXT:    subl $176, %esp
+; X86-NEXT:    subl $160, %esp
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
@@ -128,9 +128,9 @@ define void @f() nounwind {
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl 128(%esp,%edx), %eax
-; X86-NEXT:    movl 132(%esp,%edx), %edi
-; X86-NEXT:    movl 136(%esp,%edx), %edx
+; X86-NEXT:    movl 112(%esp,%edx), %eax
+; X86-NEXT:    movl 116(%esp,%edx), %edi
+; X86-NEXT:    movl 120(%esp,%edx), %edx
 ; X86-NEXT:    shldl %cl, %edi, %edx
 ; X86-NEXT:    movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    shldl %cl, %eax, %edi
@@ -159,15 +159,14 @@ define void @f() nounwind {
 ; X86-NEXT:    shrb $3, %al
 ; X86-NEXT:    andb $12, %al
 ; X86-NEXT:    movzbl %al, %eax
-; X86-NEXT:    movl 88(%esp,%eax), %edi
-; X86-NEXT:    movl 80(%esp,%eax), %ebx
-; X86-NEXT:    movl 84(%esp,%eax), %eax
+; X86-NEXT:    movl 72(%esp,%eax), %edi
+; X86-NEXT:    movl 64(%esp,%eax), %ebx
+; X86-NEXT:    movl 68(%esp,%eax), %eax
 ; X86-NEXT:    movl %eax, %edx
 ; X86-NEXT:    shrdl %cl, %edi, %edx
 ; X86-NEXT:    movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
 ; X86-NEXT:    shrdl %cl, %eax, %ebx
-; X86-NEXT:    movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
 ; X86-NEXT:    addl $-1, %eax
 ; X86-NEXT:    movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
@@ -183,9 +182,10 @@ define void @f() nounwind {
 ; X86-NEXT:    .p2align 4
 ; X86-NEXT:  .LBB0_14: # %udiv-do-while
 ; X86-NEXT:    # =>This Inner Loop Header: Depth=1
-; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
-; X86-NEXT:    shldl $1, %edx, %ecx
-; X86-NEXT:    shldl $1, %ebx, %edx
+; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
+; X86-NEXT:    shldl $1, %eax, %ecx
+; X86-NEXT:    shldl $1, %ebx, %eax
+; X86-NEXT:    movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload
 ; X86-NEXT:    movl %edi, %esi
 ; X86-NEXT:    andl $2, %esi
@@ -193,10 +193,12 @@ define void @f() nounwind {
 ; X86-NEXT:    leal (%esi,%ebx,2), %ebx
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
 ; X86-NEXT:    shldl $1, %esi, %edi
-; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %eax, %edi
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
 ; X86-NEXT:    shldl $1, %eax, %esi
-; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    orl %edx, %esi
 ; X86-NEXT:    movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    addl %eax, %eax
 ; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload
@@ -205,6 +207,7 @@ define void @f() nounwind {
 ; X86-NEXT:    movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    cmpl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
+; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
 ; X86-NEXT:    sbbl %edx, %esi
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
 ; X86-NEXT:    sbbl %ecx, %esi

>From df3bc42cabd71bccf154f65fd14b2b15bdef552a Mon Sep 17 00:00:00 2001
From: Vlad <Vladislav.Romanov at amd.com>
Date: Tue, 14 Apr 2026 08:58:51 -0500
Subject: [PATCH 2/2] Use VNInfo

---
 llvm/lib/CodeGen/InlineSpiller.cpp | 29 +++++++++++++++++++----------
 llvm/test/CodeGen/X86/pr38539.ll   | 29 +++++++++++++----------------
 2 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp
index ca086f21566a0..f4750d5375e8a 100644
--- a/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -682,22 +682,31 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, MachineInstr &MI) {
   if (!DefMI) {
     // Try to find the rematerializable definition by tracing through COPY
     // chains.
-    MachineInstr *CurDef = MRI.getUniqueVRegDef(VirtReg.reg());
+    LiveInterval &LI = LIS.getInterval(VirtReg.reg());
+    VNInfo *CurVNI = LI.getVNInfoAt(UseIdx);
+    MachineInstr *CurDef = nullptr;
+
     LLVM_DEBUG(dbgs() << "\ttracing COPY chain from "
-                      << printReg(VirtReg.reg(), &TRI) << ", initial def: "
-                      << (CurDef ? TII.getName(CurDef->getOpcode()) : "null")
-                      << "\n");
-    while (CurDef && CurDef->isCopy() && !CurDef->getOperand(0).getSubReg() &&
-           !CurDef->getOperand(1).getSubReg()) {
+                      << printReg(VirtReg.reg(), &TRI) << "\n");
+
+    // Trace backwards through COPY chain using VNInfo
+    while (CurVNI) {
+      CurDef = LIS.getInstructionFromIndex(CurVNI->def);
+
+      LLVM_DEBUG(dbgs() << "\t -> def at " << CurVNI->def << ": "
+                        << (CurDef ? TII.getName(CurDef->getOpcode()) : "null")
+                        << "\n");
+
+      if (!CurDef || !CurDef->isFullCopy())
+        break;
+
       Register SrcReg = CurDef->getOperand(1).getReg();
       if (!SrcReg.isVirtual())
         break;
       LLVM_DEBUG(dbgs() << "\t -> tracing through COPY to "
                         << printReg(SrcReg, &TRI) << "\n");
-      CurDef = MRI.getUniqueVRegDef(SrcReg);
-      LLVM_DEBUG(dbgs() << "\t -> def: "
-                        << (CurDef ? TII.getName(CurDef->getOpcode()) : "null")
-                        << "\n");
+      LiveInterval &SrcLI = LIS.getInterval(SrcReg);
+      CurVNI = SrcLI.getVNInfoBefore(CurVNI->def);
     }
     if (CurDef && TII.isReMaterializable(*CurDef)) {
       DefMI = CurDef;
diff --git a/llvm/test/CodeGen/X86/pr38539.ll b/llvm/test/CodeGen/X86/pr38539.ll
index 3f1c0d58b542f..eecd15dd2afe9 100644
--- a/llvm/test/CodeGen/X86/pr38539.ll
+++ b/llvm/test/CodeGen/X86/pr38539.ll
@@ -22,7 +22,7 @@ define void @f() nounwind {
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
 ; X86-NEXT:    andl $-16, %esp
-; X86-NEXT:    subl $160, %esp
+; X86-NEXT:    subl $176, %esp
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
@@ -128,9 +128,9 @@ define void @f() nounwind {
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
 ; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl 112(%esp,%edx), %eax
-; X86-NEXT:    movl 116(%esp,%edx), %edi
-; X86-NEXT:    movl 120(%esp,%edx), %edx
+; X86-NEXT:    movl 128(%esp,%edx), %eax
+; X86-NEXT:    movl 132(%esp,%edx), %edi
+; X86-NEXT:    movl 136(%esp,%edx), %edx
 ; X86-NEXT:    shldl %cl, %edi, %edx
 ; X86-NEXT:    movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    shldl %cl, %eax, %edi
@@ -159,14 +159,15 @@ define void @f() nounwind {
 ; X86-NEXT:    shrb $3, %al
 ; X86-NEXT:    andb $12, %al
 ; X86-NEXT:    movzbl %al, %eax
-; X86-NEXT:    movl 72(%esp,%eax), %edi
-; X86-NEXT:    movl 64(%esp,%eax), %ebx
-; X86-NEXT:    movl 68(%esp,%eax), %eax
+; X86-NEXT:    movl 88(%esp,%eax), %edi
+; X86-NEXT:    movl 80(%esp,%eax), %ebx
+; X86-NEXT:    movl 84(%esp,%eax), %eax
 ; X86-NEXT:    movl %eax, %edx
 ; X86-NEXT:    shrdl %cl, %edi, %edx
 ; X86-NEXT:    movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
 ; X86-NEXT:    shrdl %cl, %eax, %ebx
+; X86-NEXT:    movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
 ; X86-NEXT:    addl $-1, %eax
 ; X86-NEXT:    movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
@@ -182,10 +183,9 @@ define void @f() nounwind {
 ; X86-NEXT:    .p2align 4
 ; X86-NEXT:  .LBB0_14: # %udiv-do-while
 ; X86-NEXT:    # =>This Inner Loop Header: Depth=1
-; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
-; X86-NEXT:    shldl $1, %eax, %ecx
-; X86-NEXT:    shldl $1, %ebx, %eax
-; X86-NEXT:    movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT:    shldl $1, %edx, %ecx
+; X86-NEXT:    shldl $1, %ebx, %edx
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload
 ; X86-NEXT:    movl %edi, %esi
 ; X86-NEXT:    andl $2, %esi
@@ -193,12 +193,10 @@ define void @f() nounwind {
 ; X86-NEXT:    leal (%esi,%ebx,2), %ebx
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
 ; X86-NEXT:    shldl $1, %esi, %edi
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %eax, %edi
+; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
 ; X86-NEXT:    shldl $1, %eax, %esi
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    orl %edx, %esi
+; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload
 ; X86-NEXT:    movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    addl %eax, %eax
 ; X86-NEXT:    orl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload
@@ -207,7 +205,6 @@ define void @f() nounwind {
 ; X86-NEXT:    movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
 ; X86-NEXT:    cmpl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
-; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
 ; X86-NEXT:    sbbl %edx, %esi
 ; X86-NEXT:    movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
 ; X86-NEXT:    sbbl %ecx, %esi



More information about the llvm-commits mailing list