[llvm] [WIP][X86] Add custom ISD::VEC_REDUCE_*MIN/MAX support (PR #194848)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 29 06:01:39 PDT 2026
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/194848
Pulled out of #194473 - update combineMinMaxReduction to fold to a ISD::VECREDUCE_SMAX/SMIN/UMAX/UMIN node and then perform the lowering later on.
combineMinMaxReduction will go away once we can use shouldExpandReduction, rely on the middle-end to recognise reductions and not have to recreate them from the expanded patterns.
I've added pre-SSE41 handling using vector unrolling - hopefully this will go away once #194672 is in place.
>From 399cf602ca3273f088cec758fdfb19bc2044736b Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 27 Apr 2026 23:10:12 +0100
Subject: [PATCH] [X86] Add custom ISD::VEC_REDUCE_*MIN/MAX support
Pulled out of #194473 - update combineMinMaxReduction to fold to a ISD::VECREDUCE_SMAX/SMIN/UMAX/UMIN node and then perform the lowering later on.
combineMinMaxReduction will go away once we can use shouldExpandReduction and rely on the middle-end
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 174 +++++++++++++-------
llvm/test/CodeGen/X86/vector-reduce-smax.ll | 56 +++----
llvm/test/CodeGen/X86/vector-reduce-smin.ll | 78 ++++-----
llvm/test/CodeGen/X86/vector-reduce-umax.ll | 28 ++--
llvm/test/CodeGen/X86/vector-reduce-umin.ll | 50 +++---
5 files changed, 224 insertions(+), 162 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6b926b8131db5..78a1dc9e790ce 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -1161,6 +1161,15 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::UMIN, VT, VT == MVT::v16i8 ? Legal : Custom);
}
+ // SSE2 can use basic vector unrolling.
+ // SSE41 can use PHMINPOS to perform v16i8/v8i16 minmax reductions.
+ for (auto VT : {MVT::v16i8, MVT::v8i16}) {
+ setOperationAction(ISD::VECREDUCE_SMAX, VT, Custom);
+ setOperationAction(ISD::VECREDUCE_SMIN, VT, Custom);
+ setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
+ setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
+ }
+
setOperationAction(ISD::UADDSAT, MVT::v16i8, Legal);
setOperationAction(ISD::SADDSAT, MVT::v16i8, Legal);
setOperationAction(ISD::USUBSAT, MVT::v16i8, Legal);
@@ -29826,6 +29835,88 @@ static SDValue LowerMINMAX(SDValue Op, const X86Subtarget &Subtarget,
return SDValue();
}
+// Attempt to replace an min/max v8i16/v16i8 horizontal reduction with
+// PHMINPOSUW.
+static SDValue LowerMINMAX_REDUCE(SDValue Op, const X86Subtarget &Subtarget,
+ SelectionDAG &DAG) {
+ EVT ExtractVT = Op.getValueType();
+ if (ExtractVT != MVT::i16 && ExtractVT != MVT::i8)
+ return SDValue();
+
+ // Check for SMAX/SMIN/UMAX/UMIN horizontal reduction patterns.
+ ISD::NodeType BinOp = ISD::getVecReduceBaseOpcode(Op.getOpcode());
+
+ SDValue Src = Op.getOperand(0);
+ EVT SrcVT = Src.getValueType();
+ EVT SrcSVT = SrcVT.getScalarType();
+ if (SrcSVT != ExtractVT || (SrcVT.getSizeInBits() % 128) != 0)
+ return SDValue();
+
+ SDLoc DL(Op);
+ SDValue MinPos = Src;
+
+ // First, reduce the source down to 128-bit, applying BinOp to lo/hi.
+ while (SrcVT.getSizeInBits() > 128) {
+ SDValue Lo, Hi;
+ std::tie(Lo, Hi) = splitVector(MinPos, DAG, DL);
+ SrcVT = Lo.getValueType();
+ MinPos = DAG.getNode(BinOp, DL, SrcVT, Lo, Hi);
+ }
+ assert(((SrcVT == MVT::v8i16 && ExtractVT == MVT::i16) ||
+ (SrcVT == MVT::v16i8 && ExtractVT == MVT::i8)) &&
+ "Unexpected value type");
+
+ // Without SSE41, we need to unroll.
+ if (!Subtarget.hasSSE41()) {
+ unsigned NumSrcElts = SrcVT.getVectorNumElements();
+ for (unsigned NumElts = NumSrcElts; NumElts != 1; NumElts /= 2) {
+ SmallVector<int, 16> Mask(NumSrcElts, -1);
+ std::iota(Mask.begin(), Mask.begin() + (NumElts / 2), NumElts / 2);
+ SDValue Upper =
+ DAG.getVectorShuffle(SrcVT, DL, MinPos, DAG.getUNDEF(SrcVT), Mask);
+ MinPos = DAG.getNode(BinOp, DL, SrcVT, MinPos, Upper);
+ }
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtractVT, MinPos,
+ DAG.getVectorIdxConstant(0, DL));
+ }
+
+ // PHMINPOSUW applies to UMIN(v8i16), for SMIN/SMAX/UMAX we must apply a mask
+ // to flip the value accordingly.
+ SDValue Mask;
+ unsigned MaskEltsBits = ExtractVT.getSizeInBits();
+ if (BinOp == ISD::SMAX)
+ Mask = DAG.getConstant(APInt::getSignedMaxValue(MaskEltsBits), DL, SrcVT);
+ else if (BinOp == ISD::SMIN)
+ Mask = DAG.getConstant(APInt::getSignedMinValue(MaskEltsBits), DL, SrcVT);
+ else if (BinOp == ISD::UMAX)
+ Mask = DAG.getAllOnesConstant(DL, SrcVT);
+
+ if (Mask)
+ MinPos = DAG.getNode(ISD::XOR, DL, SrcVT, Mask, MinPos);
+
+ // For v16i8 cases we need to perform UMIN on pairs of byte elements,
+ // shuffling each upper element down and insert zeros. This means that the
+ // v16i8 UMIN will leave the upper element as zero, performing zero-extension
+ // ready for the PHMINPOS.
+ if (ExtractVT == MVT::i8) {
+ SDValue Upper = DAG.getVectorShuffle(
+ SrcVT, DL, MinPos, DAG.getConstant(0, DL, MVT::v16i8),
+ {1, 16, 3, 16, 5, 16, 7, 16, 9, 16, 11, 16, 13, 16, 15, 16});
+ MinPos = DAG.getNode(ISD::UMIN, DL, SrcVT, MinPos, Upper);
+ }
+
+ // Perform the PHMINPOS on a v8i16 vector,
+ MinPos = DAG.getBitcast(MVT::v8i16, MinPos);
+ MinPos = DAG.getNode(X86ISD::PHMINPOS, DL, MVT::v8i16, MinPos);
+ MinPos = DAG.getBitcast(SrcVT, MinPos);
+
+ if (Mask)
+ MinPos = DAG.getNode(ISD::XOR, DL, SrcVT, Mask, MinPos);
+
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtractVT, MinPos,
+ DAG.getVectorIdxConstant(0, DL));
+}
+
static SDValue LowerFMINIMUM_FMAXIMUM(SDValue Op, const X86Subtarget &Subtarget,
SelectionDAG &DAG) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
@@ -34385,6 +34476,10 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::SMIN:
case ISD::UMAX:
case ISD::UMIN: return LowerMINMAX(Op, Subtarget, DAG);
+ case ISD::VECREDUCE_SMAX:
+ case ISD::VECREDUCE_SMIN:
+ case ISD::VECREDUCE_UMAX:
+ case ISD::VECREDUCE_UMIN: return LowerMINMAX_REDUCE(Op, Subtarget, DAG);
case ISD::FMINIMUM:
case ISD::FMAXIMUM:
case ISD::FMINIMUMNUM:
@@ -46955,14 +47050,10 @@ static SDValue createPSADBW(SelectionDAG &DAG, SDValue N0, SDValue N1,
PSADBWBuilder);
}
-// Attempt to replace an min/max v8i16/v16i8 horizontal reduction with
-// PHMINPOSUW.
+// Attempt to replace an integer min/max horizontal reduction with
+// ISD::VECREDUCE_SMIN/SMAX/UMIN/UMAX.
static SDValue combineMinMaxReduction(SDNode *Extract, SelectionDAG &DAG,
const X86Subtarget &Subtarget) {
- // Bail without SSE41.
- if (!Subtarget.hasSSE41())
- return SDValue();
-
EVT ExtractVT = Extract->getValueType(0);
if (ExtractVT != MVT::i16 && ExtractVT != MVT::i8)
return SDValue();
@@ -46979,55 +47070,25 @@ static SDValue combineMinMaxReduction(SDNode *Extract, SelectionDAG &DAG,
if (SrcSVT != ExtractVT || (SrcVT.getSizeInBits() % 128) != 0)
return SDValue();
- SDLoc DL(Extract);
- SDValue MinPos = Src;
-
- // First, reduce the source down to 128-bit, applying BinOp to lo/hi.
- while (SrcVT.getSizeInBits() > 128) {
- SDValue Lo, Hi;
- std::tie(Lo, Hi) = splitVector(MinPos, DAG, DL);
- SrcVT = Lo.getValueType();
- MinPos = DAG.getNode(BinOp, DL, SrcVT, Lo, Hi);
- }
- assert(((SrcVT == MVT::v8i16 && ExtractVT == MVT::i16) ||
- (SrcVT == MVT::v16i8 && ExtractVT == MVT::i8)) &&
- "Unexpected value type");
-
- // PHMINPOSUW applies to UMIN(v8i16), for SMIN/SMAX/UMAX we must apply a mask
- // to flip the value accordingly.
- SDValue Mask;
- unsigned MaskEltsBits = ExtractVT.getSizeInBits();
- if (BinOp == ISD::SMAX)
- Mask = DAG.getConstant(APInt::getSignedMaxValue(MaskEltsBits), DL, SrcVT);
- else if (BinOp == ISD::SMIN)
- Mask = DAG.getConstant(APInt::getSignedMinValue(MaskEltsBits), DL, SrcVT);
- else if (BinOp == ISD::UMAX)
- Mask = DAG.getAllOnesConstant(DL, SrcVT);
-
- if (Mask)
- MinPos = DAG.getNode(ISD::XOR, DL, SrcVT, Mask, MinPos);
-
- // For v16i8 cases we need to perform UMIN on pairs of byte elements,
- // shuffling each upper element down and insert zeros. This means that the
- // v16i8 UMIN will leave the upper element as zero, performing zero-extension
- // ready for the PHMINPOS.
- if (ExtractVT == MVT::i8) {
- SDValue Upper = DAG.getVectorShuffle(
- SrcVT, DL, MinPos, DAG.getConstant(0, DL, MVT::v16i8),
- {1, 16, 3, 16, 5, 16, 7, 16, 9, 16, 11, 16, 13, 16, 15, 16});
- MinPos = DAG.getNode(ISD::UMIN, DL, SrcVT, MinPos, Upper);
+ ISD::NodeType RdxOp;
+ switch (BinOp) {
+ case ISD::SMAX:
+ RdxOp = ISD::VECREDUCE_SMAX;
+ break;
+ case ISD::SMIN:
+ RdxOp = ISD::VECREDUCE_SMIN;
+ break;
+ case ISD::UMAX:
+ RdxOp = ISD::VECREDUCE_UMAX;
+ break;
+ case ISD::UMIN:
+ RdxOp = ISD::VECREDUCE_UMIN;
+ break;
+ default:
+ llvm_unreachable("Unexpected reduction");
}
- // Perform the PHMINPOS on a v8i16 vector,
- MinPos = DAG.getBitcast(MVT::v8i16, MinPos);
- MinPos = DAG.getNode(X86ISD::PHMINPOS, DL, MVT::v8i16, MinPos);
- MinPos = DAG.getBitcast(SrcVT, MinPos);
-
- if (Mask)
- MinPos = DAG.getNode(ISD::XOR, DL, SrcVT, Mask, MinPos);
-
- return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtractVT, MinPos,
- DAG.getVectorIdxConstant(0, DL));
+ return DAG.getNode(RdxOp, SDLoc(Extract), ExtractVT, Src);
}
// Attempt to replace an all_of/any_of/parity style horizontal reduction with a MOVMSK.
@@ -47982,9 +48043,10 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG,
if (SDValue Cmp = combinePredicateReduction(N, DAG, Subtarget))
return Cmp;
- // Attempt to replace min/max v8i16/v16i8 reductions with PHMINPOSUW.
- if (SDValue MinMax = combineMinMaxReduction(N, DAG, Subtarget))
- return MinMax;
+ // Attempt to replace min/max v8i16/v16i8 reductions with ISD::VECREDUCE.
+ if (DCI.isBeforeLegalizeOps())
+ if (SDValue MinMax = combineMinMaxReduction(N, DAG, Subtarget))
+ return MinMax;
// Attempt to optimize ADD/FADD/MUL reductions with HADD, promotion etc..
if (SDValue V = combineArithReduction(N, DAG, Subtarget))
diff --git a/llvm/test/CodeGen/X86/vector-reduce-smax.ll b/llvm/test/CodeGen/X86/vector-reduce-smax.ll
index 95aea6f524023..fdf394e14eeef 100644
--- a/llvm/test/CodeGen/X86/vector-reduce-smax.ll
+++ b/llvm/test/CodeGen/X86/vector-reduce-smax.ll
@@ -1426,21 +1426,21 @@ define i16 @test_v32i16(<32 x i16> %a0) {
define i16 @test_v64i16(<64 x i16> %a0) {
; SSE2-LABEL: test_v64i16:
; SSE2: # %bb.0:
-; SSE2-NEXT: pmaxsw %xmm6, %xmm2
-; SSE2-NEXT: pmaxsw %xmm4, %xmm0
-; SSE2-NEXT: pmaxsw %xmm2, %xmm0
; SSE2-NEXT: pmaxsw %xmm7, %xmm3
; SSE2-NEXT: pmaxsw %xmm5, %xmm1
; SSE2-NEXT: pmaxsw %xmm3, %xmm1
-; SSE2-NEXT: pmaxsw %xmm0, %xmm1
-; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
+; SSE2-NEXT: pmaxsw %xmm6, %xmm2
+; SSE2-NEXT: pmaxsw %xmm4, %xmm0
+; SSE2-NEXT: pmaxsw %xmm2, %xmm0
; SSE2-NEXT: pmaxsw %xmm1, %xmm0
-; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1]
+; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
; SSE2-NEXT: pmaxsw %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm1, %xmm0
-; SSE2-NEXT: psrld $16, %xmm0
+; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1]
; SSE2-NEXT: pmaxsw %xmm1, %xmm0
-; SSE2-NEXT: movd %xmm0, %eax
+; SSE2-NEXT: movdqa %xmm0, %xmm1
+; SSE2-NEXT: psrld $16, %xmm1
+; SSE2-NEXT: pmaxsw %xmm0, %xmm1
+; SSE2-NEXT: movd %xmm1, %eax
; SSE2-NEXT: # kill: def $ax killed $ax killed $eax
; SSE2-NEXT: retq
;
@@ -2023,35 +2023,35 @@ define i8 @test_v64i8(<64 x i8> %a0) {
define i8 @test_v128i8(<128 x i8> %a0) {
; SSE2-LABEL: test_v128i8:
; SSE2: # %bb.0:
-; SSE2-NEXT: movdqa %xmm2, %xmm8
-; SSE2-NEXT: pcmpgtb %xmm6, %xmm8
-; SSE2-NEXT: pand %xmm8, %xmm2
-; SSE2-NEXT: pandn %xmm6, %xmm8
-; SSE2-NEXT: por %xmm2, %xmm8
-; SSE2-NEXT: movdqa %xmm0, %xmm2
-; SSE2-NEXT: pcmpgtb %xmm4, %xmm2
-; SSE2-NEXT: pand %xmm2, %xmm0
-; SSE2-NEXT: pandn %xmm4, %xmm2
-; SSE2-NEXT: por %xmm0, %xmm2
-; SSE2-NEXT: movdqa %xmm3, %xmm0
-; SSE2-NEXT: pcmpgtb %xmm7, %xmm0
-; SSE2-NEXT: pand %xmm0, %xmm3
-; SSE2-NEXT: pandn %xmm7, %xmm0
-; SSE2-NEXT: por %xmm3, %xmm0
+; SSE2-NEXT: movdqa %xmm3, %xmm8
+; SSE2-NEXT: pcmpgtb %xmm7, %xmm8
+; SSE2-NEXT: pand %xmm8, %xmm3
+; SSE2-NEXT: pandn %xmm7, %xmm8
+; SSE2-NEXT: por %xmm3, %xmm8
; SSE2-NEXT: movdqa %xmm1, %xmm3
; SSE2-NEXT: pcmpgtb %xmm5, %xmm3
; SSE2-NEXT: pand %xmm3, %xmm1
; SSE2-NEXT: pandn %xmm5, %xmm3
; SSE2-NEXT: por %xmm1, %xmm3
; SSE2-NEXT: movdqa %xmm3, %xmm1
-; SSE2-NEXT: pcmpgtb %xmm0, %xmm1
+; SSE2-NEXT: pcmpgtb %xmm8, %xmm1
; SSE2-NEXT: pand %xmm1, %xmm3
-; SSE2-NEXT: pandn %xmm0, %xmm1
+; SSE2-NEXT: pandn %xmm8, %xmm1
; SSE2-NEXT: por %xmm3, %xmm1
+; SSE2-NEXT: movdqa %xmm2, %xmm3
+; SSE2-NEXT: pcmpgtb %xmm6, %xmm3
+; SSE2-NEXT: pand %xmm3, %xmm2
+; SSE2-NEXT: pandn %xmm6, %xmm3
+; SSE2-NEXT: por %xmm2, %xmm3
+; SSE2-NEXT: movdqa %xmm0, %xmm2
+; SSE2-NEXT: pcmpgtb %xmm4, %xmm2
+; SSE2-NEXT: pand %xmm2, %xmm0
+; SSE2-NEXT: pandn %xmm4, %xmm2
+; SSE2-NEXT: por %xmm0, %xmm2
; SSE2-NEXT: movdqa %xmm2, %xmm0
-; SSE2-NEXT: pcmpgtb %xmm8, %xmm0
+; SSE2-NEXT: pcmpgtb %xmm3, %xmm0
; SSE2-NEXT: pand %xmm0, %xmm2
-; SSE2-NEXT: pandn %xmm8, %xmm0
+; SSE2-NEXT: pandn %xmm3, %xmm0
; SSE2-NEXT: por %xmm2, %xmm0
; SSE2-NEXT: movdqa %xmm0, %xmm2
; SSE2-NEXT: pcmpgtb %xmm1, %xmm2
diff --git a/llvm/test/CodeGen/X86/vector-reduce-smin.ll b/llvm/test/CodeGen/X86/vector-reduce-smin.ll
index f86d3c1dd6e3f..84bbf6c8c03db 100644
--- a/llvm/test/CodeGen/X86/vector-reduce-smin.ll
+++ b/llvm/test/CodeGen/X86/vector-reduce-smin.ll
@@ -1427,21 +1427,21 @@ define i16 @test_v32i16(<32 x i16> %a0) {
define i16 @test_v64i16(<64 x i16> %a0) {
; SSE2-LABEL: test_v64i16:
; SSE2: # %bb.0:
-; SSE2-NEXT: pminsw %xmm6, %xmm2
-; SSE2-NEXT: pminsw %xmm4, %xmm0
-; SSE2-NEXT: pminsw %xmm2, %xmm0
; SSE2-NEXT: pminsw %xmm7, %xmm3
; SSE2-NEXT: pminsw %xmm5, %xmm1
; SSE2-NEXT: pminsw %xmm3, %xmm1
-; SSE2-NEXT: pminsw %xmm0, %xmm1
-; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
+; SSE2-NEXT: pminsw %xmm6, %xmm2
+; SSE2-NEXT: pminsw %xmm4, %xmm0
+; SSE2-NEXT: pminsw %xmm2, %xmm0
; SSE2-NEXT: pminsw %xmm1, %xmm0
-; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1]
+; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
; SSE2-NEXT: pminsw %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm1, %xmm0
-; SSE2-NEXT: psrld $16, %xmm0
+; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1]
; SSE2-NEXT: pminsw %xmm1, %xmm0
-; SSE2-NEXT: movd %xmm0, %eax
+; SSE2-NEXT: movdqa %xmm0, %xmm1
+; SSE2-NEXT: psrld $16, %xmm1
+; SSE2-NEXT: pminsw %xmm0, %xmm1
+; SSE2-NEXT: movd %xmm1, %eax
; SSE2-NEXT: # kill: def $ax killed $ax killed $eax
; SSE2-NEXT: retq
;
@@ -2024,41 +2024,41 @@ define i8 @test_v64i8(<64 x i8> %a0) {
define i8 @test_v128i8(<128 x i8> %a0) {
; SSE2-LABEL: test_v128i8:
; SSE2: # %bb.0:
-; SSE2-NEXT: movdqa %xmm5, %xmm8
-; SSE2-NEXT: pcmpgtb %xmm1, %xmm8
-; SSE2-NEXT: pand %xmm8, %xmm1
-; SSE2-NEXT: pandn %xmm5, %xmm8
-; SSE2-NEXT: por %xmm1, %xmm8
+; SSE2-NEXT: movdqa %xmm4, %xmm8
+; SSE2-NEXT: pcmpgtb %xmm0, %xmm8
+; SSE2-NEXT: pand %xmm8, %xmm0
+; SSE2-NEXT: pandn %xmm4, %xmm8
+; SSE2-NEXT: por %xmm0, %xmm8
+; SSE2-NEXT: movdqa %xmm6, %xmm4
+; SSE2-NEXT: pcmpgtb %xmm2, %xmm4
+; SSE2-NEXT: pand %xmm4, %xmm2
+; SSE2-NEXT: pandn %xmm6, %xmm4
+; SSE2-NEXT: por %xmm2, %xmm4
+; SSE2-NEXT: movdqa %xmm4, %xmm0
+; SSE2-NEXT: pcmpgtb %xmm8, %xmm0
+; SSE2-NEXT: pand %xmm0, %xmm8
+; SSE2-NEXT: pandn %xmm4, %xmm0
+; SSE2-NEXT: por %xmm8, %xmm0
+; SSE2-NEXT: movdqa %xmm5, %xmm2
+; SSE2-NEXT: pcmpgtb %xmm1, %xmm2
+; SSE2-NEXT: pand %xmm2, %xmm1
+; SSE2-NEXT: pandn %xmm5, %xmm2
+; SSE2-NEXT: por %xmm1, %xmm2
; SSE2-NEXT: movdqa %xmm7, %xmm1
; SSE2-NEXT: pcmpgtb %xmm3, %xmm1
; SSE2-NEXT: pand %xmm1, %xmm3
; SSE2-NEXT: pandn %xmm7, %xmm1
; SSE2-NEXT: por %xmm3, %xmm1
-; SSE2-NEXT: movdqa %xmm4, %xmm3
-; SSE2-NEXT: pcmpgtb %xmm0, %xmm3
-; SSE2-NEXT: pand %xmm3, %xmm0
-; SSE2-NEXT: pandn %xmm4, %xmm3
-; SSE2-NEXT: por %xmm0, %xmm3
-; SSE2-NEXT: movdqa %xmm6, %xmm0
-; SSE2-NEXT: pcmpgtb %xmm2, %xmm0
-; SSE2-NEXT: pand %xmm0, %xmm2
-; SSE2-NEXT: pandn %xmm6, %xmm0
-; SSE2-NEXT: por %xmm2, %xmm0
-; SSE2-NEXT: movdqa %xmm0, %xmm2
-; SSE2-NEXT: pcmpgtb %xmm3, %xmm2
-; SSE2-NEXT: pand %xmm2, %xmm3
-; SSE2-NEXT: pandn %xmm0, %xmm2
-; SSE2-NEXT: por %xmm3, %xmm2
-; SSE2-NEXT: movdqa %xmm1, %xmm0
-; SSE2-NEXT: pcmpgtb %xmm8, %xmm0
-; SSE2-NEXT: pand %xmm0, %xmm8
-; SSE2-NEXT: pandn %xmm1, %xmm0
-; SSE2-NEXT: por %xmm8, %xmm0
-; SSE2-NEXT: movdqa %xmm0, %xmm1
-; SSE2-NEXT: pcmpgtb %xmm2, %xmm1
-; SSE2-NEXT: pand %xmm1, %xmm2
-; SSE2-NEXT: pandn %xmm0, %xmm1
-; SSE2-NEXT: por %xmm2, %xmm1
+; SSE2-NEXT: movdqa %xmm1, %xmm3
+; SSE2-NEXT: pcmpgtb %xmm2, %xmm3
+; SSE2-NEXT: pand %xmm3, %xmm2
+; SSE2-NEXT: pandn %xmm1, %xmm3
+; SSE2-NEXT: por %xmm2, %xmm3
+; SSE2-NEXT: movdqa %xmm3, %xmm1
+; SSE2-NEXT: pcmpgtb %xmm0, %xmm1
+; SSE2-NEXT: pand %xmm1, %xmm0
+; SSE2-NEXT: pandn %xmm3, %xmm1
+; SSE2-NEXT: por %xmm0, %xmm1
; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
; SSE2-NEXT: movdqa %xmm0, %xmm2
; SSE2-NEXT: pcmpgtb %xmm1, %xmm2
diff --git a/llvm/test/CodeGen/X86/vector-reduce-umax.ll b/llvm/test/CodeGen/X86/vector-reduce-umax.ll
index 2f3c1e09ea78e..588053cd05379 100644
--- a/llvm/test/CodeGen/X86/vector-reduce-umax.ll
+++ b/llvm/test/CodeGen/X86/vector-reduce-umax.ll
@@ -1648,16 +1648,16 @@ define i16 @test_v32i16(<32 x i16> %a0) {
define i16 @test_v64i16(<64 x i16> %a0) {
; SSE2-LABEL: test_v64i16:
; SSE2: # %bb.0:
-; SSE2-NEXT: psubusw %xmm1, %xmm5
-; SSE2-NEXT: paddw %xmm1, %xmm5
-; SSE2-NEXT: psubusw %xmm3, %xmm7
-; SSE2-NEXT: paddw %xmm3, %xmm7
; SSE2-NEXT: psubusw %xmm0, %xmm4
; SSE2-NEXT: paddw %xmm0, %xmm4
; SSE2-NEXT: psubusw %xmm2, %xmm6
; SSE2-NEXT: paddw %xmm2, %xmm6
; SSE2-NEXT: psubusw %xmm4, %xmm6
; SSE2-NEXT: paddw %xmm4, %xmm6
+; SSE2-NEXT: psubusw %xmm1, %xmm5
+; SSE2-NEXT: paddw %xmm1, %xmm5
+; SSE2-NEXT: psubusw %xmm3, %xmm7
+; SSE2-NEXT: paddw %xmm3, %xmm7
; SSE2-NEXT: psubusw %xmm5, %xmm7
; SSE2-NEXT: paddw %xmm5, %xmm7
; SSE2-NEXT: psubusw %xmm6, %xmm7
@@ -2145,24 +2145,24 @@ define i8 @test_v64i8(<64 x i8> %a0) {
define i8 @test_v128i8(<128 x i8> %a0) {
; SSE2-LABEL: test_v128i8:
; SSE2: # %bb.0:
-; SSE2-NEXT: pmaxub %xmm6, %xmm2
-; SSE2-NEXT: pmaxub %xmm4, %xmm0
-; SSE2-NEXT: pmaxub %xmm2, %xmm0
; SSE2-NEXT: pmaxub %xmm7, %xmm3
; SSE2-NEXT: pmaxub %xmm5, %xmm1
; SSE2-NEXT: pmaxub %xmm3, %xmm1
-; SSE2-NEXT: pmaxub %xmm0, %xmm1
-; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
+; SSE2-NEXT: pmaxub %xmm6, %xmm2
+; SSE2-NEXT: pmaxub %xmm4, %xmm0
+; SSE2-NEXT: pmaxub %xmm2, %xmm0
; SSE2-NEXT: pmaxub %xmm1, %xmm0
-; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1]
+; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
; SSE2-NEXT: pmaxub %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm1, %xmm0
-; SSE2-NEXT: psrld $16, %xmm0
+; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1]
; SSE2-NEXT: pmaxub %xmm1, %xmm0
; SSE2-NEXT: movdqa %xmm0, %xmm1
-; SSE2-NEXT: psrlw $8, %xmm1
+; SSE2-NEXT: psrld $16, %xmm1
; SSE2-NEXT: pmaxub %xmm0, %xmm1
-; SSE2-NEXT: movd %xmm1, %eax
+; SSE2-NEXT: movdqa %xmm1, %xmm0
+; SSE2-NEXT: psrlw $8, %xmm0
+; SSE2-NEXT: pmaxub %xmm1, %xmm0
+; SSE2-NEXT: movd %xmm0, %eax
; SSE2-NEXT: # kill: def $al killed $al killed $eax
; SSE2-NEXT: retq
;
diff --git a/llvm/test/CodeGen/X86/vector-reduce-umin.ll b/llvm/test/CodeGen/X86/vector-reduce-umin.ll
index dc8d0d53a91a1..ce2175637781c 100644
--- a/llvm/test/CodeGen/X86/vector-reduce-umin.ll
+++ b/llvm/test/CodeGen/X86/vector-reduce-umin.ll
@@ -1602,21 +1602,21 @@ define i16 @test_v32i16(<32 x i16> %a0) {
define i16 @test_v64i16(<64 x i16> %a0) {
; SSE2-LABEL: test_v64i16:
; SSE2: # %bb.0:
-; SSE2-NEXT: movdqa %xmm2, %xmm8
-; SSE2-NEXT: psubusw %xmm6, %xmm8
-; SSE2-NEXT: psubw %xmm8, %xmm2
-; SSE2-NEXT: movdqa %xmm0, %xmm6
-; SSE2-NEXT: psubusw %xmm4, %xmm6
-; SSE2-NEXT: psubw %xmm6, %xmm0
-; SSE2-NEXT: movdqa %xmm3, %xmm4
-; SSE2-NEXT: psubusw %xmm7, %xmm4
-; SSE2-NEXT: psubw %xmm4, %xmm3
-; SSE2-NEXT: movdqa %xmm1, %xmm4
-; SSE2-NEXT: psubusw %xmm5, %xmm4
-; SSE2-NEXT: psubw %xmm4, %xmm1
-; SSE2-NEXT: movdqa %xmm1, %xmm4
-; SSE2-NEXT: psubusw %xmm3, %xmm4
-; SSE2-NEXT: psubw %xmm4, %xmm1
+; SSE2-NEXT: movdqa %xmm3, %xmm8
+; SSE2-NEXT: psubusw %xmm7, %xmm8
+; SSE2-NEXT: psubw %xmm8, %xmm3
+; SSE2-NEXT: movdqa %xmm1, %xmm7
+; SSE2-NEXT: psubusw %xmm5, %xmm7
+; SSE2-NEXT: psubw %xmm7, %xmm1
+; SSE2-NEXT: movdqa %xmm1, %xmm5
+; SSE2-NEXT: psubusw %xmm3, %xmm5
+; SSE2-NEXT: psubw %xmm5, %xmm1
+; SSE2-NEXT: movdqa %xmm2, %xmm3
+; SSE2-NEXT: psubusw %xmm6, %xmm3
+; SSE2-NEXT: psubw %xmm3, %xmm2
+; SSE2-NEXT: movdqa %xmm0, %xmm3
+; SSE2-NEXT: psubusw %xmm4, %xmm3
+; SSE2-NEXT: psubw %xmm3, %xmm0
; SSE2-NEXT: movdqa %xmm0, %xmm3
; SSE2-NEXT: psubusw %xmm2, %xmm3
; SSE2-NEXT: psubw %xmm3, %xmm0
@@ -2010,24 +2010,24 @@ define i8 @test_v64i8(<64 x i8> %a0) {
define i8 @test_v128i8(<128 x i8> %a0) {
; SSE2-LABEL: test_v128i8:
; SSE2: # %bb.0:
-; SSE2-NEXT: pminub %xmm6, %xmm2
-; SSE2-NEXT: pminub %xmm4, %xmm0
-; SSE2-NEXT: pminub %xmm2, %xmm0
; SSE2-NEXT: pminub %xmm7, %xmm3
; SSE2-NEXT: pminub %xmm5, %xmm1
; SSE2-NEXT: pminub %xmm3, %xmm1
-; SSE2-NEXT: pminub %xmm0, %xmm1
-; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3]
+; SSE2-NEXT: pminub %xmm6, %xmm2
+; SSE2-NEXT: pminub %xmm4, %xmm0
+; SSE2-NEXT: pminub %xmm2, %xmm0
; SSE2-NEXT: pminub %xmm1, %xmm0
-; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1]
+; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
; SSE2-NEXT: pminub %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm1, %xmm0
-; SSE2-NEXT: psrld $16, %xmm0
+; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1]
; SSE2-NEXT: pminub %xmm1, %xmm0
; SSE2-NEXT: movdqa %xmm0, %xmm1
-; SSE2-NEXT: psrlw $8, %xmm1
+; SSE2-NEXT: psrld $16, %xmm1
; SSE2-NEXT: pminub %xmm0, %xmm1
-; SSE2-NEXT: movd %xmm1, %eax
+; SSE2-NEXT: movdqa %xmm1, %xmm0
+; SSE2-NEXT: psrlw $8, %xmm0
+; SSE2-NEXT: pminub %xmm1, %xmm0
+; SSE2-NEXT: movd %xmm0, %eax
; SSE2-NEXT: # kill: def $al killed $al killed $eax
; SSE2-NEXT: retq
;
More information about the llvm-commits
mailing list