[llvm] [VectorCombine] Merge permutes of the same source in foldShuffleOfBinops (PR #228472)
Weiwen He via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 07:55:21 PDT 2026
https://github.com/he-weiwen created https://github.com/llvm/llvm-project/pull/228472
Fixes #206147
Adds a new `MergePermutes` step to `foldShuffleOfBinops` to handle cases where the two operands that would end up on the same side of the binop are permutes on the same value, i.e:
```
x = shuffle(v, poison, m1), z = shuffle(v, poison, m2)
shuffle(binop(x , ...), binop(z, ...), M)
= binop(shuffle(shuffle(v, poison, m1), shuffle(v, poison, m2), M), ...)
= binop(shuffle(v, poison, M'), ...)
```
Unlike the existing `MergeInner`, `MergePermutes` allows v to have different widths from `x/z` .
It’s called after `MergeInner` is done. When the width of `v` is equal to that of `x/z`, both apply: `MergeInner` folds it into `shuffle(v, v)`, and `MergePermutes` folds it further into `shuffle(v, poison)`.
When the folded shuffle is an identity except for poison lanes - `MergePermutes` fold it into `shuffle(v, poison, <0…n-1>)`. Not doing so would lead to regressions in test cases that were previously handled by `foldShuffleToIdentity` .
>From c8b8cff9eb67b2cbbb12f9d93724ee08e09f0cb6 Mon Sep 17 00:00:00 2001
From: Weiwen He <he.weiwen at outlook.com>
Date: Fri, 2 Oct 2026 12:19:56 +0100
Subject: [PATCH 1/2] [VectorCombine] Add baseline tests for shuffles of binops
of same-source permutes (NFC)
---
.../AArch64/shuffletoidentity.ll | 19 +++++
.../VectorCombine/X86/shuffle-of-binops.ll | 75 +++++++++++++++++++
2 files changed, 94 insertions(+)
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
index 9364b4efa89311..5613941cf5726e 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
@@ -259,6 +259,25 @@ define <8 x half> @splatandidentity(<8 x half> %a, <8 x half> %b) {
ret <8 x half> %r
}
+define <8 x half> @splatandidentity_commuted(<8 x half> %a, <8 x half> %b) {
+; CHECK-LABEL: @splatandidentity_commuted(
+; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
+; CHECK-NEXT: [[BS:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT: [[ABT:%.*]] = fadd <4 x half> [[AT]], [[BS]]
+; CHECK-NEXT: [[ABB:%.*]] = fadd <4 x half> [[BS]], [[AB]]
+; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x half> [[ABT]], <4 x half> [[ABB]], <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: ret <8 x half> [[R]]
+;
+ %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
+ %bs = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> zeroinitializer
+ %abt = fadd <4 x half> %at, %bs
+ %abb = fadd <4 x half> %bs, %ab
+ %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ ret <8 x half> %r
+}
+
define <8 x half> @splattwice(<8 x half> %a, <8 x half> %b) {
; CHECK-LABEL: @splattwice(
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <8 x i32> zeroinitializer
diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
index e1e95019680434..8ca6dd358d7e2b 100644
--- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
+++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
@@ -490,3 +490,78 @@ define <8 x i32> @shuf_uniform_const_mul_v8i32_v4i32(<4 x i32> %a0, <4 x i32> %a
%res = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
ret <8 x i32> %res
}
+
+define <8 x float> @shuf_fdiv_v4f32_extract_halves_poison(<4 x float> %x, <4 x float> %z, <8 x float> %d) {
+; CHECK-LABEL: define <8 x float> @shuf_fdiv_v4f32_extract_halves_poison(
+; CHECK-SAME: <4 x float> [[X:%.*]], <4 x float> [[Z:%.*]], <8 x float> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x float> [[D]], <8 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; CHECK-NEXT: [[HI:%.*]] = shufflevector <8 x float> [[D]], <8 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: [[L:%.*]] = fdiv <4 x float> [[X]], [[LO]]
+; CHECK-NEXT: [[R:%.*]] = fdiv <4 x float> [[Z]], [[HI]]
+; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[L]], <4 x float> [[R]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 poison>
+; CHECK-NEXT: ret <8 x float> [[S]]
+;
+ %lo = shufflevector <8 x float> %d, <8 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %hi = shufflevector <8 x float> %d, <8 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %l = fdiv <4 x float> %x, %lo
+ %r = fdiv <4 x float> %z, %hi
+ %s = shufflevector <4 x float> %l, <4 x float> %r, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 poison>
+ ret <8 x float> %s
+}
+
+define <4 x i32> @shuf_sdiv_v4i32_same_width_permutes_of_same_src(<4 x i32> %a, <4 x i32> %y) {
+; CHECK-LABEL: define <4 x i32> @shuf_sdiv_v4i32_same_width_permutes_of_same_src(
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <4 x i32> <i32 1, i32 0, i32 5, i32 4>
+; CHECK-NEXT: [[S:%.*]] = sdiv <4 x i32> [[Y]], [[TMP1]]
+; CHECK-NEXT: ret <4 x i32> [[S]]
+;
+ %a0 = shufflevector <4 x i32> %a, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+ %a1 = shufflevector <4 x i32> %a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %l = sdiv <4 x i32> %y, %a0
+ %r = sdiv <4 x i32> %y, %a1
+ %s = shufflevector <4 x i32> %l, <4 x i32> %r, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+ ret <4 x i32> %s
+}
+
+define <8 x i32> @shuf_sdiv_v4i32_extract_halves_multiuse(<8 x i32> %a, <4 x i32> %y) {
+; CHECK-LABEL: define <8 x i32> @shuf_sdiv_v4i32_extract_halves_multiuse(
+; CHECK-SAME: <8 x i32> [[A:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x i32> [[A]], <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; CHECK-NEXT: [[HI:%.*]] = shufflevector <8 x i32> [[A]], <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: call void @use(<4 x i32> [[LO]])
+; CHECK-NEXT: [[L:%.*]] = sdiv <4 x i32> [[Y]], [[LO]]
+; CHECK-NEXT: [[R:%.*]] = sdiv <4 x i32> [[Y]], [[HI]]
+; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[L]], <4 x i32> [[R]], <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
+; CHECK-NEXT: ret <8 x i32> [[S]]
+;
+ %lo = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %hi = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ call void @use(<4 x i32> %lo)
+ %l = sdiv <4 x i32> %y, %lo
+ %r = sdiv <4 x i32> %y, %hi
+ %s = shufflevector <4 x i32> %l, <4 x i32> %r, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
+ ret <8 x i32> %s
+}
+
+define <8 x i32> @shuf_add_v4i32_extract_halves_multiuse_binops(<8 x i32> %a, <4 x i32> %y) {
+; CHECK-LABEL: define <8 x i32> @shuf_add_v4i32_extract_halves_multiuse_binops(
+; CHECK-SAME: <8 x i32> [[A:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[A0:%.*]] = shufflevector <8 x i32> [[A]], <8 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[A1:%.*]] = shufflevector <8 x i32> [[A]], <8 x i32> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
+; CHECK-NEXT: [[L:%.*]] = add <4 x i32> [[A0]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[A1]], [[Y]]
+; CHECK-NEXT: call void @use(<4 x i32> [[L]])
+; CHECK-NEXT: call void @use(<4 x i32> [[R]])
+; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[L]], <4 x i32> [[R]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: ret <8 x i32> [[S]]
+;
+ %a0 = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %a1 = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
+ %l = add <4 x i32> %a0, %y
+ %r = add <4 x i32> %a1, %y
+ call void @use(<4 x i32> %l)
+ call void @use(<4 x i32> %r)
+ %s = shufflevector <4 x i32> %l, <4 x i32> %r, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ ret <8 x i32> %s
+}
>From 031e229016fd0d087dbbc061a6a6a778d64c17d5 Mon Sep 17 00:00:00 2001
From: Weiwen He <he.weiwen at outlook.com>
Date: Fri, 2 Oct 2026 12:20:06 +0100
Subject: [PATCH 2/2] [VectorCombine] Merge permutes of the same source in
foldShuffleOfBinops
---
.../Transforms/Vectorize/VectorCombine.cpp | 57 ++++++++++++++++++-
.../test/Transforms/PhaseOrdering/X86/hadd.ll | 20 ++-----
.../test/Transforms/PhaseOrdering/X86/hsub.ll | 20 ++-----
.../AArch64/shuffletoidentity-concat.ll | 28 ++-------
.../AArch64/shuffletoidentity.ll | 35 +++---------
.../VectorCombine/X86/shuffle-of-binops.ll | 9 +--
6 files changed, 82 insertions(+), 87 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index d16a3a1535cb75..46650a22e37880 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -2805,11 +2805,62 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
}
return false;
};
+ // Handle shuffle(binop(x,y),binop(z,w)) where (x, z) or (y, w) are permutes
+ // of the same value, so that shuffle of permutes on either operand of the
+ // binop can be merged into a single permute.
+ FixedVectorType *SrcTy0 = BinOpTy, *SrcTy1 = BinOpTy;
+ auto MergePermutes = [&](Value *&A, Value *&B, MutableArrayRef<int> Mask,
+ TargetTransformInfo::ShuffleKind &SK,
+ FixedVectorType *&SrcTy) -> bool {
+ auto GetSource = [](Value *Op) -> std::pair<Value *, ArrayRef<int>> {
+ Value *InnerOp;
+ ArrayRef<int> InnerMask;
+ if (match(Op, m_OneUse(m_Shuffle(m_Value(InnerOp), m_Undef(),
+ m_Mask(InnerMask)))) &&
+ all_of(InnerMask, [InnerOp](int M) {
+ auto *VTy = cast<FixedVectorType>(InnerOp->getType());
+ return M < (int)VTy->getNumElements();
+ }))
+ return {InnerOp, InnerMask};
+ return {Op, {}};
+ };
+ auto [V, MaskA] = GetSource(A);
+ auto [VB, MaskB] = GetSource(B);
+ if (VB != V)
+ return false;
+ auto *VTy = cast<FixedVectorType>(V->getType());
+ for (int &M : Mask) {
+ if (M < 0)
+ continue;
+ if (M < (int)NumSrcElts)
+ M = MaskA.empty() ? M : MaskA[M];
+ else
+ M = MaskB.empty() ? M - NumSrcElts : MaskB[M - NumSrcElts];
+ }
+ // If the merged shuffle is an identity apart from poison lanes, refine
+ // those lanes to make it a pure identity so that it folds away to V.
+ if (ShuffleVectorInst::isIdentityMask(Mask, VTy->getNumElements()))
+ std::iota(Mask.begin(), Mask.end(), 0);
+ // A permute is only removed if the binop using it is removed too.
+ bool RemoveA = !MaskA.empty() && LHS->hasOneUser();
+ bool RemoveB = !MaskB.empty() && RHS->hasOneUser();
+ if (RemoveA)
+ OldCost += TTI.getInstructionCost(cast<Instruction>(A), CostKind);
+ if (RemoveB)
+ OldCost += TTI.getInstructionCost(cast<Instruction>(B), CostKind);
+ A = V;
+ B = PoisonValue::get(VTy);
+ SK = TargetTransformInfo::SK_PermuteSingleSrc;
+ SrcTy = VTy;
+ return RemoveA || RemoveB;
+ };
bool ReducedInstCount = false;
ReducedInstCount |= MergeInner(X, 0, NewMask0, CostKind);
ReducedInstCount |= MergeInner(Y, 0, NewMask1, CostKind);
ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0, CostKind);
ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1, CostKind);
+ ReducedInstCount |= MergePermutes(X, Z, NewMask0, SK0, SrcTy0);
+ ReducedInstCount |= MergePermutes(Y, W, NewMask1, SK1, SrcTy1);
bool SingleSrcBinOp = (X == Y) && (Z == W) && (NewMask0 == NewMask1);
// SingleSrcBinOp only reduces instruction count if we also eliminate the
// original binop(s). If binops have multiple uses, they won't be eliminated.
@@ -2829,10 +2880,10 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
auto *ShuffleCmpTy =
FixedVectorType::get(BinOpTy->getElementType(), ShuffleDstTy);
InstructionCost NewCost = TTI.getShuffleCost(
- SK0, ShuffleCmpTy, BinOpTy, CostKind, NewMask0, 0, nullptr, {X, Z});
+ SK0, ShuffleCmpTy, SrcTy0, CostKind, NewMask0, 0, nullptr, {X, Z});
if (!SingleSrcBinOp)
- NewCost += TTI.getShuffleCost(SK1, ShuffleCmpTy, BinOpTy, CostKind,
- NewMask1, 0, nullptr, {Y, W});
+ NewCost += TTI.getShuffleCost(SK1, ShuffleCmpTy, SrcTy1, CostKind, NewMask1,
+ 0, nullptr, {Y, W});
if (PredLHS == CmpInst::BAD_ICMP_PREDICATE) {
NewCost += TTI.getArithmeticInstrCost(LHS->getOpcode(), ShuffleDstTy,
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/hadd.ll b/llvm/test/Transforms/PhaseOrdering/X86/hadd.ll
index 70a84d14bd6cf9..5c8b0c4e100f87 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/hadd.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/hadd.ll
@@ -137,24 +137,16 @@ define <8 x i16> @add_v8i16_76u43210(<8 x i16> %a, <8 x i16> %b) {
; SSE2-NEXT: ret <8 x i16> [[RESULT]]
;
; SSE4-LABEL: @add_v8i16_76u43210(
-; SSE4-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <8 x i32> <i32 0, i32 3, i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <8 x i32> <i32 1, i32 2, i32 5, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[HADD22:%.*]] = add <8 x i16> [[TMP1]], [[TMP2]]
-; SSE4-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B:%.*]], <8 x i32> <i32 6, i32 8, i32 poison, i32 12, i32 14, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B]], <8 x i32> <i32 7, i32 9, i32 poison, i32 13, i32 15, i32 poison, i32 poison, i32 poison>
+; SSE4-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[A:%.*]], <8 x i32> <i32 6, i32 4, i32 poison, i32 0, i32 14, i32 12, i32 11, i32 8>
+; SSE4-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[A]], <8 x i32> <i32 7, i32 5, i32 poison, i32 1, i32 15, i32 13, i32 10, i32 9>
; SSE4-NEXT: [[TMP5:%.*]] = add <8 x i16> [[TMP3]], [[TMP4]]
-; SSE4-NEXT: [[RESULT:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[HADD22]], <8 x i32> <i32 4, i32 3, i32 poison, i32 1, i32 0, i32 10, i32 9, i32 8>
-; SSE4-NEXT: ret <8 x i16> [[RESULT]]
+; SSE4-NEXT: ret <8 x i16> [[TMP5]]
;
; AVX-LABEL: @add_v8i16_76u43210(
-; AVX-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <8 x i32> <i32 0, i32 3, i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <8 x i32> <i32 1, i32 2, i32 5, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[HADD22:%.*]] = add <8 x i16> [[TMP1]], [[TMP2]]
-; AVX-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B:%.*]], <8 x i32> <i32 6, i32 8, i32 poison, i32 12, i32 14, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B]], <8 x i32> <i32 7, i32 9, i32 poison, i32 13, i32 15, i32 poison, i32 poison, i32 poison>
+; AVX-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[A:%.*]], <8 x i32> <i32 6, i32 4, i32 poison, i32 0, i32 14, i32 12, i32 11, i32 8>
+; AVX-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[A]], <8 x i32> <i32 7, i32 5, i32 poison, i32 1, i32 15, i32 13, i32 10, i32 9>
; AVX-NEXT: [[TMP5:%.*]] = add <8 x i16> [[TMP3]], [[TMP4]]
-; AVX-NEXT: [[RESULT:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[HADD22]], <8 x i32> <i32 4, i32 3, i32 poison, i32 1, i32 0, i32 10, i32 9, i32 8>
-; AVX-NEXT: ret <8 x i16> [[RESULT]]
+; AVX-NEXT: ret <8 x i16> [[TMP5]]
;
%a0 = extractelement <8 x i16> %a, i32 0
%a1 = extractelement <8 x i16> %a, i32 1
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/hsub.ll b/llvm/test/Transforms/PhaseOrdering/X86/hsub.ll
index 966e8ca62e9ec9..fa1496660d93fd 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/hsub.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/hsub.ll
@@ -137,24 +137,16 @@ define <8 x i16> @sub_v8i16_76u43210(<8 x i16> %a, <8 x i16> %b) {
; SSE2-NEXT: ret <8 x i16> [[RESULT]]
;
; SSE4-LABEL: @sub_v8i16_76u43210(
-; SSE4-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[HSUB22:%.*]] = sub <8 x i16> [[TMP1]], [[TMP2]]
-; SSE4-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B:%.*]], <8 x i32> <i32 6, i32 8, i32 poison, i32 12, i32 14, i32 poison, i32 poison, i32 poison>
-; SSE4-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B]], <8 x i32> <i32 7, i32 9, i32 poison, i32 13, i32 15, i32 poison, i32 poison, i32 poison>
+; SSE4-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[A:%.*]], <8 x i32> <i32 6, i32 4, i32 poison, i32 0, i32 14, i32 12, i32 10, i32 8>
+; SSE4-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[A]], <8 x i32> <i32 7, i32 5, i32 poison, i32 1, i32 15, i32 13, i32 11, i32 9>
; SSE4-NEXT: [[TMP5:%.*]] = sub <8 x i16> [[TMP3]], [[TMP4]]
-; SSE4-NEXT: [[RESULT:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[HSUB22]], <8 x i32> <i32 4, i32 3, i32 poison, i32 1, i32 0, i32 10, i32 9, i32 8>
-; SSE4-NEXT: ret <8 x i16> [[RESULT]]
+; SSE4-NEXT: ret <8 x i16> [[TMP5]]
;
; AVX-LABEL: @sub_v8i16_76u43210(
-; AVX-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[HSUB22:%.*]] = sub <8 x i16> [[TMP1]], [[TMP2]]
-; AVX-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B:%.*]], <8 x i32> <i32 6, i32 8, i32 poison, i32 12, i32 14, i32 poison, i32 poison, i32 poison>
-; AVX-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[B]], <8 x i32> <i32 7, i32 9, i32 poison, i32 13, i32 15, i32 poison, i32 poison, i32 poison>
+; AVX-NEXT: [[TMP3:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[A:%.*]], <8 x i32> <i32 6, i32 4, i32 poison, i32 0, i32 14, i32 12, i32 10, i32 8>
+; AVX-NEXT: [[TMP4:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[A]], <8 x i32> <i32 7, i32 5, i32 poison, i32 1, i32 15, i32 13, i32 11, i32 9>
; AVX-NEXT: [[TMP5:%.*]] = sub <8 x i16> [[TMP3]], [[TMP4]]
-; AVX-NEXT: [[RESULT:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[HSUB22]], <8 x i32> <i32 4, i32 3, i32 poison, i32 1, i32 0, i32 10, i32 9, i32 8>
-; AVX-NEXT: ret <8 x i16> [[RESULT]]
+; AVX-NEXT: ret <8 x i16> [[TMP5]]
;
%a0 = extractelement <8 x i16> %a, i32 0
%a1 = extractelement <8 x i16> %a, i32 1
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity-concat.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity-concat.ll
index b88bdae4a335a6..f2910862f2e92b 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity-concat.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity-concat.ll
@@ -136,30 +136,12 @@ define <16 x i32> @concata_addmul_bigger(<4 x i32> %a1a, <4 x i32> %a2a, <4 x i3
define <16 x i32> @concata_addmul_bigger_undef(<4 x i32> %a1a, <4 x i32> %a2a, <4 x i32> %a3a, <4 x i32> %a4a, <16 x i32> %b, <16 x i32> %c) {
; CHECK-LABEL: @concata_addmul_bigger_undef(
-; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x i32> [[A1A:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[A2:%.*]] = shufflevector <4 x i32> [[A2A:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[A3:%.*]] = shufflevector <4 x i32> [[A3A:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[A4:%.*]] = shufflevector <4 x i32> [[A4A:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[B1:%.*]] = shufflevector <16 x i32> [[B:%.*]], <16 x i32> poison, <4 x i32> <i32 15, i32 14, i32 13, i32 12>
-; CHECK-NEXT: [[B2:%.*]] = shufflevector <16 x i32> [[B]], <16 x i32> poison, <4 x i32> <i32 11, i32 10, i32 9, i32 8>
-; CHECK-NEXT: [[B3:%.*]] = shufflevector <16 x i32> [[B]], <16 x i32> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[B4:%.*]] = shufflevector <16 x i32> [[B]], <16 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[C1:%.*]] = shufflevector <16 x i32> [[C:%.*]], <16 x i32> poison, <4 x i32> <i32 15, i32 14, i32 13, i32 12>
-; CHECK-NEXT: [[C2:%.*]] = shufflevector <16 x i32> [[C]], <16 x i32> poison, <4 x i32> <i32 11, i32 10, i32 9, i32 8>
-; CHECK-NEXT: [[C3:%.*]] = shufflevector <16 x i32> [[C]], <16 x i32> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[C4:%.*]] = shufflevector <16 x i32> [[C]], <16 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[X1:%.*]] = mul <4 x i32> [[A1]], [[B1]]
-; CHECK-NEXT: [[X2:%.*]] = mul <4 x i32> [[A2]], [[B2]]
-; CHECK-NEXT: [[X3:%.*]] = mul <4 x i32> [[A3]], [[B3]]
-; CHECK-NEXT: [[X4:%.*]] = mul <4 x i32> [[A4]], [[B4]]
-; CHECK-NEXT: [[Y1:%.*]] = add <4 x i32> [[X1]], [[C1]]
-; CHECK-NEXT: [[Y2:%.*]] = add <4 x i32> [[X2]], [[C2]]
-; CHECK-NEXT: [[Y3:%.*]] = add <4 x i32> [[X3]], [[C3]]
-; CHECK-NEXT: [[Y4:%.*]] = add <4 x i32> [[X4]], [[C4]]
-; CHECK-NEXT: [[CC1:%.*]] = shufflevector <4 x i32> [[Y1]], <4 x i32> [[Y2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 7>
-; CHECK-NEXT: [[CC2:%.*]] = shufflevector <4 x i32> [[Y3]], <4 x i32> [[Y4]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: [[CC1:%.*]] = shufflevector <4 x i32> [[A1A:%.*]], <4 x i32> [[A2A:%.*]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 poison, i32 poison, i32 poison, i32 4>
+; CHECK-NEXT: [[CC2:%.*]] = shufflevector <4 x i32> [[A3A:%.*]], <4 x i32> [[A4A:%.*]], <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
; CHECK-NEXT: [[R:%.*]] = shufflevector <8 x i32> [[CC1]], <8 x i32> [[CC2]], <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: ret <16 x i32> [[R]]
+; CHECK-NEXT: [[TMP4:%.*]] = mul <16 x i32> [[R]], [[B:%.*]]
+; CHECK-NEXT: [[R1:%.*]] = add <16 x i32> [[TMP4]], [[C:%.*]]
+; CHECK-NEXT: ret <16 x i32> [[R1]]
;
%a1 = shufflevector <4 x i32> %a1a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
%a2 = shufflevector <4 x i32> %a2a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
index 5613941cf5726e..8471c36b2b8b7c 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
@@ -63,13 +63,9 @@ define <8 x i8> @wrong_addsub(<8 x i8> %a, <8 x i8> %b) {
; Different lanes that do not make an identity
define <8 x i8> @wrong_lanes(<8 x i8> %a, <8 x i8> %b) {
; CHECK-LABEL: @wrong_lanes(
-; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x i8> [[B:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x i8> [[B]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[ABT:%.*]] = add <4 x i8> [[AT]], [[BT]]
-; CHECK-NEXT: [[ABB:%.*]] = add <4 x i8> [[AB]], [[BB]]
-; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> <i32 6, i32 7, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 0, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[B:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 0, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT: [[R:%.*]] = add <8 x i8> [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret <8 x i8> [[R]]
;
%ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
@@ -261,12 +257,8 @@ define <8 x half> @splatandidentity(<8 x half> %a, <8 x half> %b) {
define <8 x half> @splatandidentity_commuted(<8 x half> %a, <8 x half> %b) {
; CHECK-LABEL: @splatandidentity_commuted(
-; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[BS:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT: [[ABT:%.*]] = fadd <4 x half> [[AT]], [[BS]]
-; CHECK-NEXT: [[ABB:%.*]] = fadd <4 x half> [[BS]], [[AB]]
-; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x half> [[ABT]], <4 x half> [[ABB]], <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <8 x i32> zeroinitializer
+; CHECK-NEXT: [[R:%.*]] = fadd <8 x half> [[TMP1]], [[A]]
; CHECK-NEXT: ret <8 x half> [[R]]
;
%ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
@@ -323,11 +315,7 @@ define <8 x i8> @constantsplat(<8 x i8> %a) {
define <8 x i8> @constantdiff(<8 x i8> %a) {
; CHECK-LABEL: @constantdiff(
-; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[ABT:%.*]] = add <4 x i8> [[AT]], <i8 1, i8 2, i8 3, i8 4>
-; CHECK-NEXT: [[ABB:%.*]] = add <4 x i8> [[AB]], <i8 5, i8 6, i8 7, i8 8>
-; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R:%.*]] = add <8 x i8> [[A:%.*]], <i8 8, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1>
; CHECK-NEXT: ret <8 x i8> [[R]]
;
%ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
@@ -340,11 +328,7 @@ define <8 x i8> @constantdiff(<8 x i8> %a) {
define <8 x i8> @constantdiff2(<8 x i8> %a) {
; CHECK-LABEL: @constantdiff2(
-; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[ABT:%.*]] = add <4 x i8> [[AT]], <i8 1, i8 2, i8 3, i8 4>
-; CHECK-NEXT: [[ABB:%.*]] = add <4 x i8> [[AB]], <i8 1, i8 2, i8 3, i8 4>
-; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R:%.*]] = add <8 x i8> [[A:%.*]], <i8 4, i8 3, i8 2, i8 1, i8 4, i8 3, i8 2, i8 1>
; CHECK-NEXT: ret <8 x i8> [[R]]
;
%ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
@@ -407,13 +391,10 @@ define <4 x i32> @extrause_add_same_operands(<4 x i32> %x) {
define <8 x i8> @extrause_add_different_operands(<8 x i8> %a, <8 x i8> %b) {
; CHECK-LABEL: @extrause_add_different_operands(
; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x i8> [[B:%.*]], <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x i8> [[B]], <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
-; CHECK-NEXT: [[ABT:%.*]] = add <4 x i8> [[AT]], [[BT]]
; CHECK-NEXT: [[ABB:%.*]] = add <4 x i8> [[AB]], [[BB]]
; CHECK-NEXT: call void @use(<4 x i8> [[ABB]])
-; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R:%.*]] = add <8 x i8> [[A]], [[B]]
; CHECK-NEXT: ret <8 x i8> [[R]]
;
%ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
index 8ca6dd358d7e2b..c4f05d61b700b1 100644
--- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
+++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll
@@ -494,11 +494,8 @@ define <8 x i32> @shuf_uniform_const_mul_v8i32_v4i32(<4 x i32> %a0, <4 x i32> %a
define <8 x float> @shuf_fdiv_v4f32_extract_halves_poison(<4 x float> %x, <4 x float> %z, <8 x float> %d) {
; CHECK-LABEL: define <8 x float> @shuf_fdiv_v4f32_extract_halves_poison(
; CHECK-SAME: <4 x float> [[X:%.*]], <4 x float> [[Z:%.*]], <8 x float> [[D:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x float> [[D]], <8 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
-; CHECK-NEXT: [[HI:%.*]] = shufflevector <8 x float> [[D]], <8 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-; CHECK-NEXT: [[L:%.*]] = fdiv <4 x float> [[X]], [[LO]]
-; CHECK-NEXT: [[R:%.*]] = fdiv <4 x float> [[Z]], [[HI]]
-; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[L]], <4 x float> [[R]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 poison>
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X]], <4 x float> [[Z]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 poison>
+; CHECK-NEXT: [[S:%.*]] = fdiv <8 x float> [[TMP1]], [[D]]
; CHECK-NEXT: ret <8 x float> [[S]]
;
%lo = shufflevector <8 x float> %d, <8 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -512,7 +509,7 @@ define <8 x float> @shuf_fdiv_v4f32_extract_halves_poison(<4 x float> %x, <4 x f
define <4 x i32> @shuf_sdiv_v4i32_same_width_permutes_of_same_src(<4 x i32> %a, <4 x i32> %y) {
; CHECK-LABEL: define <4 x i32> @shuf_sdiv_v4i32_same_width_permutes_of_same_src(
; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <4 x i32> <i32 1, i32 0, i32 5, i32 4>
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0>
; CHECK-NEXT: [[S:%.*]] = sdiv <4 x i32> [[Y]], [[TMP1]]
; CHECK-NEXT: ret <4 x i32> [[S]]
;
More information about the llvm-commits
mailing list