[llvm] Fix [PowerPC] 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
Mon Dec 8 07:06:07 PST 2025
https://github.com/diggerlin updated https://github.com/llvm/llvm-project/pull/170548
>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 1/5] 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
+}
>From d6ddc518545ce36b88958738c5545d9db18470b3 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Fri, 5 Dec 2025 19:33:53 +0000
Subject: [PATCH 2/5] address comment
---
llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 43 +++++++++++++----------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index a45d1f3a72d7e..18f50a9af588a 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -797,12 +797,8 @@ 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())
@@ -828,6 +824,7 @@ bool PPCMIPeephole::simplifyCode() {
(MyOpcode == PPC::XXSPLTW && DefOpcode == PPC::LXVWSX) ||
(MyOpcode == PPC::XXSPLTW && DefOpcode == PPC::MTVSRWS)||
(MyOpcode == PPC::XXSPLTW && isConvertOfSplat());
+
// If the instruction[s] that feed this splat have already splat
// the value, this splat is redundant.
if (AlreadySplat) {
@@ -840,29 +837,15 @@ bool PPCMIPeephole::simplifyCode() {
ToErase = &MI;
Simplified = true;
}
+
// 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(SplatImmNo).getImm();
if (ShiftOp1 == ShiftOp2) {
- // 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
@@ -872,12 +855,34 @@ bool PPCMIPeephole::simplifyCode() {
//
// %6:vrrc = VSPLTB 3, killed %1:vrrc
// %7:vsrc = XXLAND killed %6:vrrc, killed %1:vrrc
+
+ Register ShiftRes = DefMI->getOperand(0).getReg();
if (MRI->hasOneNonDBGUse(ShiftRes)) {
LLVM_DEBUG(dbgs() << "Removing redundant shift: ");
LLVM_DEBUG(DefMI->dump());
ToErase = DefMI;
}
Simplified = true;
+ unsigned ShiftImm = DefMI->getOperand(3).getImm();
+ // The operand number of the splat Imm in the instruction.
+ unsigned SplatImmNo = MyOpcode == PPC::XXSPLTW ? 2 : 1;
+ unsigned SplatImm = MI.getOperand(SplatImmNo).getImm();
+
+ // 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.
+ auto CalculateNewElementIdx = [&](unsigned Opcode) {
+ if (Opcode == PPC::VSPLTB)
+ return (SplatImm + ShiftImm * 4) & 0xF;
+ else if (Opcode == PPC::VSPLTH)
+ return (SplatImm + ShiftImm * 2) & 0x7;
+ else
+ return (SplatImm + ShiftImm) & 0x3;
+ };
+
+ unsigned NewElem = CalculateNewElementIdx(MyOpcode);
+
LLVM_DEBUG(dbgs() << "Changing splat immediate from " << SplatImm
<< " to " << NewElem << " in instruction: ");
LLVM_DEBUG(MI.dump());
>From 65c09ade096e44611764b0fe86b77683bde4ea16 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Fri, 5 Dec 2025 19:45:21 +0000
Subject: [PATCH 3/5] delete a unused varaible
---
llvm/lib/Target/PowerPC/PPCMIPeephole.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
index 18f50a9af588a..977fc177a3002 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -841,7 +841,6 @@ 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();
>From 77535f939aa5e31e4282633d1cc3825a7df2f0e7 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Mon, 8 Dec 2025 15:04:58 +0000
Subject: [PATCH 4/5] minor change
---
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 977fc177a3002..be82a80559e90 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -842,9 +842,8 @@ bool PPCMIPeephole::simplifyCode() {
// vector element zero.
if (DefOpcode == PPC::XXSLDWI) {
Register ShiftOp1 = DefMI->getOperand(1).getReg();
- Register ShiftOp2 = DefMI->getOperand(2).getReg();
- if (ShiftOp1 == ShiftOp2) {
+ if (ShiftOp1 == DefMI->getOperand(2).getReg()) {
// 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
>From 80f2aadd79cbd13de810d4ffaf50747f78f3ffff Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Mon, 8 Dec 2025 15:14:43 +0000
Subject: [PATCH 5/5] minor: address comment
---
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 be82a80559e90..94d06422c12be 100644
--- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp
@@ -854,8 +854,7 @@ bool PPCMIPeephole::simplifyCode() {
// %6:vrrc = VSPLTB 3, killed %1:vrrc
// %7:vsrc = XXLAND killed %6:vrrc, killed %1:vrrc
- Register ShiftRes = DefMI->getOperand(0).getReg();
- if (MRI->hasOneNonDBGUse(ShiftRes)) {
+ if (MRI->hasOneNonDBGUse(DefMI->getOperand(0).getReg())) {
LLVM_DEBUG(dbgs() << "Removing redundant shift: ");
LLVM_DEBUG(DefMI->dump());
ToErase = DefMI;
More information about the llvm-commits
mailing list