[llvm] [PowerPC] FIX llc crashed at -O1/O2/O3: Assertion `isImm() && "Wrong MachineOperand mutator"' failed. (PR #170548)

zhijian lin via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 3 11:59:40 PST 2025


https://github.com/diggerlin created https://github.com/llvm/llvm-project/pull/170548

Fixed issue 
[[PowerPC] llc crashed at -O1/O2/O3: Assertion `isImm() && "Wrong MachineOperand mutator"' failed.](https://github.com/llvm/llvm-project/issues/167672)

the root cause of the crash, the IMM operand is different operand num in the instruction 

>From ed0258ea043a249cb123aab6f9cbee1c73e29859 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Wed, 26 Nov 2025 20:49:52 +0000
Subject: [PATCH] fix a bug of splat-after-xxsldwi

---
 llvm/lib/Target/PowerPC/PPCMIPeephole.cpp     | 34 ++++++++++++++++---
 .../CodeGen/PowerPC/splat-after-xxsldwi.ll    | 22 ++++++++++++
 2 files changed, 52 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/splat-after-xxsldwi.ll

diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index 18350650bfe2d..a45d1f3a72d7e 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -797,7 +797,12 @@ bool PPCMIPeephole::simplifyCode() {
       case PPC::VSPLTH:
       case PPC::XXSPLTW: {
         unsigned MyOpcode = MI.getOpcode();
+
+        // The operand number of the source register in the splat instruction.
         unsigned OpNo = MyOpcode == PPC::XXSPLTW ? 1 : 2;
+
+        // The operand number of the splat Imm in the instruction.
+        unsigned SplatImmNo = MyOpcode == PPC::XXSPLTW ? 2 : 1;
         Register TrueReg =
           TRI->lookThruCopyLike(MI.getOperand(OpNo).getReg(), MRI);
         if (!TrueReg.isVirtual())
@@ -837,15 +842,36 @@ bool PPCMIPeephole::simplifyCode() {
         }
         // Splat fed by a shift. Usually when we align value to splat into
         // vector element zero.
+
         if (DefOpcode == PPC::XXSLDWI) {
           Register ShiftRes = DefMI->getOperand(0).getReg();
           Register ShiftOp1 = DefMI->getOperand(1).getReg();
           Register ShiftOp2 = DefMI->getOperand(2).getReg();
           unsigned ShiftImm = DefMI->getOperand(3).getImm();
-          unsigned SplatImm =
-              MI.getOperand(MyOpcode == PPC::XXSPLTW ? 2 : 1).getImm();
+          unsigned SplatImm = MI.getOperand(SplatImmNo).getImm();
+
           if (ShiftOp1 == ShiftOp2) {
-            unsigned NewElem = (SplatImm + ShiftImm) & 0x3;
+            // Calculate the new splat-element immediate. We need to convert the
+            // element index into the proper unit (byte for VSPLTB, halfword for
+            // VSPLTH, word for VSPLTW) because PPC::XXSLDWI interprets its
+            // ShiftImm in 32-bit word units.
+            unsigned NewElem = 0;
+            if (MyOpcode == PPC::VSPLTB)
+              NewElem = (SplatImm + ShiftImm * 4) & 0xF;
+            else if (MyOpcode == PPC::VSPLTH)
+              NewElem = (SplatImm + ShiftImm * 2) & 0x7;
+            else
+              NewElem = (SplatImm + ShiftImm) & 0x3;
+
+            // For example, We can erase XXSLDWI from in following:
+            //    %2:vrrc = XXSLDWI killed %1:vrrc, %1:vrrc, 1
+            //    %6:vrrc = VSPLTB 15, killed %2:vrrc
+            //    %7:vsrc = XXLAND killed %6:vrrc, killed %1:vrrc
+            //
+            // --->
+            //
+            //     %6:vrrc = VSPLTB 3, killed %1:vrrc
+            //     %7:vsrc = XXLAND killed %6:vrrc, killed %1:vrrc
             if (MRI->hasOneNonDBGUse(ShiftRes)) {
               LLVM_DEBUG(dbgs() << "Removing redundant shift: ");
               LLVM_DEBUG(DefMI->dump());
@@ -858,7 +884,7 @@ bool PPCMIPeephole::simplifyCode() {
             addRegToUpdate(MI.getOperand(OpNo).getReg());
             addRegToUpdate(ShiftOp1);
             MI.getOperand(OpNo).setReg(ShiftOp1);
-            MI.getOperand(2).setImm(NewElem);
+            MI.getOperand(SplatImmNo).setImm(NewElem);
           }
         }
         break;
diff --git a/llvm/test/CodeGen/PowerPC/splat-after-xxsldwi.ll b/llvm/test/CodeGen/PowerPC/splat-after-xxsldwi.ll
new file mode 100644
index 0000000000000..d0e96e3fbbf56
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/splat-after-xxsldwi.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names -mtriple=powerpc64-ibm-aix < %s  | \
+; RUN:   FileCheck %s
+
+
+define <4 x i8> @backsmith_pure_1(<8 x i32> %0) {
+; CHECK-LABEL: backsmith_pure_1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    ld r3, L..C0(r2) # %const.0
+; CHECK-NEXT:    xxsldwi vs34, vs35, vs35, 1
+; CHECK-NEXT:    lxvw4x vs36, 0, r3
+; CHECK-NEXT:    vspltb v3, v3, 3
+; CHECK-NEXT:    vperm v2, v2, v2, v4
+; CHECK-NEXT:    xxland vs34, vs35, vs34
+; CHECK-NEXT:    blr
+entry:
+  %shuffle = shufflevector <8 x i32> %0, <8 x i32> zeroinitializer, <4 x i32> <i32 5, i32 6, i32 7, i32 4>
+  %conv4 = trunc <4 x i32> %shuffle to <4 x i8>
+  %shift = shufflevector <4 x i8> %conv4, <4 x i8> zeroinitializer, <4 x i32> <i32 3, i32 poison, i32 poison, i32 poison>
+  %foldExtExtBinop = and <4 x i8> %shift, %conv4
+  ret <4 x i8> %foldExtExtBinop
+}



More information about the llvm-commits mailing list