[llvm] [VectorCombine] Fold reduction chains with equivalent bitcast sources (PR #212084)
Jinpeng Wang via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 10 02:33:22 PDT 2026
https://github.com/jjppp updated https://github.com/llvm/llvm-project/pull/212084
>From 3d198528021815ff6297739b6a6fd33d8479fac5 Mon Sep 17 00:00:00 2001
From: jpwang <jpwang at smail.nju.edu.cn>
Date: Sun, 26 Jul 2026 03:45:44 +0000
Subject: [PATCH 1/5] [VectorCombine] Recognize reduction chains with
equivalent bitcast sources
---
.../Transforms/Vectorize/VectorCombine.cpp | 22 +++-
.../fold-shuffle-chains-to-reduce.ll | 107 ++++++++++++++++++
2 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index b5f5cd96f4aa5..9b79c7b98a357 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -4263,15 +4263,33 @@ bool VectorCombine::foldShuffleChainsToReduce(Instruction &I) {
APInt Elts;
};
std::optional<ReductionCut> Cut;
+ auto AreEquivalentBitcastSources = [](Value *V1, Value *V2) {
+ auto *C1 = dyn_cast<BitCastInst>(V1);
+ auto *C2 = dyn_cast<BitCastInst>(V2);
+ return C1 && C2 && C1->getType() == C2->getType() &&
+ C1->getOperand(0) == C2->getOperand(0);
+ };
for (Value *S : Sources) {
auto It = Demands.find(S);
if (It == Demands.end() || It->second.Lanes.isZero())
continue;
- if (Cut || (!IsIdempotent && !It->second.Duplicates.isZero())) {
+ if (!IsIdempotent && !It->second.Duplicates.isZero()) {
+ Cut.reset();
+ break;
+ }
+ if (!Cut) {
+ Cut = ReductionCut{S, It->second.Lanes};
+ continue;
+ }
+ if (!AreEquivalentBitcastSources(Cut->Src, S)) {
+ Cut.reset();
+ break;
+ }
+ if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
Cut.reset();
break;
}
- Cut = ReductionCut{S, It->second.Lanes};
+ Cut->Elts |= It->second.Lanes;
}
if (!Cut) {
for (Value *V : Nodes) {
diff --git a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
index f00ce63159d17..eb23fecab6102 100644
--- a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
+++ b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
@@ -435,3 +435,110 @@ define i32 @test_reduce_reconvergent_intermediate_v4i32(<4 x i32> %a) {
%e = extractelement <2 x i32> %c, i64 0
ret i32 %e
}
+
+; Equivalent bitcast sources with disjoint demanded lanes can be merged into
+; one complete reduction.
+define i32 @test_reduce_equivalent_bitcast_sources(<2 x i64> %a) {
+; CHECK-LABEL: define i32 @test_reduce_equivalent_bitcast_sources(
+; CHECK-SAME: <2 x i64> [[A:%.*]]) {
+; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BC0]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %bc0 = bitcast <2 x i64> %a to <4 x i32>
+ %hi = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
+
+ %bc1 = bitcast <2 x i64> %a to <4 x i32>
+ %sum0 = add <4 x i32> %hi, %bc1
+
+ %sh = shufflevector <4 x i32> %sum0, <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+ %sum1 = add <4 x i32> %sum0, %sh
+ %r = extractelement <4 x i32> %sum1, i64 0
+ ret i32 %r
+}
+
+; Equivalent sources demand lane 0 through two different paths. Add is not
+; idempotent, so merging the lane sets would lose one contribution.
+define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
+ <2 x i64> %a) {
+; CHECK-LABEL: define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
+; CHECK-NOT: @llvm.vector.reduce.add
+; CHECK: ret i32
+;
+ %bc0 = bitcast <2 x i64> %a to <4 x i32>
+ %lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+
+ %bc1 = bitcast <2 x i64> %a to <4 x i32>
+ %rhs = shufflevector <4 x i32> %bc1, <4 x i32> poison, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison>
+
+ %sum0 = add <4 x i32> %lhs, %rhs
+ %sh = shufflevector <4 x i32> %sum0, <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+ %sum1 = add <4 x i32> %sum0, %sh
+ %r = extractelement <4 x i32> %sum1, i64 0
+ ret i32 %r
+}
+
+; The second equivalent source has an internally duplicated demanded lane.
+; Its lane set does not overlap the first source, so this specifically checks
+; the per-source Duplicates field rather than cross-source overlap.
+define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
+ <2 x i64> %a) {
+; CHECK-LABEL: define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
+; CHECK-NOT: @llvm.vector.reduce.add
+; CHECK: ret i32
+;
+ %bc0 = bitcast <2 x i64> %a to <4 x i32>
+ %lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+
+ %bc1 = bitcast <2 x i64> %a to <4 x i32>
+ %rhs = shufflevector <4 x i32> %bc1, <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 poison, i32 poison>
+
+ %sum0 = add <4 x i32> %lhs, %rhs
+ %sh = shufflevector <4 x i32> %sum0, <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+ %sum1 = add <4 x i32> %sum0, %sh
+ %r = extractelement <4 x i32> %sum1, i64 0
+ ret i32 %r
+}
+
+; Bitcasts with the same result type but different underlying values are
+; different logical sources and cannot be merged.
+define i32 @test_no_reduce_different_bitcast_sources(
+ <2 x i64> %a, <2 x i64> %b) {
+; CHECK-LABEL: define i32 @test_no_reduce_different_bitcast_sources(
+; CHECK-NOT: @llvm.vector.reduce.add
+; CHECK: ret i32
+;
+ %bc0 = bitcast <2 x i64> %a to <4 x i32>
+ %hi = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
+
+ %bc1 = bitcast <2 x i64> %b to <4 x i32>
+ %sum0 = add <4 x i32> %hi, %bc1
+
+ %sh = shufflevector <4 x i32> %sum0, <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+ %sum1 = add <4 x i32> %sum0, %sh
+ %r = extractelement <4 x i32> %sum1, i64 0
+ ret i32 %r
+}
+
+; Overlapping lanes are safe for an idempotent operation.
+define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
+ <2 x i64> %a) {
+; CHECK-LABEL: define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
+; CHECK-SAME: <2 x i64> [[A:%.*]]) {
+; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[PARTIAL:%.*]] = shufflevector <4 x i32> [[BC0]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.vector.reduce.or.v3i32(<3 x i32> [[PARTIAL]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %bc0 = bitcast <2 x i64> %a to <4 x i32>
+ %lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+
+ %bc1 = bitcast <2 x i64> %a to <4 x i32>
+ %rhs = shufflevector <4 x i32> %bc1, <4 x i32> poison, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison>
+
+ %or0 = or <4 x i32> %lhs, %rhs
+ %sh = shufflevector <4 x i32> %or0, <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+ %or1 = or <4 x i32> %or0, %sh
+ %r = extractelement <4 x i32> %or1, i64 0
+ ret i32 %r
+}
>From f78fa2b175f4baf1f598aca3effaed131f736676 Mon Sep 17 00:00:00 2001
From: jpwang <jpwang at smail.nju.edu.cn>
Date: Mon, 3 Aug 2026 22:58:57 +0800
Subject: [PATCH 2/5] Update tests
---
.../fold-shuffle-chains-to-reduce.ll | 43 ++++++++++++++-----
1 file changed, 33 insertions(+), 10 deletions(-)
diff --git a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
index eb23fecab6102..d401f5e452f2a 100644
--- a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
+++ b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
@@ -460,11 +460,19 @@ define i32 @test_reduce_equivalent_bitcast_sources(<2 x i64> %a) {
; Equivalent sources demand lane 0 through two different paths. Add is not
; idempotent, so merging the lane sets would lose one contribution.
define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
- <2 x i64> %a) {
; CHECK-LABEL: define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
-; CHECK-NOT: @llvm.vector.reduce.add
-; CHECK: ret i32
+; CHECK-SAME: <2 x i64> [[A:%.*]]) {
+; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[LHS:%.*]] = shufflevector <4 x i32> [[BC0]], <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[RHS:%.*]] = shufflevector <4 x i32> [[BC1]], <4 x i32> poison, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison>
+; CHECK-NEXT: [[SUM0:%.*]] = add <4 x i32> [[LHS]], [[RHS]]
+; CHECK-NEXT: [[SH:%.*]] = shufflevector <4 x i32> [[SUM0]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[SUM1:%.*]] = add <4 x i32> [[SUM0]], [[SH]]
+; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
+; CHECK-NEXT: ret i32 [[R]]
;
+ <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
@@ -482,11 +490,19 @@ define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
; Its lane set does not overlap the first source, so this specifically checks
; the per-source Duplicates field rather than cross-source overlap.
define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
- <2 x i64> %a) {
; CHECK-LABEL: define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
-; CHECK-NOT: @llvm.vector.reduce.add
-; CHECK: ret i32
+; CHECK-SAME: <2 x i64> [[A:%.*]]) {
+; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[LHS:%.*]] = shufflevector <4 x i32> [[BC0]], <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[RHS:%.*]] = shufflevector <4 x i32> [[BC1]], <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 poison, i32 poison>
+; CHECK-NEXT: [[SUM0:%.*]] = add <4 x i32> [[LHS]], [[RHS]]
+; CHECK-NEXT: [[SH:%.*]] = shufflevector <4 x i32> [[SUM0]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[SUM1:%.*]] = add <4 x i32> [[SUM0]], [[SH]]
+; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
+; CHECK-NEXT: ret i32 [[R]]
;
+ <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
@@ -503,11 +519,18 @@ define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
; Bitcasts with the same result type but different underlying values are
; different logical sources and cannot be merged.
define i32 @test_no_reduce_different_bitcast_sources(
- <2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: define i32 @test_no_reduce_different_bitcast_sources(
-; CHECK-NOT: @llvm.vector.reduce.add
-; CHECK: ret i32
+; CHECK-SAME: <2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]]) {
+; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
+; CHECK-NEXT: [[HI:%.*]] = shufflevector <4 x i32> [[BC0]], <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
+; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[B]] to <4 x i32>
+; CHECK-NEXT: [[SUM0:%.*]] = add <4 x i32> [[HI]], [[BC1]]
+; CHECK-NEXT: [[SH:%.*]] = shufflevector <4 x i32> [[SUM0]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[SUM1:%.*]] = add <4 x i32> [[SUM0]], [[SH]]
+; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
+; CHECK-NEXT: ret i32 [[R]]
;
+ <2 x i64> %a, <2 x i64> %b) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%hi = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
@@ -522,7 +545,6 @@ define i32 @test_no_reduce_different_bitcast_sources(
; Overlapping lanes are safe for an idempotent operation.
define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
- <2 x i64> %a) {
; CHECK-LABEL: define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
; CHECK-SAME: <2 x i64> [[A:%.*]]) {
; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
@@ -530,6 +552,7 @@ define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.vector.reduce.or.v3i32(<3 x i32> [[PARTIAL]])
; CHECK-NEXT: ret i32 [[R]]
;
+ <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
>From 468fa75268e3d92a66527e082d6172b484c8d0ef Mon Sep 17 00:00:00 2001
From: jpwang <jpwang at smail.nju.edu.cn>
Date: Mon, 3 Aug 2026 23:03:22 +0800
Subject: [PATCH 3/5] Update tests
---
.../VectorCombine/fold-shuffle-chains-to-reduce.ll | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
index d401f5e452f2a..d38d5bef6dd18 100644
--- a/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
+++ b/llvm/test/Transforms/VectorCombine/fold-shuffle-chains-to-reduce.ll
@@ -459,7 +459,7 @@ define i32 @test_reduce_equivalent_bitcast_sources(<2 x i64> %a) {
; Equivalent sources demand lane 0 through two different paths. Add is not
; idempotent, so merging the lane sets would lose one contribution.
-define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
+define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(<2 x i64> %a) {
; CHECK-LABEL: define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
; CHECK-SAME: <2 x i64> [[A:%.*]]) {
; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
@@ -472,7 +472,6 @@ define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
; CHECK-NEXT: ret i32 [[R]]
;
- <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
@@ -489,7 +488,7 @@ define i32 @test_no_reduce_equivalent_bitcast_sources_overlap(
; The second equivalent source has an internally duplicated demanded lane.
; Its lane set does not overlap the first source, so this specifically checks
; the per-source Duplicates field rather than cross-source overlap.
-define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
+define i32 @test_no_reduce_later_equivalent_source_has_duplicates(<2 x i64> %a) {
; CHECK-LABEL: define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
; CHECK-SAME: <2 x i64> [[A:%.*]]) {
; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
@@ -502,7 +501,6 @@ define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
; CHECK-NEXT: ret i32 [[R]]
;
- <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
@@ -518,7 +516,7 @@ define i32 @test_no_reduce_later_equivalent_source_has_duplicates(
; Bitcasts with the same result type but different underlying values are
; different logical sources and cannot be merged.
-define i32 @test_no_reduce_different_bitcast_sources(
+define i32 @test_no_reduce_different_bitcast_sources(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: define i32 @test_no_reduce_different_bitcast_sources(
; CHECK-SAME: <2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]]) {
; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
@@ -530,7 +528,6 @@ define i32 @test_no_reduce_different_bitcast_sources(
; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[SUM1]], i64 0
; CHECK-NEXT: ret i32 [[R]]
;
- <2 x i64> %a, <2 x i64> %b) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%hi = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
@@ -544,7 +541,7 @@ define i32 @test_no_reduce_different_bitcast_sources(
}
; Overlapping lanes are safe for an idempotent operation.
-define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
+define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(<2 x i64> %a) {
; CHECK-LABEL: define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
; CHECK-SAME: <2 x i64> [[A:%.*]]) {
; CHECK-NEXT: [[BC0:%.*]] = bitcast <2 x i64> [[A]] to <4 x i32>
@@ -552,7 +549,6 @@ define i32 @test_reduce_idempotent_equivalent_bitcast_sources_overlap(
; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.vector.reduce.or.v3i32(<3 x i32> [[PARTIAL]])
; CHECK-NEXT: ret i32 [[R]]
;
- <2 x i64> %a) {
%bc0 = bitcast <2 x i64> %a to <4 x i32>
%lhs = shufflevector <4 x i32> %bc0, <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
>From 826b2ae9c046a3655882b75c83215e835d3e242a Mon Sep 17 00:00:00 2001
From: jpwang <jpwang at smail.nju.edu.cn>
Date: Fri, 7 Aug 2026 00:17:58 +0800
Subject: [PATCH 4/5] Use peekThroughBitcasts for generality
---
.../Transforms/Vectorize/VectorCombine.cpp | 24 +++++++------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 9b79c7b98a357..c596b789a21ca 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -219,6 +219,12 @@ static Value *peekThroughBitcasts(Value *V) {
return V;
}
+/// Helper to peek through bitcasts to the same value.
+static bool isEquivBitcast(Value *X, Value *Y) {
+ return X->getType() == Y->getType() &&
+ peekThroughBitcasts(X) == peekThroughBitcasts(Y);
+}
+
static bool canWidenLoad(LoadInst *Load, const TargetTransformInfo &TTI) {
// Do not widen load if atomic/volatile or under asan/hwasan/memtag/tsan.
// The widened load may load data from dirty regions or create data races
@@ -3740,19 +3746,13 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
if (!FrontV)
return false;
- // Helper to peek through bitcasts to the same value.
- auto IsEquiv = [&](Value *X, Value *Y) {
- return X->getType() == Y->getType() &&
- peekThroughBitcasts(X) == peekThroughBitcasts(Y);
- };
-
// Look for an identity value.
if (FrontLane == 0 &&
cast<FixedVectorType>(FrontV->getType())->getNumElements() ==
Item.size() &&
- all_of(drop_begin(enumerate(Item)), [IsEquiv, Item](const auto &E) {
+ all_of(drop_begin(enumerate(Item)), [Item](const auto &E) {
Value *FrontV = Item.front().first;
- return !E.value().first || (IsEquiv(E.value().first, FrontV) &&
+ return !E.value().first || (isEquivBitcast(E.value().first, FrontV) &&
E.value().second == (int)E.index());
})) {
IdentityLeafs.insert(std::make_pair(FrontV, From));
@@ -4263,12 +4263,6 @@ bool VectorCombine::foldShuffleChainsToReduce(Instruction &I) {
APInt Elts;
};
std::optional<ReductionCut> Cut;
- auto AreEquivalentBitcastSources = [](Value *V1, Value *V2) {
- auto *C1 = dyn_cast<BitCastInst>(V1);
- auto *C2 = dyn_cast<BitCastInst>(V2);
- return C1 && C2 && C1->getType() == C2->getType() &&
- C1->getOperand(0) == C2->getOperand(0);
- };
for (Value *S : Sources) {
auto It = Demands.find(S);
if (It == Demands.end() || It->second.Lanes.isZero())
@@ -4281,7 +4275,7 @@ bool VectorCombine::foldShuffleChainsToReduce(Instruction &I) {
Cut = ReductionCut{S, It->second.Lanes};
continue;
}
- if (!AreEquivalentBitcastSources(Cut->Src, S)) {
+ if (!isEquivBitcast(Cut->Src, S)) {
Cut.reset();
break;
}
>From 4fee22e998f6a26f938548cfc959cd4ca26877dd Mon Sep 17 00:00:00 2001
From: jpwang <jpwang at smail.nju.edu.cn>
Date: Mon, 10 Aug 2026 17:33:05 +0800
Subject: [PATCH 5/5] fix style issue
---
llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index c792badb03d96..b88472f69c548 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -222,7 +222,7 @@ static Value *peekThroughBitcasts(Value *V) {
/// Helper to peek through bitcasts to the same value.
static bool isEquivBitcast(Value *X, Value *Y) {
return X->getType() == Y->getType() &&
- peekThroughBitcasts(X) == peekThroughBitcasts(Y);
+ peekThroughBitcasts(X) == peekThroughBitcasts(Y);
}
static bool canWidenLoad(LoadInst *Load, const TargetTransformInfo &TTI) {
More information about the llvm-commits
mailing list