[llvm] TwoAddressInstructions: Move the rescheduled copy chain back to front (PR #227289)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 05:18:00 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/227289

rescheduleMIBelowKill sinks an instruction below the kill of its tied
source, along with the run of copies that follows it. With LiveIntervals
the copies are spliced one at a time so handleMove sees a well-formed
block, but they were visited front to back and each inserted before the
previously moved one. This reversed them, and transiently moved a copy
below its use, asserting in handleMoveDown.

Walk them back to front instead, which also preserves the original order.

Exposed by #225174, which made LiveIntervals available here by default.

Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>

>From 88a286909296371220d2028347dc41c9f848c6fd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 29 Sep 2026 14:06:51 +0200
Subject: [PATCH] TwoAddressInstructions: Move the rescheduled copy chain back
 to front

rescheduleMIBelowKill sinks an instruction below the kill of its tied
source, along with the run of copies that follows it. With LiveIntervals
the copies are spliced one at a time so handleMove sees a well-formed
block, but they were visited front to back and each inserted before the
previously moved one. This reversed them, and transiently moved a copy
below its use, asserting in handleMoveDown.

Walk them back to front instead, which also preserves the original order.

Exposed by #225174, which made LiveIntervals available here by default.

Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
---
 .../lib/CodeGen/TwoAddressInstructionPass.cpp |  5 +--
 .../X86/twoaddr-reschedule-copy-chain.mir     | 36 +++++++++++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/twoaddr-reschedule-copy-chain.mir

diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index 0d1ab23757f9f..9ec96c180a0c1 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -1065,8 +1065,9 @@ bool TwoAddressInstructionImpl::rescheduleMIBelowKill(
   if (LIS) {
     // We have to move the copies (and any interleaved debug instructions)
     // first so that the MBB is still well-formed when calling handleMove().
-    for (MachineBasicBlock::iterator MBBI = AfterMI; MBBI != End;) {
-      auto CopyMI = MBBI++;
+    // Move them back to front, so a copy never ends up above its source def.
+    for (MachineBasicBlock::iterator MIIt(MI); std::next(MIIt) != End;) {
+      MachineBasicBlock::iterator CopyMI = std::prev(End);
       MBB->splice(InsertPos, MBB, CopyMI);
       if (!CopyMI->isDebugOrPseudoInstr())
         LIS->handleMove(*CopyMI);
diff --git a/llvm/test/CodeGen/X86/twoaddr-reschedule-copy-chain.mir b/llvm/test/CodeGen/X86/twoaddr-reschedule-copy-chain.mir
new file mode 100644
index 0000000000000..df1e058770398
--- /dev/null
+++ b/llvm/test/CodeGen/X86/twoaddr-reschedule-copy-chain.mir
@@ -0,0 +1,36 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=i386-unknown-linux -mattr=+sse2 -run-pass=liveintervals,twoaddressinstruction -o - %s | FileCheck %s
+
+# Rescheduling %2 below its kill also moves the copies following
+# it. They have to move in reverse order, or %3 ends up below the copy
+# reading it.
+
+---
+name:            reschedule_copy_chain
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: reschedule_copy_chain
+    ; CHECK: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 1
+    ; CHECK-NEXT: [[MOV32ri1:%[0-9]+]]:gr32 = MOV32ri 2
+    ; CHECK-NEXT: [[MOVDI2PDIrr:%[0-9]+]]:vr128 = MOVDI2PDIrr [[MOV32ri]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY [[MOV32ri]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = SUB32rr [[COPY]], [[MOV32ri1]], implicit-def dead $eflags
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32_abcd = COPY [[COPY]]
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr8 = COPY [[COPY1]].sub_8bit
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vr128 = COPY [[MOVDI2PDIrr]]
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vr128 = PSRLDri [[COPY3]], 3
+    ; CHECK-NEXT: $al = COPY [[COPY2]]
+    ; CHECK-NEXT: $xmm0 = COPY [[COPY3]]
+    ; CHECK-NEXT: RET 0, implicit killed $al, implicit killed $xmm0
+    %0:gr32 = MOV32ri 1
+    %1:gr32 = MOV32ri 2
+    %2:gr32 = SUB32rr %0, %1, implicit-def dead $eflags
+    %3:gr32_abcd = COPY %2
+    %4:gr8 = COPY %3.sub_8bit
+    %5:vr128 = MOVDI2PDIrr %0
+    %6:vr128 = PSRLDri %5, 3
+    $al = COPY %4
+    $xmm0 = COPY %6
+    RET 0, implicit killed $al, implicit killed $xmm0
+...



More information about the llvm-commits mailing list