https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/211107
>From bfd1ec2846559898d850e9fb5605e5404832c57c Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Tue, 21 Jul 2026 19:35:27 +0200 Subject: [PATCH] PPC: Fold 64-bit zero-extending word load feeding extsw subregister A gprc LWZ/LWZX feeding EXTSW_32_64 is rewritten into a sign-extending LWA/LWAX load. Extend the same fold to the 64-bit zero-extending word loads LWZ8/LWZX8 when the EXTSW_32_64 reads their sub_32 subregister, producing a single LWA/LWAX instead of a redundant lwz+extsw pair. Co-authored-by: Claude (Claude Opus 4.8, claude-opus-4-8) <[email protected]> --- llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 14 ++++++-- .../peephole-elim-extsw-subreg-input.mir | 35 +++++++++---------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp index a7c627915a7ca..60c8e7c20d846 100644 --- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -1019,8 +1019,15 @@ bool PPCMIPeephole::simplifyCode() { 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) { + // just do a sign-extending load. The source may be a 32-bit gprc load + // consumed directly, or a 64-bit g8rc load consumed through its sub_32 + // subregister. + bool SrcIsGPRCWordZextLoad = + SrcOpcode == PPC::LWZ || SrcOpcode == PPC::LWZX; + bool SrcIsG8RCWordZextLoad = + SrcOpcode == PPC::LWZ8 || SrcOpcode == PPC::LWZX8; + if ((!NarrowSubReg && SrcIsGPRCWordZextLoad) || + (NarrowSubReg == PPC::sub_32 && SrcIsG8RCWordZextLoad)) { if (!MRI->hasOneNonDBGUse(SrcMI->getOperand(0).getReg())) break; @@ -1046,7 +1053,8 @@ bool PPCMIPeephole::simplifyCode() { // Likewise if the source is X-Form the new opcode should also be // X-Form. unsigned Opc = PPC::LWA_32; - bool SourceIsXForm = SrcOpcode == PPC::LWZX; + bool SourceIsXForm = + SrcOpcode == PPC::LWZX || SrcOpcode == PPC::LWZX8; bool MIIs64Bit = MI.getOpcode() == PPC::EXTSW || MI.getOpcode() == PPC::EXTSW_32_64; diff --git a/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir b/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir index 1c7d3c1f87ca7..e57864a196ce4 100644 --- a/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir +++ b/llvm/test/CodeGen/PowerPC/peephole-elim-extsw-subreg-input.mir @@ -26,10 +26,9 @@ body: | BLR8 implicit $lr8, implicit $rm, implicit $x3 ... -# FIXME: A 64-bit zero-extending word load (LWZ8/LWZX8) feeding an EXTSW that -# reads its sub_32 could fold into a sign-extending load, the same way a gprc -# LWZ/LWZX + EXTSW folds. The load-folding path only matches the 32-bit -# LWZ/LWZX defs, so these subregister cases are left as a separate load + extsw. +# A 64-bit zero-extending word load (LWZ8/LWZX8) feeding an EXTSW that reads its +# sub_32 is folded into a sign-extending load, the same way a gprc LWZ/LWZX + +# EXTSW folds. --- name: extsw_lwz8_subreg_input tracksRegLiveness: true @@ -40,9 +39,9 @@ body: | ; CHECK: liveins: $x3 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY killed $x3 - ; CHECK-NEXT: [[LWZ8_:%[0-9]+]]:g8rc = LWZ8 0, killed [[COPY]] :: (load (s32)) - ; CHECK-NEXT: [[EXTSW_32_64_:%[0-9]+]]:g8rc = EXTSW_32_64 killed [[LWZ8_]].sub_32 - ; CHECK-NEXT: $x3 = COPY killed [[EXTSW_32_64_]] + ; CHECK-NEXT: [[LWA:%[0-9]+]]:g8rc = LWA 0, killed [[COPY]] :: (load (s32)) + ; CHECK-NEXT: dead [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: $x3 = COPY killed [[LWA]] ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit killed $x3 %0:g8rc_and_g8rc_nox0 = COPY $x3 %1:g8rc = LWZ8 0, %0 :: (load (s32)) @@ -63,9 +62,9 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY killed $x3 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:g8rc = COPY killed $x4 - ; CHECK-NEXT: [[LWZX8_:%[0-9]+]]:g8rc = LWZX8 killed [[COPY]], killed [[COPY1]] :: (load (s32)) - ; CHECK-NEXT: [[EXTSW_32_64_:%[0-9]+]]:g8rc = EXTSW_32_64 killed [[LWZX8_]].sub_32 - ; CHECK-NEXT: $x3 = COPY killed [[EXTSW_32_64_]] + ; CHECK-NEXT: [[LWAX:%[0-9]+]]:g8rc = LWAX killed [[COPY]], killed [[COPY1]] :: (load (s32)) + ; CHECK-NEXT: dead [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: $x3 = COPY killed [[LWAX]] ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit killed $x3 %0:g8rc_and_g8rc_nox0 = COPY $x3 %3:g8rc = COPY $x4 @@ -86,10 +85,10 @@ body: | ; CHECK: liveins: $x3 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY killed $x3 - ; CHECK-NEXT: [[LWZ8_:%[0-9]+]]:g8rc = LWZ8 0, killed [[COPY]] :: (load (s32)) - ; CHECK-NEXT: [[EXTSW_32_:%[0-9]+]]:gprc = EXTSW_32 killed [[LWZ8_]].sub_32 - ; CHECK-NEXT: [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF - ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:g8rc = INSERT_SUBREG killed [[DEF]], killed [[EXTSW_32_]], %subreg.sub_32 + ; CHECK-NEXT: [[LWA_32_:%[0-9]+]]:gprc = LWA_32 0, killed [[COPY]] :: (load (s32)) + ; CHECK-NEXT: dead [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:g8rc = INSERT_SUBREG killed [[DEF1]], killed [[LWA_32_]], %subreg.sub_32 ; CHECK-NEXT: $x3 = COPY killed [[INSERT_SUBREG]] ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit killed $x3 %0:g8rc_and_g8rc_nox0 = COPY $x3 @@ -113,10 +112,10 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY killed $x3 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:g8rc = COPY killed $x4 - ; CHECK-NEXT: [[LWZX8_:%[0-9]+]]:g8rc = LWZX8 killed [[COPY]], killed [[COPY1]] :: (load (s32)) - ; CHECK-NEXT: [[EXTSW_32_:%[0-9]+]]:gprc = EXTSW_32 killed [[LWZX8_]].sub_32 - ; CHECK-NEXT: [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF - ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:g8rc = INSERT_SUBREG killed [[DEF]], killed [[EXTSW_32_]], %subreg.sub_32 + ; CHECK-NEXT: [[LWAX_32_:%[0-9]+]]:gprc = LWAX_32 killed [[COPY]], killed [[COPY1]] :: (load (s32)) + ; CHECK-NEXT: dead [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:g8rc = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:g8rc = INSERT_SUBREG killed [[DEF1]], killed [[LWAX_32_]], %subreg.sub_32 ; CHECK-NEXT: $x3 = COPY killed [[INSERT_SUBREG]] ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit killed $x3 %0:g8rc_and_g8rc_nox0 = COPY $x3 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
