[llvm-branch-commits] [llvm] PPC: Fix extsw elimination when the input reads a subregister (PR #208052)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Sep 20 02:14:05 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/208052
>From 32e27201f4ef6ab67659a5751b2314c6e6b45603 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 7 Jul 2026 17:04:45 +0200
Subject: [PATCH 1/3] PPC: Fix extsw elimination when the input reads a
subregister
The EXTSW_32_64 sign-extend elimination previously assumed its input
was a full register value. It would then try using that value as the
source of the new (unnecessary) INSERT_SUBREG.
The new test would then hit this verifier error:
```
bb.0:
liveins: $x3
%0:g8rc = COPY killed $x3
%1:g8rc = RLDICL killed %0:g8rc, 0, 33
%3:g8rc = IMPLICIT_DEF
%2:g8rc = INSERT_SUBREG %3:g8rc(tied-def 0), %1:g8rc, %subreg.sub_32
$x3 = COPY killed %2:g8rc
BLR8 implicit $lr8, implicit $rm, implicit killed $x3
*** Bad machine code: INSERT_SUBREG expected inserted value to have equal or lesser size than the subreg it was inserted into ***
- function: extsw_elim_subreg_input
- basic block: %bb.0 (0x13c834070)
- instruction: %2:g8rc = INSERT_SUBREG %3:g8rc(tied-def 0), %1:g8rc, %subreg.sub_32
```
This avoids verifier error regressions in a future change.
Co-Authored-By: Claude <noreply at anthropic.com> (Claude Opus 4.8, claude-opus-4-8)
---
llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 39 +++++++++++++------
.../peephole-elim-extsw-subreg-input.mir | 30 ++++++++++++++
2 files changed, 57 insertions(+), 12 deletions(-)
create mode 100644 llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir
diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index 71a7994750c56..ea56e71eb789a 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -1016,11 +1016,14 @@ bool PPCMIPeephole::simplifyCode() {
if (!NarrowReg.isVirtual())
break;
+ unsigned NarrowSubReg = MI.getOperand(1).getSubReg();
+
MachineInstr *SrcMI = MRI->getVRegDef(NarrowReg);
unsigned SrcOpcode = SrcMI->getOpcode();
// If we've used a zero-extending load that we will sign-extend,
// just do a sign-extending load.
- if (SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX) {
+ if (!NarrowSubReg &&
+ (SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX)) {
if (!MRI->hasOneNonDBGUse(SrcMI->getOperand(0).getReg()))
break;
@@ -1088,18 +1091,30 @@ bool PPCMIPeephole::simplifyCode() {
// chain used to deduce sign extension to eliminate the 'extsw' will
// need to be promoted to 64-bit pseudo instructions when the 'extsw'
// is eliminated.
- TII->promoteInstr32To64ForElimEXTSW(NarrowReg, MRI, 0, LV);
-
LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n");
- Register TmpReg =
- MF->getRegInfo().createVirtualRegister(&PPC::G8RCRegClass);
- BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::IMPLICIT_DEF),
- TmpReg);
- BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::INSERT_SUBREG),
- MI.getOperand(0).getReg())
- .addReg(TmpReg)
- .addReg(NarrowReg)
- .addImm(PPC::sub_32);
+
+ if (NarrowSubReg) {
+ // The input reads a subregister of a wider register which we can
+ // use directly.
+ assert(NarrowSubReg == PPC::sub_32 &&
+ "EXTSW_32_64 input must read the sub_32 subregister");
+ BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
+ MI.getOperand(0).getReg())
+ .addReg(NarrowReg);
+ addRegToUpdate(NarrowReg);
+ } else {
+ TII->promoteInstr32To64ForElimEXTSW(NarrowReg, MRI, 0, LV);
+
+ Register TmpReg =
+ MF->getRegInfo().createVirtualRegister(&PPC::G8RCRegClass);
+ BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::IMPLICIT_DEF),
+ TmpReg);
+ BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::INSERT_SUBREG),
+ MI.getOperand(0).getReg())
+ .addReg(TmpReg)
+ .addReg(NarrowReg)
+ .addImm(PPC::sub_32);
+ }
ToErase = &MI;
Simplified = true;
NumEliminatedSExt++;
diff --git a/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir b/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir
new file mode 100644
index 0000000000000..86caff368f3f2
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir
@@ -0,0 +1,30 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -run-pass=ppc-mi-peepholes -ppc-eliminate-signext -verify-machineinstrs -o - %s | FileCheck %s
+
+# When the EXTSW_32_64 input reads the sub_32 subregister of a 64-bit register
+# that is already sign-extended (here RLDICL with MB >= 33), the high 32 bits of
+# that register already hold the sign extension of the low word, so the result
+# of the sign-extend is the whole 64-bit register. Eliminate the EXTSW by
+# copying that register directly rather than building an INSERT_SUBREG that would
+# use the full register where a 32-bit register is required.
+
+---
+name: extsw_elim_subreg_input
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x3
+ ; CHECK-LABEL: name: extsw_elim_subreg_input
+ ; CHECK: liveins: $x3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:g8rc = COPY killed $x3
+ ; CHECK-NEXT: [[RLDICL:%[0-9]+]]:g8rc = RLDICL killed [[COPY]], 0, 33
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:g8rc = COPY killed [[RLDICL]]
+ ; CHECK-NEXT: $x3 = COPY killed [[COPY1]]
+ ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ %0:g8rc = COPY $x3
+ %1:g8rc = RLDICL %0, 0, 33
+ %2:g8rc = EXTSW_32_64 %1.sub_32
+ $x3 = COPY %2
+ BLR8 implicit $lr8, implicit $rm, implicit $x3
+...
>From 01992e6ce932b769f42fe9077ed56a39f5706a9b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 21 Jul 2026 20:03:15 +0200
Subject: [PATCH 2/3] Remove NarrowSubReg check
---
llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index ea56e71eb789a..5372cf8044d56 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -1022,8 +1022,7 @@ bool PPCMIPeephole::simplifyCode() {
unsigned SrcOpcode = SrcMI->getOpcode();
// If we've used a zero-extending load that we will sign-extend,
// just do a sign-extending load.
- if (!NarrowSubReg &&
- (SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX)) {
+ if ((SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX)) {
if (!MRI->hasOneNonDBGUse(SrcMI->getOperand(0).getReg()))
break;
>From 3ec282d981362bca39e57f20e500faace7be7751 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 20 Sep 2026 10:57:45 +0200
Subject: [PATCH 3/3] review comments
---
llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index 5372cf8044d56..a7c627915a7ca 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -1016,13 +1016,11 @@ bool PPCMIPeephole::simplifyCode() {
if (!NarrowReg.isVirtual())
break;
- unsigned NarrowSubReg = MI.getOperand(1).getSubReg();
-
MachineInstr *SrcMI = MRI->getVRegDef(NarrowReg);
unsigned SrcOpcode = SrcMI->getOpcode();
// If we've used a zero-extending load that we will sign-extend,
// just do a sign-extending load.
- if ((SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX)) {
+ if (SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX) {
if (!MRI->hasOneNonDBGUse(SrcMI->getOperand(0).getReg()))
break;
@@ -1092,9 +1090,10 @@ bool PPCMIPeephole::simplifyCode() {
// is eliminated.
LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n");
+ unsigned NarrowSubReg = MI.getOperand(1).getSubReg();
if (NarrowSubReg) {
// The input reads a subregister of a wider register which we can
- // use directly.
+ // use directly by dropping the subreg.
assert(NarrowSubReg == PPC::sub_32 &&
"EXTSW_32_64 input must read the sub_32 subregister");
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY),
More information about the llvm-branch-commits
mailing list