[llvm] [PowerPC] fix the costs of vector insert/extract for wide integers on 32-bit targets (PR #195263)
zhijian lin via llvm-commits
llvm-commits at lists.llvm.org
Fri May 1 06:34:12 PDT 2026
https://github.com/diggerlin created https://github.com/llvm/llvm-project/pull/195263
The patch fix the issue
[[PPC PWR10] Bit extraction opts to use expensive vector code](https://github.com/llvm/llvm-project/issues/113352)
>From c9cca4a5a55b7968ee4dfca4a36026534103eeb0 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Tue, 14 Apr 2026 20:17:55 +0000
Subject: [PATCH 1/3] add pre-commit test case
---
.../SLPVectorizer/PowerPC/issue-113352.ll | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
diff --git a/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll b/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
new file mode 100644
index 0000000000000..28a6b841e5d46
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
@@ -0,0 +1,23 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -mtriple=powerpc-unknown-aix -mcpu=pwr10 -passes=slp-vectorizer < %s | FileCheck %s
+
+define range(i64 0, 8) i64 @extract_bits1(i64 noundef %a) local_unnamed_addr {
+; CHECK-LABEL: @extract_bits1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i64> [[TMP0]], <2 x i64> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 2, i64 5>
+; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i64> [[TMP2]], <i64 1, i64 6>
+; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i64> [[TMP3]], i32 0
+; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP3]], i32 1
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[TMP4]], [[TMP5]]
+; CHECK-NEXT: ret i64 [[OR]]
+;
+entry:
+ %shr = lshr i64 %a, 2
+ %and = and i64 %shr, 1
+ %shr1 = lshr i64 %a, 5
+ %and2 = and i64 %shr1, 6
+ %or = or disjoint i64 %and, %and2
+ ret i64 %or
+}
>From 7c50c2eae3c1516b300ec6bec7a512154dae818d Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Tue, 14 Apr 2026 20:21:24 +0000
Subject: [PATCH 2/3] fix the issue 113352
---
llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp | 11 +++++++++++
.../Transforms/SLPVectorizer/PowerPC/issue-113352.ll | 12 +++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index 6971db1acfc8e..536c5f7251936 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -710,6 +710,17 @@ InstructionCost PPCTTIImpl::getVectorInstrCost(
}
if (Val->getScalarType()->isIntegerTy()) {
unsigned EltSize = Val->getScalarSizeInBits();
+ // On 32-bit targets, moving wider values in and out of vector registers
+ // is more expensive because we need to move 2 registers and we do so
+ // through the stack. There are 2 scalar stores + vector load + permute
+ // to combine with existing element for insert. The extract is a bit
+ // simpler as the combine isn't needed - vector store + 2 scalar loads.
+ if (EltSize > 32 && !ST->isPPC64()) {
+ if (ISD == ISD::EXTRACT_VECTOR_ELT)
+ CostFactor *= 3;
+ else if (ISD == ISD::INSERT_VECTOR_ELT)
+ CostFactor *= 4;
+ }
// Computing on 1 bit values requires extra mask or compare operations.
unsigned MaskCostForOneBitSize = (VecMaskCost && EltSize == 1) ? 1 : 0;
// Computing on non const index requires extra mask or compare operations.
diff --git a/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll b/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
index 28a6b841e5d46..ba5a6e0e779c6 100644
--- a/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
+++ b/llvm/test/Transforms/SLPVectorizer/PowerPC/issue-113352.ll
@@ -4,13 +4,11 @@
define range(i64 0, 8) i64 @extract_bits1(i64 noundef %a) local_unnamed_addr {
; CHECK-LABEL: @extract_bits1(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
-; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i64> [[TMP0]], <2 x i64> poison, <2 x i32> zeroinitializer
-; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 2, i64 5>
-; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i64> [[TMP2]], <i64 1, i64 6>
-; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i64> [[TMP3]], i32 0
-; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP3]], i32 1
-; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[TMP4]], [[TMP5]]
+; CHECK-NEXT: [[SHR:%.*]] = lshr i64 [[A:%.*]], 2
+; CHECK-NEXT: [[AND:%.*]] = and i64 [[SHR]], 1
+; CHECK-NEXT: [[SHR1:%.*]] = lshr i64 [[A]], 5
+; CHECK-NEXT: [[AND2:%.*]] = and i64 [[SHR1]], 6
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[AND]], [[AND2]]
; CHECK-NEXT: ret i64 [[OR]]
;
entry:
>From 692b017ddb12a7b5b3dc1c1eadc035411f280ebc Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Mon, 27 Apr 2026 19:53:54 +0000
Subject: [PATCH 3/3] changed existing test cased on the new slp vectorize pass
cost mode
---
.../CostModel/PowerPC/ld-st-with-length.ll | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/llvm/test/Analysis/CostModel/PowerPC/ld-st-with-length.ll b/llvm/test/Analysis/CostModel/PowerPC/ld-st-with-length.ll
index 0f854781c02ae..5a3a5280651ea 100644
--- a/llvm/test/Analysis/CostModel/PowerPC/ld-st-with-length.ll
+++ b/llvm/test/Analysis/CostModel/PowerPC/ld-st-with-length.ll
@@ -79,9 +79,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; P932-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i16.p0(<2 x i16> %x2, ptr align 1 %base, <2 x i1> splat (i1 true))
; P932-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %x3 = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i32> zeroinitializer)
; P932-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i32.p0(<2 x i32> %x3, ptr align 1 %base, <2 x i1> splat (i1 true))
-; P932-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
+; P932-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
; P932-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.masked.store.v2i64.p0(<2 x i64> %x4, ptr align 1 %base, <2 x i1> splat (i1 true))
-; P932-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
+; P932-NEXT: Cost Model: Found an estimated cost of 72 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
; P932-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.masked.store.v3i64.p0(<3 x i64> %x5, ptr align 1 %base, <3 x i1> splat (i1 true))
; P932-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %x6 = call <4 x i15> @llvm.masked.load.v4i15.p0(ptr align 1 %base, <4 x i1> splat (i1 true), <4 x i15> zeroinitializer)
; P932-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.masked.store.v4i15.p0(<4 x i15> %x6, ptr align 1 %base, <4 x i1> splat (i1 true))
@@ -91,9 +91,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; P932-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i16.p0(<2 x i16> %x8, ptr %base, <2 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %x9 = call <2 x i32> @llvm.vp.load.v2i32.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i32.p0(<2 x i32> %x9, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; P932-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
+; P932-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.vp.store.v2i64.p0(<2 x i64> %x10, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; P932-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
+; P932-NEXT: Cost Model: Found an estimated cost of 72 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.vp.store.v3i64.p0(<3 x i64> %x11, ptr %base, <3 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %x12 = call <4 x i15> @llvm.vp.load.v4i15.p0(ptr %base, <4 x i1> splat (i1 true), i32 1)
; P932-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.vp.store.v4i15.p0(<4 x i15> %x12, ptr %base, <4 x i1> splat (i1 true), i32 1)
@@ -172,9 +172,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i16.p0(<2 x i16> %x2, ptr align 1 %base, <2 x i1> splat (i1 true))
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %x3 = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i32> zeroinitializer)
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i32.p0(<2 x i32> %x3, ptr align 1 %base, <2 x i1> splat (i1 true))
-; P1032-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
+; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
; P1032-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.masked.store.v2i64.p0(<2 x i64> %x4, ptr align 1 %base, <2 x i1> splat (i1 true))
-; P1032-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
+; P1032-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
; P1032-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.masked.store.v3i64.p0(<3 x i64> %x5, ptr align 1 %base, <3 x i1> splat (i1 true))
; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x6 = call <4 x i15> @llvm.masked.load.v4i15.p0(ptr align 1 %base, <4 x i1> splat (i1 true), <4 x i15> zeroinitializer)
; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.masked.store.v4i15.p0(<4 x i15> %x6, ptr align 1 %base, <4 x i1> splat (i1 true))
@@ -184,9 +184,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i16.p0(<2 x i16> %x8, ptr %base, <2 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %x9 = call <2 x i32> @llvm.vp.load.v2i32.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i32.p0(<2 x i32> %x9, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; P1032-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
+; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.vp.store.v2i64.p0(<2 x i64> %x10, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; P1032-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
+; P1032-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.vp.store.v3i64.p0(<3 x i64> %x11, ptr %base, <3 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x12 = call <4 x i15> @llvm.vp.load.v4i15.p0(ptr %base, <4 x i1> splat (i1 true), i32 1)
; P1032-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.vp.store.v4i15.p0(<4 x i15> %x12, ptr %base, <4 x i1> splat (i1 true), i32 1)
@@ -265,9 +265,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i16.p0(<2 x i16> %x2, ptr align 1 %base, <2 x i1> splat (i1 true))
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %x3 = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i32> zeroinitializer)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.masked.store.v2i32.p0(<2 x i32> %x3, ptr align 1 %base, <2 x i1> splat (i1 true))
-; FUTURE32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
+; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x4 = call <2 x i64> @llvm.masked.load.v2i64.p0(ptr align 1 %base, <2 x i1> splat (i1 true), <2 x i64> zeroinitializer)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.masked.store.v2i64.p0(<2 x i64> %x4, ptr align 1 %base, <2 x i1> splat (i1 true))
-; FUTURE32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
+; FUTURE32-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %x5 = call <3 x i64> @llvm.masked.load.v3i64.p0(ptr align 1 %base, <3 x i1> splat (i1 true), <3 x i64> zeroinitializer)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.masked.store.v3i64.p0(<3 x i64> %x5, ptr align 1 %base, <3 x i1> splat (i1 true))
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x6 = call <4 x i15> @llvm.masked.load.v4i15.p0(ptr align 1 %base, <4 x i1> splat (i1 true), <4 x i15> zeroinitializer)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.masked.store.v4i15.p0(<4 x i15> %x6, ptr align 1 %base, <4 x i1> splat (i1 true))
@@ -277,9 +277,9 @@ define void @bar(ptr %base, <2 x i8> %val) {
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i16.p0(<2 x i16> %x8, ptr %base, <2 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %x9 = call <2 x i32> @llvm.vp.load.v2i32.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: call void @llvm.vp.store.v2i32.p0(<2 x i32> %x9, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; FUTURE32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
+; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x10 = call <2 x i64> @llvm.vp.load.v2i64.p0(ptr %base, <2 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: call void @llvm.vp.store.v2i64.p0(<2 x i64> %x10, ptr %base, <2 x i1> splat (i1 true), i32 1)
-; FUTURE32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
+; FUTURE32-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %x11 = call <3 x i64> @llvm.vp.load.v3i64.p0(ptr %base, <3 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: call void @llvm.vp.store.v3i64.p0(<3 x i64> %x11, ptr %base, <3 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %x12 = call <4 x i15> @llvm.vp.load.v4i15.p0(ptr %base, <4 x i1> splat (i1 true), i32 1)
; FUTURE32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: call void @llvm.vp.store.v4i15.p0(<4 x i15> %x12, ptr %base, <4 x i1> splat (i1 true), i32 1)
More information about the llvm-commits
mailing list