[llvm] [VectorCombine] Merge permutes of the same source in foldShuffleOfBinops (PR #228472)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 07:56:13 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Weiwen He (he-weiwen)
<details>
<summary>Changes</summary>
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` .
---
Patch is 24.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/228472.diff
6 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/VectorCombine.cpp (+54-3)
- (modified) llvm/test/Transforms/PhaseOrdering/X86/hadd.ll (+6-14)
- (modified) llvm/test/Transforms/PhaseOrdering/X86/hsub.ll (+6-14)
- (modified) llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity-concat.ll (+5-23)
- (modified) llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll (+21-21)
- (modified) llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll (+72)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index d16a3a1535cb75b..46650a22e378802 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 70a84d14bd6cf9c..5c8b0c4e100f879 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 966e8ca62e9ec9c..fa1496660d93fd0 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 b88bdae4a335a68..f2910862f2e92be 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 9364b4efa89311e..8471c36b2b8b7c7 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>
@@ -259,6 +255,21 @@ 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: [[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>
+ %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
@@ -304,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>
@@ -321,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>
@@ -388,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...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/228472
More information about the llvm-commits
mailing list