diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 97e783c09f0f2..f717a0b222bb9 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -50910,6 +50910,38 @@ static SDValue combineShiftRightLogical(SDNode *N, SelectionDAG &DAG, } } + // VectorCombine may have folded: + // icmp_eq(vecreduce_or(splatsign(x)),0) --> icmp_sgt(vecreduce_umax(x),-1) + // which DAG folds to: srl(vecreduce_umax(x),bw-1). + // This attempts to reconstruct the signbit reduction. + if (sd_match(N1, m_SpecificInt(EltSizeInBits - 1))) { + SDValue X = N0; + ISD::CondCode CC = ISD::SETNE; + if (sd_match(N0, m_Not(m_Value(X)))) + CC = ISD::SETEQ; + if (X.getOpcode() == ISD::VECREDUCE_UMAX) { + SDValue V = X.getOperand(0); + EVT VecVT = V.getValueType(); + if (DAG.getTargetLoweringInfo().isTypeLegal(VecVT) && + VecVT.getScalarSizeInBits() >= 8) { + if (VecVT.is512BitVector()) { + auto [Lo, Hi] = DAG.SplitVector(V, DL); + V = DAG.getNode(ISD::OR, DL, Lo.getValueType(), Lo, Hi); + VecVT = V.getValueType(); + } + if (VecVT == MVT::v16i16) { + auto [Lo, Hi] = DAG.SplitVector(V, DL); + V = DAG.getNode(X86ISD::PACKSS, DL, MVT::v16i8, Lo, Hi); + } else if (VecVT == MVT::v8i16) { + V = DAG.getNode(X86ISD::PACKSS, DL, MVT::v16i8, V, V); + } + V = getPMOVMSKB(DL, V, DAG, Subtarget); + V = DAG.getSetCC(DL, MVT::i8, V, DAG.getConstant(0, DL, MVT::i32), CC); + return DAG.getZExtOrTrunc(V, DL, VT); + } + } + } + // Only do this on the last DAG combine as it can interfere with other // combines. if (!DCI.isAfterLegalizeDAG()) diff --git a/llvm/test/CodeGen/X86/pr209714.ll b/llvm/test/CodeGen/X86/pr209714.ll new file mode 100644 index 0000000000000..9a487696bb847 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr209714.ll @@ -0,0 +1,1407 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-- -mattr=+sse2 | FileCheck %s --check-prefixes=X86-SSE,X86-SSE2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=X64-SSE,X64-SSE2 +; RUN: llc < %s -mtriple=i686-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=X86-SSE,X86-SSE4,X86-SSE41 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=X64-SSE,X64-SSE4 +; RUN: llc < %s -mtriple=i686-- -mattr=+sse4.2 | FileCheck %s --check-prefixes=X86-SSE,X86-SSE4,X86-SSE42 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.2 | FileCheck %s --check-prefixes=X64-SSE,X64-SSE4 +; RUN: llc < %s -mtriple=i686-- -mattr=+avx | FileCheck %s --check-prefixes=X86-AVX,X86-AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefixes=X64-AVX,X64-AVX1 +; RUN: llc < %s -mtriple=i686-- -mattr=+avx2 | FileCheck %s --check-prefixes=X86-AVX,X86-AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=X64-AVX,X64-AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512bw | FileCheck %s --check-prefixes=AVX512,AVX512BW +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512bw,+avx512dq,+avx512vl | FileCheck %s --check-prefixes=AVX512,AVX512BWVL + +; Ensure umax reductions which only demand the signbit correctly fold to MOVSMSK/TESTP style patterns. + +define i8 @reduce_umax_v16i8_signbit(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v16i8_signbit: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE-NEXT: pand (%eax), %xmm0 +; X86-SSE-NEXT: pmovmskb %xmm0, %eax +; X86-SSE-NEXT: testl %eax, %eax +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v16i8_signbit: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movdqa (%rsi), %xmm0 +; X64-SSE-NEXT: pand (%rdi), %xmm0 +; X64-SSE-NEXT: pmovmskb %xmm0, %eax +; X64-SSE-NEXT: testl %eax, %eax +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v16i8_signbit: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: vmovdqa (%ecx), %xmm0 +; X86-AVX-NEXT: vpand (%eax), %xmm0, %xmm0 +; X86-AVX-NEXT: vpmovmskb %xmm0, %eax +; X86-AVX-NEXT: testl %eax, %eax +; X86-AVX-NEXT: sete %al +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v16i8_signbit: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqa (%rsi), %xmm0 +; X64-AVX-NEXT: vpand (%rdi), %xmm0, %xmm0 +; X64-AVX-NEXT: vpmovmskb %xmm0, %eax +; X64-AVX-NEXT: testl %eax, %eax +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v16i8_signbit: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa (%rsi), %xmm0 +; AVX512-NEXT: vpand (%rdi), %xmm0, %xmm0 +; AVX512-NEXT: vpmovmskb %xmm0, %eax +; AVX512-NEXT: testl %eax, %eax +; AVX512-NEXT: sete %al +; AVX512-NEXT: retq + %a = load <16 x i8>, ptr %pa + %b = load <16 x i8>, ptr %pb + %and = and <16 x i8> %b, %a + %rdx = call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %and) + %cmp = icmp sgt i8 %rdx, -1 + %res = zext i1 %cmp to i8 + ret i8 %res +} + +define i16 @reduce_umax_v8i16_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v8i16_signbit_not: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE-NEXT: pandn (%eax), %xmm0 +; X86-SSE-NEXT: packsswb %xmm0, %xmm0 +; X86-SSE-NEXT: pmovmskb %xmm0, %ecx +; X86-SSE-NEXT: xorl %eax, %eax +; X86-SSE-NEXT: testl %ecx, %ecx +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: # kill: def $ax killed $ax killed $eax +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v8i16_signbit_not: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movdqa (%rdi), %xmm0 +; X64-SSE-NEXT: pandn (%rsi), %xmm0 +; X64-SSE-NEXT: packsswb %xmm0, %xmm0 +; X64-SSE-NEXT: pmovmskb %xmm0, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v8i16_signbit_not: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: vmovdqa (%ecx), %xmm0 +; X86-AVX-NEXT: vpandn (%eax), %xmm0, %xmm0 +; X86-AVX-NEXT: vpacksswb %xmm0, %xmm0, %xmm0 +; X86-AVX-NEXT: vpmovmskb %xmm0, %ecx +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: testl %ecx, %ecx +; X86-AVX-NEXT: sete %al +; X86-AVX-NEXT: # kill: def $ax killed $ax killed $eax +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v8i16_signbit_not: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqa (%rdi), %xmm0 +; X64-AVX-NEXT: vpandn (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vpacksswb %xmm0, %xmm0, %xmm0 +; X64-AVX-NEXT: vpmovmskb %xmm0, %ecx +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: testl %ecx, %ecx +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: # kill: def $ax killed $ax killed $eax +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v8i16_signbit_not: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-NEXT: vpandn (%rsi), %xmm0, %xmm0 +; AVX512-NEXT: vpacksswb %xmm0, %xmm0, %xmm0 +; AVX512-NEXT: vpmovmskb %xmm0, %ecx +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: testl %ecx, %ecx +; AVX512-NEXT: sete %al +; AVX512-NEXT: # kill: def $ax killed $ax killed $eax +; AVX512-NEXT: retq + %a = load <8 x i16>, ptr %pa + %b = load <8 x i16>, ptr %pb + %a.not = xor <8 x i16> %a, splat (i16 -1) + %and = and <8 x i16> %b, %a.not + %rdx = call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %and) + %cmp = icmp sgt i16 %rdx, -1 + %res = zext i1 %cmp to i16 + ret i16 %res +} + +define i32 @reduce_umax_v4i32_signbit(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v4i32_signbit: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movaps (%ecx), %xmm0 +; X86-SSE-NEXT: andps (%eax), %xmm0 +; X86-SSE-NEXT: movmskps %xmm0, %ecx +; X86-SSE-NEXT: xorl %eax, %eax +; X86-SSE-NEXT: testl %ecx, %ecx +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v4i32_signbit: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movaps (%rsi), %xmm0 +; X64-SSE-NEXT: andps (%rdi), %xmm0 +; X64-SSE-NEXT: movmskps %xmm0, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v4i32_signbit: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: vmovaps (%eax), %xmm0 +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: vtestps (%ecx), %xmm0 +; X86-AVX-NEXT: sete %al +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v4i32_signbit: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovaps (%rdi), %xmm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestps (%rsi), %xmm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v4i32_signbit: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovaps (%rdi), %xmm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vtestps (%rsi), %xmm0 +; AVX512-NEXT: sete %al +; AVX512-NEXT: retq + %a = load <4 x i32>, ptr %pa + %b = load <4 x i32>, ptr %pb + %and = and <4 x i32> %b, %a + %rdx = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %and) + %cmp = icmp sgt i32 %rdx, -1 + %res = zext i1 %cmp to i32 + ret i32 %res +} + +define i64 @reduce_umax_v2i64_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v2i64_signbit_not: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movapd (%ecx), %xmm0 +; X86-SSE-NEXT: andnpd (%eax), %xmm0 +; X86-SSE-NEXT: movmskpd %xmm0, %ecx +; X86-SSE-NEXT: xorl %eax, %eax +; X86-SSE-NEXT: testl %ecx, %ecx +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: xorl %edx, %edx +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v2i64_signbit_not: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movapd (%rdi), %xmm0 +; X64-SSE-NEXT: andnpd (%rsi), %xmm0 +; X64-SSE-NEXT: movmskpd %xmm0, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v2i64_signbit_not: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: vmovapd (%eax), %xmm0 +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: vtestpd (%ecx), %xmm0 +; X86-AVX-NEXT: setb %al +; X86-AVX-NEXT: xorl %edx, %edx +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v2i64_signbit_not: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovapd (%rdi), %xmm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestpd (%rsi), %xmm0 +; X64-AVX-NEXT: setb %al +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v2i64_signbit_not: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovapd (%rdi), %xmm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vtestpd (%rsi), %xmm0 +; AVX512-NEXT: setb %al +; AVX512-NEXT: retq + %a = load <2 x i64>, ptr %pa + %b = load <2 x i64>, ptr %pb + %a.not = xor <2 x i64> %a, splat (i64 -1) + %and = and <2 x i64> %b, %a.not + %rdx = call i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> %and) + %cmp = icmp sgt i64 %rdx, -1 + %res = zext i1 %cmp to i64 + ret i64 %res +} + +define i8 @reduce_umax_v32i8_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v32i8_signbit_not: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE-NEXT: pandn 16(%eax), %xmm1 +; X86-SSE-NEXT: pandn (%eax), %xmm0 +; X86-SSE-NEXT: por %xmm1, %xmm0 +; X86-SSE-NEXT: pmovmskb %xmm0, %eax +; X86-SSE-NEXT: testl %eax, %eax +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v32i8_signbit_not: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movdqa (%rdi), %xmm0 +; X64-SSE-NEXT: movdqa 16(%rdi), %xmm1 +; X64-SSE-NEXT: pandn 16(%rsi), %xmm1 +; X64-SSE-NEXT: pandn (%rsi), %xmm0 +; X64-SSE-NEXT: por %xmm1, %xmm0 +; X64-SSE-NEXT: pmovmskb %xmm0, %eax +; X64-SSE-NEXT: testl %eax, %eax +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX1-LABEL: reduce_umax_v32i8_signbit_not: +; X86-AVX1: # %bb.0: +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX1-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX1-NEXT: vandnps (%eax), %ymm0, %ymm0 +; X86-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 +; X86-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X86-AVX1-NEXT: vpmovmskb %xmm0, %eax +; X86-AVX1-NEXT: testl %eax, %eax +; X86-AVX1-NEXT: sete %al +; X86-AVX1-NEXT: vzeroupper +; X86-AVX1-NEXT: retl +; +; X64-AVX1-LABEL: reduce_umax_v32i8_signbit_not: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovaps (%rdi), %ymm0 +; X64-AVX1-NEXT: vandnps (%rsi), %ymm0, %ymm0 +; X64-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 +; X64-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vpmovmskb %xmm0, %eax +; X64-AVX1-NEXT: testl %eax, %eax +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; +; X86-AVX2-LABEL: reduce_umax_v32i8_signbit_not: +; X86-AVX2: # %bb.0: +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX2-NEXT: vmovdqa (%ecx), %ymm0 +; X86-AVX2-NEXT: vpandn (%eax), %ymm0, %ymm0 +; X86-AVX2-NEXT: vpmovmskb %ymm0, %eax +; X86-AVX2-NEXT: testl %eax, %eax +; X86-AVX2-NEXT: sete %al +; X86-AVX2-NEXT: vzeroupper +; X86-AVX2-NEXT: retl +; +; X64-AVX2-LABEL: reduce_umax_v32i8_signbit_not: +; X64-AVX2: # %bb.0: +; X64-AVX2-NEXT: vmovdqa (%rdi), %ymm0 +; X64-AVX2-NEXT: vpandn (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax +; X64-AVX2-NEXT: testl %eax, %eax +; X64-AVX2-NEXT: sete %al +; X64-AVX2-NEXT: vzeroupper +; X64-AVX2-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v32i8_signbit_not: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa (%rdi), %ymm0 +; AVX512-NEXT: vpandn (%rsi), %ymm0, %ymm0 +; AVX512-NEXT: vpmovmskb %ymm0, %eax +; AVX512-NEXT: testl %eax, %eax +; AVX512-NEXT: sete %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <32 x i8>, ptr %pa + %b = load <32 x i8>, ptr %pb + %a.not = xor <32 x i8> %a, splat (i8 -1) + %and = and <32 x i8> %b, %a.not + %rdx = call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %and) + %cmp = icmp sgt i8 %rdx, -1 + %res = zext i1 %cmp to i8 + ret i8 %res +} + +define i16 @reduce_umax_v16i16_signbit(ptr %pa, ptr %pb) { +; X86-SSE2-LABEL: reduce_umax_v16i16_signbit: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE2-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE2-NEXT: pand (%eax), %xmm0 +; X86-SSE2-NEXT: pand 16(%eax), %xmm1 +; X86-SSE2-NEXT: psubusw %xmm0, %xmm1 +; X86-SSE2-NEXT: paddw %xmm0, %xmm1 +; X86-SSE2-NEXT: packsswb %xmm1, %xmm1 +; X86-SSE2-NEXT: pmovmskb %xmm1, %ecx +; X86-SSE2-NEXT: xorl %eax, %eax +; X86-SSE2-NEXT: testl %ecx, %ecx +; X86-SSE2-NEXT: sete %al +; X86-SSE2-NEXT: # kill: def $ax killed $ax killed $eax +; X86-SSE2-NEXT: retl +; +; X64-SSE2-LABEL: reduce_umax_v16i16_signbit: +; X64-SSE2: # %bb.0: +; X64-SSE2-NEXT: movdqa (%rsi), %xmm0 +; X64-SSE2-NEXT: movdqa 16(%rsi), %xmm1 +; X64-SSE2-NEXT: pand (%rdi), %xmm0 +; X64-SSE2-NEXT: pand 16(%rdi), %xmm1 +; X64-SSE2-NEXT: psubusw %xmm0, %xmm1 +; X64-SSE2-NEXT: paddw %xmm0, %xmm1 +; X64-SSE2-NEXT: packsswb %xmm1, %xmm1 +; X64-SSE2-NEXT: pmovmskb %xmm1, %ecx +; X64-SSE2-NEXT: xorl %eax, %eax +; X64-SSE2-NEXT: testl %ecx, %ecx +; X64-SSE2-NEXT: sete %al +; X64-SSE2-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SSE2-NEXT: retq +; +; X86-SSE4-LABEL: reduce_umax_v16i16_signbit: +; X86-SSE4: # %bb.0: +; X86-SSE4-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE4-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE4-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE4-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE4-NEXT: pand 16(%eax), %xmm1 +; X86-SSE4-NEXT: pand (%eax), %xmm0 +; X86-SSE4-NEXT: pmaxuw %xmm1, %xmm0 +; X86-SSE4-NEXT: packsswb %xmm0, %xmm0 +; X86-SSE4-NEXT: pmovmskb %xmm0, %ecx +; X86-SSE4-NEXT: xorl %eax, %eax +; X86-SSE4-NEXT: testl %ecx, %ecx +; X86-SSE4-NEXT: sete %al +; X86-SSE4-NEXT: # kill: def $ax killed $ax killed $eax +; X86-SSE4-NEXT: retl +; +; X64-SSE4-LABEL: reduce_umax_v16i16_signbit: +; X64-SSE4: # %bb.0: +; X64-SSE4-NEXT: movdqa (%rsi), %xmm0 +; X64-SSE4-NEXT: movdqa 16(%rsi), %xmm1 +; X64-SSE4-NEXT: pand 16(%rdi), %xmm1 +; X64-SSE4-NEXT: pand (%rdi), %xmm0 +; X64-SSE4-NEXT: pmaxuw %xmm1, %xmm0 +; X64-SSE4-NEXT: packsswb %xmm0, %xmm0 +; X64-SSE4-NEXT: pmovmskb %xmm0, %ecx +; X64-SSE4-NEXT: xorl %eax, %eax +; X64-SSE4-NEXT: testl %ecx, %ecx +; X64-SSE4-NEXT: sete %al +; X64-SSE4-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SSE4-NEXT: retq +; +; X86-AVX1-LABEL: reduce_umax_v16i16_signbit: +; X86-AVX1: # %bb.0: +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX1-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX1-NEXT: vandps (%eax), %ymm0, %ymm0 +; X86-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 +; X86-AVX1-NEXT: vpacksswb %xmm1, %xmm0, %xmm0 +; X86-AVX1-NEXT: vpmovmskb %xmm0, %ecx +; X86-AVX1-NEXT: xorl %eax, %eax +; X86-AVX1-NEXT: testl %ecx, %ecx +; X86-AVX1-NEXT: sete %al +; X86-AVX1-NEXT: # kill: def $ax killed $ax killed $eax +; X86-AVX1-NEXT: vzeroupper +; X86-AVX1-NEXT: retl +; +; X64-AVX1-LABEL: reduce_umax_v16i16_signbit: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovaps (%rsi), %ymm0 +; X64-AVX1-NEXT: vandps (%rdi), %ymm0, %ymm0 +; X64-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 +; X64-AVX1-NEXT: vpacksswb %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vpmovmskb %xmm0, %ecx +; X64-AVX1-NEXT: xorl %eax, %eax +; X64-AVX1-NEXT: testl %ecx, %ecx +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: # kill: def $ax killed $ax killed $eax +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; +; X86-AVX2-LABEL: reduce_umax_v16i16_signbit: +; X86-AVX2: # %bb.0: +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX2-NEXT: vmovdqa (%ecx), %ymm0 +; X86-AVX2-NEXT: vpand (%eax), %ymm0, %ymm0 +; X86-AVX2-NEXT: vpmovmskb %ymm0, %ecx +; X86-AVX2-NEXT: xorl %eax, %eax +; X86-AVX2-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; X86-AVX2-NEXT: sete %al +; X86-AVX2-NEXT: # kill: def $ax killed $ax killed $eax +; X86-AVX2-NEXT: vzeroupper +; X86-AVX2-NEXT: retl +; +; X64-AVX2-LABEL: reduce_umax_v16i16_signbit: +; X64-AVX2: # %bb.0: +; X64-AVX2-NEXT: vmovdqa (%rsi), %ymm0 +; X64-AVX2-NEXT: vpand (%rdi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpmovmskb %ymm0, %ecx +; X64-AVX2-NEXT: xorl %eax, %eax +; X64-AVX2-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; X64-AVX2-NEXT: sete %al +; X64-AVX2-NEXT: # kill: def $ax killed $ax killed $eax +; X64-AVX2-NEXT: vzeroupper +; X64-AVX2-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v16i16_signbit: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa (%rsi), %ymm0 +; AVX512-NEXT: vpand (%rdi), %ymm0, %ymm0 +; AVX512-NEXT: vpmovmskb %ymm0, %ecx +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; AVX512-NEXT: sete %al +; AVX512-NEXT: # kill: def $ax killed $ax killed $eax +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <16 x i16>, ptr %pa + %b = load <16 x i16>, ptr %pb + %and = and <16 x i16> %b, %a + %rdx = call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %and) + %cmp = icmp sgt i16 %rdx, -1 + %res = zext i1 %cmp to i16 + ret i16 %res +} + +define i32 @reduce_umax_v8i32_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v8i32_signbit_not: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movaps (%ecx), %xmm0 +; X86-SSE-NEXT: movaps 16(%ecx), %xmm1 +; X86-SSE-NEXT: andnps 16(%eax), %xmm1 +; X86-SSE-NEXT: andnps (%eax), %xmm0 +; X86-SSE-NEXT: orps %xmm1, %xmm0 +; X86-SSE-NEXT: movmskps %xmm0, %ecx +; X86-SSE-NEXT: xorl %eax, %eax +; X86-SSE-NEXT: testl %ecx, %ecx +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v8i32_signbit_not: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movaps (%rdi), %xmm0 +; X64-SSE-NEXT: movaps 16(%rdi), %xmm1 +; X64-SSE-NEXT: andnps 16(%rsi), %xmm1 +; X64-SSE-NEXT: andnps (%rsi), %xmm0 +; X64-SSE-NEXT: orps %xmm1, %xmm0 +; X64-SSE-NEXT: movmskps %xmm0, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v8i32_signbit_not: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: vmovaps (%eax), %ymm0 +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: vtestps (%ecx), %ymm0 +; X86-AVX-NEXT: setb %al +; X86-AVX-NEXT: vzeroupper +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v8i32_signbit_not: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovaps (%rdi), %ymm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestps (%rsi), %ymm0 +; X64-AVX-NEXT: setb %al +; X64-AVX-NEXT: vzeroupper +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v8i32_signbit_not: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovaps (%rdi), %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vtestps (%rsi), %ymm0 +; AVX512-NEXT: setb %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <8 x i32>, ptr %pa + %b = load <8 x i32>, ptr %pb + %a.not = xor <8 x i32> %a, splat (i32 -1) + %and = and <8 x i32> %b, %a.not + %rdx = call i32 @llvm.vector.reduce.umax.v8i32(<8 x i32> %and) + %cmp = icmp sgt i32 %rdx, -1 + %res = zext i1 %cmp to i32 + ret i32 %res +} + +define i64 @reduce_umax_v4i64_signbit(ptr %pa, ptr %pb) { +; X86-SSE2-LABEL: reduce_umax_v4i64_signbit: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movdqa (%ecx), %xmm0 +; X86-SSE2-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE2-NEXT: pand (%eax), %xmm0 +; X86-SSE2-NEXT: pand 16(%eax), %xmm1 +; X86-SSE2-NEXT: movdqa {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] +; X86-SSE2-NEXT: movdqa %xmm1, %xmm3 +; X86-SSE2-NEXT: pxor %xmm2, %xmm3 +; X86-SSE2-NEXT: pxor %xmm0, %xmm2 +; X86-SSE2-NEXT: movdqa %xmm2, %xmm4 +; X86-SSE2-NEXT: pcmpgtd %xmm3, %xmm4 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[0,0,2,2] +; X86-SSE2-NEXT: pcmpeqd %xmm3, %xmm2 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,3,3] +; X86-SSE2-NEXT: pand %xmm5, %xmm2 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm4[1,1,3,3] +; X86-SSE2-NEXT: por %xmm2, %xmm3 +; X86-SSE2-NEXT: pand %xmm3, %xmm0 +; X86-SSE2-NEXT: pandn %xmm1, %xmm3 +; X86-SSE2-NEXT: por %xmm0, %xmm3 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[3,3,3,3] +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[1,1,1,1] +; X86-SSE2-NEXT: por %xmm0, %xmm1 +; X86-SSE2-NEXT: movd %xmm1, %eax +; X86-SSE2-NEXT: notl %eax +; X86-SSE2-NEXT: shrl $31, %eax +; X86-SSE2-NEXT: xorl %edx, %edx +; X86-SSE2-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v4i64_signbit: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movapd (%rsi), %xmm0 +; X64-SSE-NEXT: movapd 16(%rsi), %xmm1 +; X64-SSE-NEXT: andpd 16(%rdi), %xmm1 +; X64-SSE-NEXT: andpd (%rdi), %xmm0 +; X64-SSE-NEXT: orpd %xmm1, %xmm0 +; X64-SSE-NEXT: movmskpd %xmm0, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-SSE41-LABEL: reduce_umax_v4i64_signbit: +; X86-SSE41: # %bb.0: +; X86-SSE41-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE41-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE41-NEXT: movdqa (%ecx), %xmm2 +; X86-SSE41-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE41-NEXT: pand (%eax), %xmm2 +; X86-SSE41-NEXT: pand 16(%eax), %xmm1 +; X86-SSE41-NEXT: movdqa {{.*#+}} xmm0 = [2147483648,2147483648,2147483648,2147483648] +; X86-SSE41-NEXT: movdqa %xmm1, %xmm3 +; X86-SSE41-NEXT: pxor %xmm0, %xmm3 +; X86-SSE41-NEXT: pxor %xmm2, %xmm0 +; X86-SSE41-NEXT: movdqa %xmm0, %xmm4 +; X86-SSE41-NEXT: pcmpgtd %xmm3, %xmm4 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm5 = xmm4[0,0,2,2] +; X86-SSE41-NEXT: pcmpeqd %xmm3, %xmm0 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3] +; X86-SSE41-NEXT: pand %xmm5, %xmm3 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm4[1,1,3,3] +; X86-SSE41-NEXT: por %xmm3, %xmm0 +; X86-SSE41-NEXT: blendvpd %xmm0, %xmm2, %xmm1 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; X86-SSE41-NEXT: por %xmm1, %xmm0 +; X86-SSE41-NEXT: pextrd $1, %xmm0, %eax +; X86-SSE41-NEXT: notl %eax +; X86-SSE41-NEXT: shrl $31, %eax +; X86-SSE41-NEXT: xorl %edx, %edx +; X86-SSE41-NEXT: retl +; +; X86-SSE42-LABEL: reduce_umax_v4i64_signbit: +; X86-SSE42: # %bb.0: +; X86-SSE42-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE42-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE42-NEXT: movdqa (%ecx), %xmm2 +; X86-SSE42-NEXT: movdqa 16(%ecx), %xmm1 +; X86-SSE42-NEXT: pand (%eax), %xmm2 +; X86-SSE42-NEXT: pand 16(%eax), %xmm1 +; X86-SSE42-NEXT: movdqa {{.*#+}} xmm0 = [0,2147483648,0,2147483648] +; X86-SSE42-NEXT: movdqa %xmm1, %xmm3 +; X86-SSE42-NEXT: pxor %xmm0, %xmm3 +; X86-SSE42-NEXT: pxor %xmm2, %xmm0 +; X86-SSE42-NEXT: pcmpgtq %xmm3, %xmm0 +; X86-SSE42-NEXT: blendvpd %xmm0, %xmm2, %xmm1 +; X86-SSE42-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; X86-SSE42-NEXT: por %xmm1, %xmm0 +; X86-SSE42-NEXT: pextrd $1, %xmm0, %eax +; X86-SSE42-NEXT: notl %eax +; X86-SSE42-NEXT: shrl $31, %eax +; X86-SSE42-NEXT: xorl %edx, %edx +; X86-SSE42-NEXT: retl +; +; X86-AVX-LABEL: reduce_umax_v4i64_signbit: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: vmovapd (%eax), %ymm0 +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: vtestpd (%ecx), %ymm0 +; X86-AVX-NEXT: sete %al +; X86-AVX-NEXT: xorl %edx, %edx +; X86-AVX-NEXT: vzeroupper +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v4i64_signbit: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovapd (%rdi), %ymm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestpd (%rsi), %ymm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: vzeroupper +; X64-AVX-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v4i64_signbit: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovapd (%rdi), %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vtestpd (%rsi), %ymm0 +; AVX512-NEXT: sete %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <4 x i64>, ptr %pa + %b = load <4 x i64>, ptr %pb + %and = and <4 x i64> %b, %a + %rdx = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> %and) + %cmp = icmp sgt i64 %rdx, -1 + %res = zext i1 %cmp to i64 + ret i64 %res +} + +define i8 @reduce_umax_v64i8_signbit(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v64i8_signbit: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movdqa 48(%ecx), %xmm0 +; X86-SSE-NEXT: movdqa (%ecx), %xmm1 +; X86-SSE-NEXT: movdqa 16(%ecx), %xmm2 +; X86-SSE-NEXT: movdqa 32(%ecx), %xmm3 +; X86-SSE-NEXT: pand 32(%eax), %xmm3 +; X86-SSE-NEXT: pand (%eax), %xmm1 +; X86-SSE-NEXT: por %xmm3, %xmm1 +; X86-SSE-NEXT: pand 48(%eax), %xmm0 +; X86-SSE-NEXT: pand 16(%eax), %xmm2 +; X86-SSE-NEXT: por %xmm0, %xmm2 +; X86-SSE-NEXT: por %xmm1, %xmm2 +; X86-SSE-NEXT: pmovmskb %xmm2, %eax +; X86-SSE-NEXT: testl %eax, %eax +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v64i8_signbit: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movdqa (%rsi), %xmm0 +; X64-SSE-NEXT: movdqa 16(%rsi), %xmm1 +; X64-SSE-NEXT: movdqa 32(%rsi), %xmm2 +; X64-SSE-NEXT: movdqa 48(%rsi), %xmm3 +; X64-SSE-NEXT: pand 32(%rdi), %xmm2 +; X64-SSE-NEXT: pand (%rdi), %xmm0 +; X64-SSE-NEXT: por %xmm2, %xmm0 +; X64-SSE-NEXT: pand 48(%rdi), %xmm3 +; X64-SSE-NEXT: pand 16(%rdi), %xmm1 +; X64-SSE-NEXT: por %xmm3, %xmm1 +; X64-SSE-NEXT: por %xmm0, %xmm1 +; X64-SSE-NEXT: pmovmskb %xmm1, %eax +; X64-SSE-NEXT: testl %eax, %eax +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX1-LABEL: reduce_umax_v64i8_signbit: +; X86-AVX1: # %bb.0: +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX1-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX1-NEXT: vmovaps 32(%ecx), %ymm1 +; X86-AVX1-NEXT: vandps (%eax), %ymm0, %ymm0 +; X86-AVX1-NEXT: vandps 32(%eax), %ymm1, %ymm1 +; X86-AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; X86-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; X86-AVX1-NEXT: vorps %xmm2, %xmm3, %xmm2 +; X86-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X86-AVX1-NEXT: vorps %xmm2, %xmm0, %xmm0 +; X86-AVX1-NEXT: vpmovmskb %xmm0, %eax +; X86-AVX1-NEXT: testl %eax, %eax +; X86-AVX1-NEXT: sete %al +; X86-AVX1-NEXT: vzeroupper +; X86-AVX1-NEXT: retl +; +; X64-AVX1-LABEL: reduce_umax_v64i8_signbit: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovaps (%rsi), %ymm0 +; X64-AVX1-NEXT: vmovaps 32(%rsi), %ymm1 +; X64-AVX1-NEXT: vandps (%rdi), %ymm0, %ymm0 +; X64-AVX1-NEXT: vandps 32(%rdi), %ymm1, %ymm1 +; X64-AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; X64-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; X64-AVX1-NEXT: vorps %xmm2, %xmm3, %xmm2 +; X64-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vorps %xmm2, %xmm0, %xmm0 +; X64-AVX1-NEXT: vpmovmskb %xmm0, %eax +; X64-AVX1-NEXT: testl %eax, %eax +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; +; X86-AVX2-LABEL: reduce_umax_v64i8_signbit: +; X86-AVX2: # %bb.0: +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX2-NEXT: vmovdqa (%ecx), %ymm0 +; X86-AVX2-NEXT: vmovdqa 32(%ecx), %ymm1 +; X86-AVX2-NEXT: vpand 32(%eax), %ymm1, %ymm1 +; X86-AVX2-NEXT: vpand (%eax), %ymm0, %ymm0 +; X86-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X86-AVX2-NEXT: vpmovmskb %ymm0, %eax +; X86-AVX2-NEXT: testl %eax, %eax +; X86-AVX2-NEXT: sete %al +; X86-AVX2-NEXT: vzeroupper +; X86-AVX2-NEXT: retl +; +; X64-AVX2-LABEL: reduce_umax_v64i8_signbit: +; X64-AVX2: # %bb.0: +; X64-AVX2-NEXT: vmovdqa (%rsi), %ymm0 +; X64-AVX2-NEXT: vmovdqa 32(%rsi), %ymm1 +; X64-AVX2-NEXT: vpand 32(%rdi), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpand (%rdi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax +; X64-AVX2-NEXT: testl %eax, %eax +; X64-AVX2-NEXT: sete %al +; X64-AVX2-NEXT: vzeroupper +; X64-AVX2-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v64i8_signbit: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa64 (%rsi), %zmm0 +; AVX512-NEXT: vpandq (%rdi), %zmm0, %zmm0 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm1 +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovmskb %ymm0, %eax +; AVX512-NEXT: testl %eax, %eax +; AVX512-NEXT: sete %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <64 x i8>, ptr %pa + %b = load <64 x i8>, ptr %pb + %and = and <64 x i8> %b, %a + %rdx = call i8 @llvm.vector.reduce.umax.v64i8(<64 x i8> %and) + %cmp = icmp sgt i8 %rdx, -1 + %res = zext i1 %cmp to i8 + ret i8 %res +} + +define i16 @reduce_umax_v32i16_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE2-LABEL: reduce_umax_v32i16_signbit_not: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movdqa 32(%ecx), %xmm1 +; X86-SSE2-NEXT: movdqa 48(%ecx), %xmm0 +; X86-SSE2-NEXT: movdqa (%ecx), %xmm2 +; X86-SSE2-NEXT: movdqa 16(%ecx), %xmm3 +; X86-SSE2-NEXT: pandn 16(%eax), %xmm3 +; X86-SSE2-NEXT: pandn 48(%eax), %xmm0 +; X86-SSE2-NEXT: pandn (%eax), %xmm2 +; X86-SSE2-NEXT: pandn 32(%eax), %xmm1 +; X86-SSE2-NEXT: psubusw %xmm2, %xmm1 +; X86-SSE2-NEXT: paddw %xmm2, %xmm1 +; X86-SSE2-NEXT: psubusw %xmm3, %xmm0 +; X86-SSE2-NEXT: paddw %xmm3, %xmm0 +; X86-SSE2-NEXT: psubusw %xmm1, %xmm0 +; X86-SSE2-NEXT: paddw %xmm1, %xmm0 +; X86-SSE2-NEXT: packsswb %xmm0, %xmm0 +; X86-SSE2-NEXT: pmovmskb %xmm0, %ecx +; X86-SSE2-NEXT: xorl %eax, %eax +; X86-SSE2-NEXT: testl %ecx, %ecx +; X86-SSE2-NEXT: sete %al +; X86-SSE2-NEXT: # kill: def $ax killed $ax killed $eax +; X86-SSE2-NEXT: retl +; +; X64-SSE2-LABEL: reduce_umax_v32i16_signbit_not: +; X64-SSE2: # %bb.0: +; X64-SSE2-NEXT: movdqa (%rdi), %xmm0 +; X64-SSE2-NEXT: movdqa 16(%rdi), %xmm1 +; X64-SSE2-NEXT: movdqa 32(%rdi), %xmm2 +; X64-SSE2-NEXT: movdqa 48(%rdi), %xmm3 +; X64-SSE2-NEXT: pandn 16(%rsi), %xmm1 +; X64-SSE2-NEXT: pandn 48(%rsi), %xmm3 +; X64-SSE2-NEXT: pandn (%rsi), %xmm0 +; X64-SSE2-NEXT: pandn 32(%rsi), %xmm2 +; X64-SSE2-NEXT: psubusw %xmm0, %xmm2 +; X64-SSE2-NEXT: paddw %xmm0, %xmm2 +; X64-SSE2-NEXT: psubusw %xmm1, %xmm3 +; X64-SSE2-NEXT: paddw %xmm1, %xmm3 +; X64-SSE2-NEXT: psubusw %xmm2, %xmm3 +; X64-SSE2-NEXT: paddw %xmm2, %xmm3 +; X64-SSE2-NEXT: packsswb %xmm3, %xmm3 +; X64-SSE2-NEXT: pmovmskb %xmm3, %ecx +; X64-SSE2-NEXT: xorl %eax, %eax +; X64-SSE2-NEXT: testl %ecx, %ecx +; X64-SSE2-NEXT: sete %al +; X64-SSE2-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SSE2-NEXT: retq +; +; X86-SSE4-LABEL: reduce_umax_v32i16_signbit_not: +; X86-SSE4: # %bb.0: +; X86-SSE4-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE4-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE4-NEXT: movdqa 48(%ecx), %xmm1 +; X86-SSE4-NEXT: movdqa (%ecx), %xmm2 +; X86-SSE4-NEXT: movdqa 16(%ecx), %xmm0 +; X86-SSE4-NEXT: movdqa 32(%ecx), %xmm3 +; X86-SSE4-NEXT: pandn 32(%eax), %xmm3 +; X86-SSE4-NEXT: pandn (%eax), %xmm2 +; X86-SSE4-NEXT: pmaxuw %xmm3, %xmm2 +; X86-SSE4-NEXT: pandn 48(%eax), %xmm1 +; X86-SSE4-NEXT: pandn 16(%eax), %xmm0 +; X86-SSE4-NEXT: pmaxuw %xmm1, %xmm0 +; X86-SSE4-NEXT: pmaxuw %xmm2, %xmm0 +; X86-SSE4-NEXT: packsswb %xmm0, %xmm0 +; X86-SSE4-NEXT: pmovmskb %xmm0, %ecx +; X86-SSE4-NEXT: xorl %eax, %eax +; X86-SSE4-NEXT: testl %ecx, %ecx +; X86-SSE4-NEXT: sete %al +; X86-SSE4-NEXT: # kill: def $ax killed $ax killed $eax +; X86-SSE4-NEXT: retl +; +; X64-SSE4-LABEL: reduce_umax_v32i16_signbit_not: +; X64-SSE4: # %bb.0: +; X64-SSE4-NEXT: movdqa (%rdi), %xmm0 +; X64-SSE4-NEXT: movdqa 16(%rdi), %xmm1 +; X64-SSE4-NEXT: movdqa 32(%rdi), %xmm2 +; X64-SSE4-NEXT: movdqa 48(%rdi), %xmm3 +; X64-SSE4-NEXT: pandn 32(%rsi), %xmm2 +; X64-SSE4-NEXT: pandn (%rsi), %xmm0 +; X64-SSE4-NEXT: pmaxuw %xmm2, %xmm0 +; X64-SSE4-NEXT: pandn 48(%rsi), %xmm3 +; X64-SSE4-NEXT: pandn 16(%rsi), %xmm1 +; X64-SSE4-NEXT: pmaxuw %xmm3, %xmm1 +; X64-SSE4-NEXT: pmaxuw %xmm0, %xmm1 +; X64-SSE4-NEXT: packsswb %xmm1, %xmm1 +; X64-SSE4-NEXT: pmovmskb %xmm1, %ecx +; X64-SSE4-NEXT: xorl %eax, %eax +; X64-SSE4-NEXT: testl %ecx, %ecx +; X64-SSE4-NEXT: sete %al +; X64-SSE4-NEXT: # kill: def $ax killed $ax killed $eax +; X64-SSE4-NEXT: retq +; +; X86-AVX1-LABEL: reduce_umax_v32i16_signbit_not: +; X86-AVX1: # %bb.0: +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX1-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX1-NEXT: vmovaps 32(%ecx), %ymm1 +; X86-AVX1-NEXT: vandnps (%eax), %ymm0, %ymm0 +; X86-AVX1-NEXT: vandnps 32(%eax), %ymm1, %ymm1 +; X86-AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; X86-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; X86-AVX1-NEXT: vpor %xmm2, %xmm3, %xmm2 +; X86-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X86-AVX1-NEXT: vpacksswb %xmm2, %xmm0, %xmm0 +; X86-AVX1-NEXT: vpmovmskb %xmm0, %ecx +; X86-AVX1-NEXT: xorl %eax, %eax +; X86-AVX1-NEXT: testl %ecx, %ecx +; X86-AVX1-NEXT: sete %al +; X86-AVX1-NEXT: # kill: def $ax killed $ax killed $eax +; X86-AVX1-NEXT: vzeroupper +; X86-AVX1-NEXT: retl +; +; X64-AVX1-LABEL: reduce_umax_v32i16_signbit_not: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovaps (%rdi), %ymm0 +; X64-AVX1-NEXT: vmovaps 32(%rdi), %ymm1 +; X64-AVX1-NEXT: vandnps (%rsi), %ymm0, %ymm0 +; X64-AVX1-NEXT: vandnps 32(%rsi), %ymm1, %ymm1 +; X64-AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; X64-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; X64-AVX1-NEXT: vpor %xmm2, %xmm3, %xmm2 +; X64-AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vpacksswb %xmm2, %xmm0, %xmm0 +; X64-AVX1-NEXT: vpmovmskb %xmm0, %ecx +; X64-AVX1-NEXT: xorl %eax, %eax +; X64-AVX1-NEXT: testl %ecx, %ecx +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: # kill: def $ax killed $ax killed $eax +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; +; X86-AVX2-LABEL: reduce_umax_v32i16_signbit_not: +; X86-AVX2: # %bb.0: +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX2-NEXT: vmovdqa (%ecx), %ymm0 +; X86-AVX2-NEXT: vmovdqa 32(%ecx), %ymm1 +; X86-AVX2-NEXT: vpandn 32(%eax), %ymm1, %ymm1 +; X86-AVX2-NEXT: vpandn (%eax), %ymm0, %ymm0 +; X86-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X86-AVX2-NEXT: vpmovmskb %ymm0, %ecx +; X86-AVX2-NEXT: xorl %eax, %eax +; X86-AVX2-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; X86-AVX2-NEXT: sete %al +; X86-AVX2-NEXT: # kill: def $ax killed $ax killed $eax +; X86-AVX2-NEXT: vzeroupper +; X86-AVX2-NEXT: retl +; +; X64-AVX2-LABEL: reduce_umax_v32i16_signbit_not: +; X64-AVX2: # %bb.0: +; X64-AVX2-NEXT: vmovdqa (%rdi), %ymm0 +; X64-AVX2-NEXT: vmovdqa 32(%rdi), %ymm1 +; X64-AVX2-NEXT: vpandn 32(%rsi), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpandn (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vpmovmskb %ymm0, %ecx +; X64-AVX2-NEXT: xorl %eax, %eax +; X64-AVX2-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; X64-AVX2-NEXT: sete %al +; X64-AVX2-NEXT: # kill: def $ax killed $ax killed $eax +; X64-AVX2-NEXT: vzeroupper +; X64-AVX2-NEXT: retq +; +; AVX512-LABEL: reduce_umax_v32i16_signbit_not: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqa64 (%rdi), %zmm0 +; AVX512-NEXT: vpandnq (%rsi), %zmm0, %zmm0 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm1 +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovmskb %ymm0, %ecx +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: testl $-1431655766, %ecx # imm = 0xAAAAAAAA +; AVX512-NEXT: sete %al +; AVX512-NEXT: # kill: def $ax killed $ax killed $eax +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %a = load <32 x i16>, ptr %pa + %b = load <32 x i16>, ptr %pb + %a.not = xor <32 x i16> %a, splat (i16 -1) + %and = and <32 x i16> %b, %a.not + %rdx = call i16 @llvm.vector.reduce.umax.v32i16(<32 x i16> %and) + %cmp = icmp sgt i16 %rdx, -1 + %res = zext i1 %cmp to i16 + ret i16 %res +} + +define i32 @reduce_umax_v16i32_signbit(ptr %pa, ptr %pb) { +; X86-SSE-LABEL: reduce_umax_v16i32_signbit: +; X86-SSE: # %bb.0: +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE-NEXT: movaps 48(%ecx), %xmm0 +; X86-SSE-NEXT: movaps (%ecx), %xmm1 +; X86-SSE-NEXT: movaps 16(%ecx), %xmm2 +; X86-SSE-NEXT: movaps 32(%ecx), %xmm3 +; X86-SSE-NEXT: andps 32(%eax), %xmm3 +; X86-SSE-NEXT: andps (%eax), %xmm1 +; X86-SSE-NEXT: orps %xmm3, %xmm1 +; X86-SSE-NEXT: andps 48(%eax), %xmm0 +; X86-SSE-NEXT: andps 16(%eax), %xmm2 +; X86-SSE-NEXT: orps %xmm0, %xmm2 +; X86-SSE-NEXT: orps %xmm1, %xmm2 +; X86-SSE-NEXT: movmskps %xmm2, %ecx +; X86-SSE-NEXT: xorl %eax, %eax +; X86-SSE-NEXT: testl %ecx, %ecx +; X86-SSE-NEXT: sete %al +; X86-SSE-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v16i32_signbit: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movaps (%rsi), %xmm0 +; X64-SSE-NEXT: movaps 16(%rsi), %xmm1 +; X64-SSE-NEXT: movaps 32(%rsi), %xmm2 +; X64-SSE-NEXT: movaps 48(%rsi), %xmm3 +; X64-SSE-NEXT: andps 32(%rdi), %xmm2 +; X64-SSE-NEXT: andps (%rdi), %xmm0 +; X64-SSE-NEXT: orps %xmm2, %xmm0 +; X64-SSE-NEXT: andps 48(%rdi), %xmm3 +; X64-SSE-NEXT: andps 16(%rdi), %xmm1 +; X64-SSE-NEXT: orps %xmm3, %xmm1 +; X64-SSE-NEXT: orps %xmm0, %xmm1 +; X64-SSE-NEXT: movmskps %xmm1, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-AVX-LABEL: reduce_umax_v16i32_signbit: +; X86-AVX: # %bb.0: +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX-NEXT: vmovaps 32(%ecx), %ymm1 +; X86-AVX-NEXT: vandps 32(%eax), %ymm1, %ymm1 +; X86-AVX-NEXT: vandps (%eax), %ymm0, %ymm0 +; X86-AVX-NEXT: vorps %ymm1, %ymm0, %ymm0 +; X86-AVX-NEXT: xorl %eax, %eax +; X86-AVX-NEXT: vtestps %ymm0, %ymm0 +; X86-AVX-NEXT: sete %al +; X86-AVX-NEXT: vzeroupper +; X86-AVX-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v16i32_signbit: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovaps (%rsi), %ymm0 +; X64-AVX-NEXT: vmovaps 32(%rsi), %ymm1 +; X64-AVX-NEXT: vandps 32(%rdi), %ymm1, %ymm1 +; X64-AVX-NEXT: vandps (%rdi), %ymm0, %ymm0 +; X64-AVX-NEXT: vorps %ymm1, %ymm0, %ymm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestps %ymm0, %ymm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: vzeroupper +; X64-AVX-NEXT: retq +; +; AVX512BW-LABEL: reduce_umax_v16i32_signbit: +; AVX512BW: # %bb.0: +; AVX512BW-NEXT: vmovdqa64 (%rsi), %zmm0 +; AVX512BW-NEXT: vpandd (%rdi), %zmm0, %zmm0 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm0, %ymm1 +; AVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512BW-NEXT: xorl %eax, %eax +; AVX512BW-NEXT: vtestps %ymm0, %ymm0 +; AVX512BW-NEXT: sete %al +; AVX512BW-NEXT: vzeroupper +; AVX512BW-NEXT: retq +; +; AVX512BWVL-LABEL: reduce_umax_v16i32_signbit: +; AVX512BWVL: # %bb.0: +; AVX512BWVL-NEXT: vmovaps (%rsi), %zmm0 +; AVX512BWVL-NEXT: vandps (%rdi), %zmm0, %zmm0 +; AVX512BWVL-NEXT: vextractf64x4 $1, %zmm0, %ymm1 +; AVX512BWVL-NEXT: vorps %ymm1, %ymm0, %ymm0 +; AVX512BWVL-NEXT: xorl %eax, %eax +; AVX512BWVL-NEXT: vtestps %ymm0, %ymm0 +; AVX512BWVL-NEXT: sete %al +; AVX512BWVL-NEXT: vzeroupper +; AVX512BWVL-NEXT: retq + %a = load <16 x i32>, ptr %pa + %b = load <16 x i32>, ptr %pb + %and = and <16 x i32> %b, %a + %rdx = call i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> %and) + %cmp = icmp sgt i32 %rdx, -1 + %res = zext i1 %cmp to i32 + ret i32 %res +} + +define i64 @reduce_umax_v8i64_signbit_not(ptr %pa, ptr %pb) { +; X86-SSE2-LABEL: reduce_umax_v8i64_signbit_not: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movdqa 48(%ecx), %xmm4 +; X86-SSE2-NEXT: movdqa 32(%ecx), %xmm1 +; X86-SSE2-NEXT: movdqa 16(%ecx), %xmm5 +; X86-SSE2-NEXT: pandn 16(%eax), %xmm5 +; X86-SSE2-NEXT: pandn 48(%eax), %xmm4 +; X86-SSE2-NEXT: movdqa {{.*#+}} xmm0 = [2147483648,2147483648,2147483648,2147483648] +; X86-SSE2-NEXT: movdqa %xmm4, %xmm2 +; X86-SSE2-NEXT: pxor %xmm0, %xmm2 +; X86-SSE2-NEXT: movdqa %xmm5, %xmm3 +; X86-SSE2-NEXT: pxor %xmm0, %xmm3 +; X86-SSE2-NEXT: movdqa %xmm3, %xmm6 +; X86-SSE2-NEXT: pcmpgtd %xmm2, %xmm6 +; X86-SSE2-NEXT: pcmpeqd %xmm2, %xmm3 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm6[0,0,2,2] +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm3[1,1,3,3] +; X86-SSE2-NEXT: pand %xmm2, %xmm7 +; X86-SSE2-NEXT: movdqa (%ecx), %xmm3 +; X86-SSE2-NEXT: pandn (%eax), %xmm3 +; X86-SSE2-NEXT: pandn 32(%eax), %xmm1 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm6[1,1,3,3] +; X86-SSE2-NEXT: por %xmm7, %xmm2 +; X86-SSE2-NEXT: pand %xmm2, %xmm5 +; X86-SSE2-NEXT: pandn %xmm4, %xmm2 +; X86-SSE2-NEXT: por %xmm5, %xmm2 +; X86-SSE2-NEXT: movdqa %xmm1, %xmm4 +; X86-SSE2-NEXT: pxor %xmm0, %xmm4 +; X86-SSE2-NEXT: movdqa %xmm3, %xmm5 +; X86-SSE2-NEXT: pxor %xmm0, %xmm5 +; X86-SSE2-NEXT: movdqa %xmm5, %xmm6 +; X86-SSE2-NEXT: pcmpgtd %xmm4, %xmm6 +; X86-SSE2-NEXT: pcmpeqd %xmm4, %xmm5 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm6[0,0,2,2] +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[1,1,3,3] +; X86-SSE2-NEXT: pand %xmm4, %xmm5 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm6[1,1,3,3] +; X86-SSE2-NEXT: por %xmm5, %xmm4 +; X86-SSE2-NEXT: pand %xmm4, %xmm3 +; X86-SSE2-NEXT: pandn %xmm1, %xmm4 +; X86-SSE2-NEXT: movdqa %xmm2, %xmm1 +; X86-SSE2-NEXT: pxor %xmm0, %xmm1 +; X86-SSE2-NEXT: por %xmm3, %xmm4 +; X86-SSE2-NEXT: pxor %xmm4, %xmm0 +; X86-SSE2-NEXT: movdqa %xmm0, %xmm3 +; X86-SSE2-NEXT: pcmpgtd %xmm1, %xmm3 +; X86-SSE2-NEXT: pcmpeqd %xmm1, %xmm0 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[0,0,2,2] +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] +; X86-SSE2-NEXT: pand %xmm1, %xmm0 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[1,1,3,3] +; X86-SSE2-NEXT: por %xmm0, %xmm1 +; X86-SSE2-NEXT: pand %xmm1, %xmm4 +; X86-SSE2-NEXT: pandn %xmm2, %xmm1 +; X86-SSE2-NEXT: por %xmm4, %xmm1 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[3,3,3,3] +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,1,1] +; X86-SSE2-NEXT: por %xmm0, %xmm1 +; X86-SSE2-NEXT: movd %xmm1, %eax +; X86-SSE2-NEXT: notl %eax +; X86-SSE2-NEXT: shrl $31, %eax +; X86-SSE2-NEXT: xorl %edx, %edx +; X86-SSE2-NEXT: retl +; +; X64-SSE-LABEL: reduce_umax_v8i64_signbit_not: +; X64-SSE: # %bb.0: +; X64-SSE-NEXT: movapd (%rdi), %xmm0 +; X64-SSE-NEXT: movapd 16(%rdi), %xmm1 +; X64-SSE-NEXT: movapd 32(%rdi), %xmm2 +; X64-SSE-NEXT: movapd 48(%rdi), %xmm3 +; X64-SSE-NEXT: andnpd 32(%rsi), %xmm2 +; X64-SSE-NEXT: andnpd (%rsi), %xmm0 +; X64-SSE-NEXT: orpd %xmm2, %xmm0 +; X64-SSE-NEXT: andnpd 48(%rsi), %xmm3 +; X64-SSE-NEXT: andnpd 16(%rsi), %xmm1 +; X64-SSE-NEXT: orpd %xmm3, %xmm1 +; X64-SSE-NEXT: orpd %xmm0, %xmm1 +; X64-SSE-NEXT: movmskpd %xmm1, %ecx +; X64-SSE-NEXT: xorl %eax, %eax +; X64-SSE-NEXT: testl %ecx, %ecx +; X64-SSE-NEXT: sete %al +; X64-SSE-NEXT: retq +; +; X86-SSE41-LABEL: reduce_umax_v8i64_signbit_not: +; X86-SSE41: # %bb.0: +; X86-SSE41-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE41-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE41-NEXT: movdqa 48(%ecx), %xmm1 +; X86-SSE41-NEXT: movdqa 32(%ecx), %xmm2 +; X86-SSE41-NEXT: movdqa 16(%ecx), %xmm4 +; X86-SSE41-NEXT: pandn 16(%eax), %xmm4 +; X86-SSE41-NEXT: pandn 48(%eax), %xmm1 +; X86-SSE41-NEXT: movdqa {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648] +; X86-SSE41-NEXT: movdqa %xmm1, %xmm0 +; X86-SSE41-NEXT: pxor %xmm3, %xmm0 +; X86-SSE41-NEXT: movdqa %xmm4, %xmm5 +; X86-SSE41-NEXT: pxor %xmm3, %xmm5 +; X86-SSE41-NEXT: movdqa %xmm5, %xmm6 +; X86-SSE41-NEXT: pcmpgtd %xmm0, %xmm6 +; X86-SSE41-NEXT: pcmpeqd %xmm0, %xmm5 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm6[0,0,2,2] +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm7 = xmm5[1,1,3,3] +; X86-SSE41-NEXT: pand %xmm0, %xmm7 +; X86-SSE41-NEXT: movdqa (%ecx), %xmm5 +; X86-SSE41-NEXT: pandn (%eax), %xmm5 +; X86-SSE41-NEXT: pandn 32(%eax), %xmm2 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm6[1,1,3,3] +; X86-SSE41-NEXT: por %xmm7, %xmm0 +; X86-SSE41-NEXT: blendvpd %xmm0, %xmm4, %xmm1 +; X86-SSE41-NEXT: movdqa %xmm2, %xmm0 +; X86-SSE41-NEXT: pxor %xmm3, %xmm0 +; X86-SSE41-NEXT: movdqa %xmm5, %xmm4 +; X86-SSE41-NEXT: pxor %xmm3, %xmm4 +; X86-SSE41-NEXT: movdqa %xmm4, %xmm6 +; X86-SSE41-NEXT: pcmpgtd %xmm0, %xmm6 +; X86-SSE41-NEXT: pcmpeqd %xmm0, %xmm4 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm6[0,0,2,2] +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm4 = xmm4[1,1,3,3] +; X86-SSE41-NEXT: pand %xmm0, %xmm4 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm6[1,1,3,3] +; X86-SSE41-NEXT: por %xmm4, %xmm0 +; X86-SSE41-NEXT: blendvpd %xmm0, %xmm5, %xmm2 +; X86-SSE41-NEXT: movapd %xmm1, %xmm0 +; X86-SSE41-NEXT: xorpd %xmm3, %xmm0 +; X86-SSE41-NEXT: xorpd %xmm2, %xmm3 +; X86-SSE41-NEXT: movapd %xmm3, %xmm4 +; X86-SSE41-NEXT: pcmpgtd %xmm0, %xmm4 +; X86-SSE41-NEXT: pcmpeqd %xmm0, %xmm3 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm4[0,0,2,2] +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,3,3] +; X86-SSE41-NEXT: pand %xmm0, %xmm3 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm4[1,1,3,3] +; X86-SSE41-NEXT: por %xmm3, %xmm0 +; X86-SSE41-NEXT: blendvpd %xmm0, %xmm2, %xmm1 +; X86-SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; X86-SSE41-NEXT: por %xmm1, %xmm0 +; X86-SSE41-NEXT: pextrd $1, %xmm0, %eax +; X86-SSE41-NEXT: notl %eax +; X86-SSE41-NEXT: shrl $31, %eax +; X86-SSE41-NEXT: xorl %edx, %edx +; X86-SSE41-NEXT: retl +; +; X86-SSE42-LABEL: reduce_umax_v8i64_signbit_not: +; X86-SSE42: # %bb.0: +; X86-SSE42-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE42-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE42-NEXT: movdqa 48(%ecx), %xmm2 +; X86-SSE42-NEXT: movdqa 32(%ecx), %xmm3 +; X86-SSE42-NEXT: movdqa (%ecx), %xmm4 +; X86-SSE42-NEXT: movdqa 16(%ecx), %xmm5 +; X86-SSE42-NEXT: pandn (%eax), %xmm4 +; X86-SSE42-NEXT: pandn 32(%eax), %xmm3 +; X86-SSE42-NEXT: pandn 16(%eax), %xmm5 +; X86-SSE42-NEXT: pandn 48(%eax), %xmm2 +; X86-SSE42-NEXT: movdqa {{.*#+}} xmm1 = [0,2147483648,0,2147483648] +; X86-SSE42-NEXT: movdqa %xmm2, %xmm6 +; X86-SSE42-NEXT: pxor %xmm1, %xmm6 +; X86-SSE42-NEXT: movdqa %xmm5, %xmm0 +; X86-SSE42-NEXT: pxor %xmm1, %xmm0 +; X86-SSE42-NEXT: pcmpgtq %xmm6, %xmm0 +; X86-SSE42-NEXT: blendvpd %xmm0, %xmm5, %xmm2 +; X86-SSE42-NEXT: movapd %xmm2, %xmm5 +; X86-SSE42-NEXT: xorpd %xmm1, %xmm5 +; X86-SSE42-NEXT: movdqa %xmm3, %xmm6 +; X86-SSE42-NEXT: pxor %xmm1, %xmm6 +; X86-SSE42-NEXT: movdqa %xmm4, %xmm0 +; X86-SSE42-NEXT: pxor %xmm1, %xmm0 +; X86-SSE42-NEXT: pcmpgtq %xmm6, %xmm0 +; X86-SSE42-NEXT: blendvpd %xmm0, %xmm4, %xmm3 +; X86-SSE42-NEXT: xorpd %xmm3, %xmm1 +; X86-SSE42-NEXT: pcmpgtq %xmm5, %xmm1 +; X86-SSE42-NEXT: movdqa %xmm1, %xmm0 +; X86-SSE42-NEXT: blendvpd %xmm0, %xmm3, %xmm2 +; X86-SSE42-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; X86-SSE42-NEXT: por %xmm2, %xmm0 +; X86-SSE42-NEXT: pextrd $1, %xmm0, %eax +; X86-SSE42-NEXT: notl %eax +; X86-SSE42-NEXT: shrl $31, %eax +; X86-SSE42-NEXT: xorl %edx, %edx +; X86-SSE42-NEXT: retl +; +; X86-AVX1-LABEL: reduce_umax_v8i64_signbit_not: +; X86-AVX1: # %bb.0: +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX1-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX1-NEXT: vmovaps (%ecx), %ymm0 +; X86-AVX1-NEXT: vmovaps 32(%ecx), %ymm1 +; X86-AVX1-NEXT: vandnps (%eax), %ymm0, %ymm0 +; X86-AVX1-NEXT: vandnps 32(%eax), %ymm1, %ymm1 +; X86-AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; X86-AVX1-NEXT: vmovddup {{.*#+}} xmm3 = [0,2147483648,0,2147483648] +; X86-AVX1-NEXT: # xmm3 = mem[0,0] +; X86-AVX1-NEXT: vxorps %xmm3, %xmm2, %xmm4 +; X86-AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; X86-AVX1-NEXT: vxorps %xmm3, %xmm5, %xmm6 +; X86-AVX1-NEXT: vpcmpgtq %xmm4, %xmm6, %xmm4 +; X86-AVX1-NEXT: vblendvpd %xmm4, %xmm5, %xmm2, %xmm2 +; X86-AVX1-NEXT: vxorpd %xmm3, %xmm2, %xmm4 +; X86-AVX1-NEXT: vxorps %xmm3, %xmm1, %xmm5 +; X86-AVX1-NEXT: vxorps %xmm3, %xmm0, %xmm6 +; X86-AVX1-NEXT: vpcmpgtq %xmm5, %xmm6, %xmm5 +; X86-AVX1-NEXT: vblendvpd %xmm5, %xmm0, %xmm1, %xmm0 +; X86-AVX1-NEXT: vxorpd %xmm3, %xmm0, %xmm1 +; X86-AVX1-NEXT: vpcmpgtq %xmm4, %xmm1, %xmm1 +; X86-AVX1-NEXT: vblendvpd %xmm1, %xmm0, %xmm2, %xmm0 +; X86-AVX1-NEXT: vshufps {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X86-AVX1-NEXT: vorpd %xmm0, %xmm1, %xmm0 +; X86-AVX1-NEXT: vextractps $1, %xmm0, %eax +; X86-AVX1-NEXT: notl %eax +; X86-AVX1-NEXT: shrl $31, %eax +; X86-AVX1-NEXT: xorl %edx, %edx +; X86-AVX1-NEXT: vzeroupper +; X86-AVX1-NEXT: retl +; +; X64-AVX-LABEL: reduce_umax_v8i64_signbit_not: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovapd (%rdi), %ymm0 +; X64-AVX-NEXT: vmovapd 32(%rdi), %ymm1 +; X64-AVX-NEXT: vandnpd 32(%rsi), %ymm1, %ymm1 +; X64-AVX-NEXT: vandnpd (%rsi), %ymm0, %ymm0 +; X64-AVX-NEXT: vorpd %ymm1, %ymm0, %ymm0 +; X64-AVX-NEXT: xorl %eax, %eax +; X64-AVX-NEXT: vtestpd %ymm0, %ymm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: vzeroupper +; X64-AVX-NEXT: retq +; +; X86-AVX2-LABEL: reduce_umax_v8i64_signbit_not: +; X86-AVX2: # %bb.0: +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-AVX2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-AVX2-NEXT: vmovdqa (%ecx), %ymm0 +; X86-AVX2-NEXT: vmovdqa 32(%ecx), %ymm1 +; X86-AVX2-NEXT: vpandn (%eax), %ymm0, %ymm0 +; X86-AVX2-NEXT: vpandn 32(%eax), %ymm1, %ymm1 +; X86-AVX2-NEXT: vpbroadcastq {{.*#+}} ymm2 = [0,2147483648,0,2147483648,0,2147483648,0,2147483648] +; X86-AVX2-NEXT: vpxor %ymm2, %ymm1, %ymm3 +; X86-AVX2-NEXT: vpxor %ymm2, %ymm0, %ymm4 +; X86-AVX2-NEXT: vpcmpgtq %ymm3, %ymm4, %ymm3 +; X86-AVX2-NEXT: vblendvpd %ymm3, %ymm0, %ymm1, %ymm0 +; X86-AVX2-NEXT: vextractf128 $1, %ymm0, %xmm1 +; X86-AVX2-NEXT: vxorpd %xmm2, %xmm1, %xmm3 +; X86-AVX2-NEXT: vxorpd %xmm2, %xmm0, %xmm2 +; X86-AVX2-NEXT: vpcmpgtq %xmm3, %xmm2, %xmm2 +; X86-AVX2-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0 +; X86-AVX2-NEXT: vshufps {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X86-AVX2-NEXT: vorpd %xmm0, %xmm1, %xmm0 +; X86-AVX2-NEXT: vextractps $1, %xmm0, %eax +; X86-AVX2-NEXT: notl %eax +; X86-AVX2-NEXT: shrl $31, %eax +; X86-AVX2-NEXT: xorl %edx, %edx +; X86-AVX2-NEXT: vzeroupper +; X86-AVX2-NEXT: retl +; +; AVX512BW-LABEL: reduce_umax_v8i64_signbit_not: +; AVX512BW: # %bb.0: +; AVX512BW-NEXT: vmovdqa64 (%rdi), %zmm0 +; AVX512BW-NEXT: vpandnq (%rsi), %zmm0, %zmm0 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm0, %ymm1 +; AVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512BW-NEXT: xorl %eax, %eax +; AVX512BW-NEXT: vtestpd %ymm0, %ymm0 +; AVX512BW-NEXT: sete %al +; AVX512BW-NEXT: vzeroupper +; AVX512BW-NEXT: retq +; +; AVX512BWVL-LABEL: reduce_umax_v8i64_signbit_not: +; AVX512BWVL: # %bb.0: +; AVX512BWVL-NEXT: vmovapd (%rdi), %zmm0 +; AVX512BWVL-NEXT: vandnpd (%rsi), %zmm0, %zmm0 +; AVX512BWVL-NEXT: vextractf64x4 $1, %zmm0, %ymm1 +; AVX512BWVL-NEXT: vorpd %ymm1, %ymm0, %ymm0 +; AVX512BWVL-NEXT: xorl %eax, %eax +; AVX512BWVL-NEXT: vtestpd %ymm0, %ymm0 +; AVX512BWVL-NEXT: sete %al +; AVX512BWVL-NEXT: vzeroupper +; AVX512BWVL-NEXT: retq + %a = load <8 x i64>, ptr %pa + %b = load <8 x i64>, ptr %pb + %a.not = xor <8 x i64> %a, splat (i64 -1) + %and = and <8 x i64> %b, %a.not + %rdx = call i64 @llvm.vector.reduce.umax.v8i64(<8 x i64> %and) + %cmp = icmp sgt i64 %rdx, -1 + %res = zext i1 %cmp to i64 + ret i64 %res +}