diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4344,7 +4344,9 @@ if ((HandOpcode == ISD::BITCAST || HandOpcode == ISD::SCALAR_TO_VECTOR) && Level <= AfterLegalizeTypes) { // Input types must be integer and the same. - if (XVT.isInteger() && XVT == Y.getValueType()) { + if (XVT.isInteger() && XVT == Y.getValueType() && + !(VT.isVector() && TLI.isTypeLegal(VT) && + !XVT.isVector() && !TLI.isTypeLegal(XVT))) { SDValue Logic = DAG.getNode(LogicOpcode, DL, XVT, X, Y); return DAG.getNode(HandOpcode, DL, VT, Logic); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -42546,17 +42546,29 @@ !IsOrXorXorCCZero) return SDValue(); - // TODO: Use PXOR + PTEST for SSE4.1 or later? EVT VT = SetCC->getValueType(0); SDLoc DL(SetCC); + bool HasAVX = Subtarget.hasAVX(); + + // Use XOR (plus OR) and PTEST after SSE4.1 and before AVX512. + // Otherwise use PCMPEQ (plus AND) and mask testing. if ((OpSize == 128 && Subtarget.hasSSE2()) || - (OpSize == 256 && Subtarget.hasAVX2()) || + (OpSize == 256 && HasAVX) || (OpSize == 512 && Subtarget.useAVX512Regs())) { - auto BW = Subtarget.hasBWI(); - EVT VecVT = OpSize == 512 ? (BW ? MVT::v64i8 : MVT::v16i32) : - OpSize == 256 ? MVT::v32i8 : - MVT::v16i8; - EVT CmpVT = OpSize == 512 ? (BW ? MVT::v64i1 : MVT::v16i1) : VecVT; + bool HasPT = Subtarget.hasSSE41(); + EVT VecVT = MVT::v16i8; + EVT CmpVT = MVT::v16i8; + if (OpSize == 256) + VecVT = CmpVT = MVT::v32i8; + if (OpSize == 512) { + if (Subtarget.hasBWI()) { + VecVT = MVT::v64i8; + CmpVT = MVT::v64i1; + } else { + VecVT = MVT::v16i32; + CmpVT = MVT::v16i1; + } + } SDValue Cmp; if (IsOrXorXorCCZero) { @@ -42568,21 +42580,38 @@ SDValue B = DAG.getBitcast(VecVT, X.getOperand(0).getOperand(1)); SDValue C = DAG.getBitcast(VecVT, X.getOperand(1).getOperand(0)); SDValue D = DAG.getBitcast(VecVT, X.getOperand(1).getOperand(1)); - SDValue Cmp1 = DAG.getSetCC(DL, CmpVT, A, B, ISD::SETEQ); - SDValue Cmp2 = DAG.getSetCC(DL, CmpVT, C, D, ISD::SETEQ); - Cmp = DAG.getNode(ISD::AND, DL, CmpVT, Cmp1, Cmp2); + if (VecVT == CmpVT && HasPT) { + SDValue Cmp1 = DAG.getNode(ISD::XOR, DL, VecVT, A, B); + SDValue Cmp2 = DAG.getNode(ISD::XOR, DL, VecVT, C, D); + Cmp = DAG.getNode(ISD::OR, DL, VecVT, Cmp1, Cmp2); + } else { + SDValue Cmp1 = DAG.getSetCC(DL, CmpVT, A, B, ISD::SETEQ); + SDValue Cmp2 = DAG.getSetCC(DL, CmpVT, C, D, ISD::SETEQ); + Cmp = DAG.getNode(ISD::AND, DL, CmpVT, Cmp1, Cmp2); + } } else { SDValue VecX = DAG.getBitcast(VecVT, X); SDValue VecY = DAG.getBitcast(VecVT, Y); - Cmp = DAG.getSetCC(DL, CmpVT, VecX, VecY, ISD::SETEQ); + if (VecVT == CmpVT && HasPT) { + Cmp = DAG.getNode(ISD::XOR, DL, VecVT, VecX, VecY); + } else { + Cmp = DAG.getSetCC(DL, CmpVT, VecX, VecY, ISD::SETEQ); + } } // For 512-bits we want to emit a setcc that will lower to kortest. - if (OpSize == 512 && BW) - return DAG.getSetCC(DL, VT, DAG.getBitcast(MVT::i64, Cmp), - DAG.getConstant(0xFFFFFFFFFFFFFFFF, DL, MVT::i64), CC); - if (OpSize == 512) - return DAG.getSetCC(DL, VT, DAG.getBitcast(MVT::i16, Cmp), - DAG.getConstant(0xFFFF, DL, MVT::i16), CC); + if (VecVT != CmpVT) { + EVT KRegVT = CmpVT == MVT::v64i1 ? MVT::i64 : MVT::i16; + SDValue Mask = DAG.getAllOnesConstant(DL, KRegVT); + return DAG.getSetCC(DL, VT, DAG.getBitcast(KRegVT, Cmp), Mask, CC); + } + if (HasPT) { + SDValue BCCmp = DAG.getBitcast(OpSize == 256 ? MVT::v4i64 : MVT::v2i64, + Cmp); + SDValue PT = DAG.getNode(X86ISD::PTEST, DL, MVT::i32, BCCmp, BCCmp); + X86::CondCode X86CC = CC == ISD::SETEQ ? X86::COND_E : X86::COND_NE; + SDValue SetCC = getSETCC(X86CC, PT, DL, DAG); + return DAG.getNode(ISD::TRUNCATE, DL, VT, SetCC.getValue(0)); + } // If all bytes match (bitmask is 0x(FFFF)FFFF), that's equality. // setcc i128 X, Y, eq --> setcc (pmovmskb (pcmpeqb X, Y)), 0xFFFF, eq // setcc i128 X, Y, ne --> setcc (pmovmskb (pcmpeqb X, Y)), 0xFFFF, ne diff --git a/llvm/test/CodeGen/X86/memcmp-minsize.ll b/test/CodeGen/X86/memcmp-minsize.ll --- a/llvm/test/CodeGen/X86/memcmp-minsize.ll +++ b/test/CodeGen/X86/memcmp-minsize.ll @@ -2,7 +2,8 @@ ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=cmov | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X86 --check-prefix=X86-SSE2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 --check-prefix=X64-SSE2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX2 ; This tests codegen time inlining/optimization of memcmp ; rdar://6480398 @@ -426,14 +427,13 @@ ; X64-SSE2-NEXT: setne %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length16_eq: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: setne %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length16_eq: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: setne %al +; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16) nounwind %cmp = icmp ne i32 %call, 0 ret i1 %cmp @@ -471,14 +471,13 @@ ; X64-SSE2-NEXT: sete %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length16_eq_const: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: sete %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length16_eq_const: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: retq %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 16) nounwind %c = icmp eq i32 %m, 0 ret i1 %c @@ -609,12 +608,20 @@ ; X64-SSE2-NEXT: popq %rcx ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length32_eq: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovups (%rdi), %ymm0 +; X64-AVX1-NEXT: vxorps (%rsi), %ymm0, %ymm0 +; X64-AVX1-NEXT: vptest %ymm0, %ymm +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length32_eq: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm ; X64-AVX2-NEXT: sete %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -648,12 +655,20 @@ ; X64-SSE2-NEXT: popq %rcx ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length32_eq_const: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovups (%rdi), %ymm0 +; X64-AVX1-NEXT: vxorps {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX1-NEXT: vptest %ymm0, %ymm0 +; X64-AVX1-NEXT: setne %al +; X64-AVX1-NEXT: vzeroupper +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length32_eq_const: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: setne %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq diff --git a/llvm/test/CodeGen/X86/memcmp-optsize.ll b/test/CodeGen/X86/memcmp-optsize.ll --- a/llvm/test/CodeGen/X86/memcmp-optsize.ll +++ b/test/CodeGen/X86/memcmp-optsize.ll @@ -2,7 +2,8 @@ ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=cmov | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X86 --check-prefix=X86-SSE2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 --check-prefix=X64-SSE2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX2 ; This tests codegen time inlining/optimization of memcmp ; rdar://6480398 @@ -560,14 +561,13 @@ ; X64-SSE2-NEXT: setne %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length16_eq: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: setne %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length16_eq: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: setne %al +; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16) nounwind %cmp = icmp ne i32 %call, 0 ret i1 %cmp @@ -605,14 +605,13 @@ ; X64-SSE2-NEXT: sete %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length16_eq_const: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: sete %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length16_eq_const: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: retq %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 16) nounwind %c = icmp eq i32 %m, 0 ret i1 %c @@ -682,18 +681,17 @@ ; X64-SSE2-NEXT: sete %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length24_eq: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; X64-AVX2-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero -; X64-AVX2-NEXT: vpcmpeqb %xmm2, %xmm1, %xmm1 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: sete %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length24_eq: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vmovq 16(%rdi), %xmm1 +; X64-AVX-NEXT: vmovq 16(%rsi), %xmm2 +; X64-AVX-NEXT: vpxor %xmm2, %xmm1, %xmm1 +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: sete %al +; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 24) nounwind %cmp = icmp eq i32 %call, 0 ret i1 %cmp @@ -737,17 +735,16 @@ ; X64-SSE2-NEXT: setne %al ; X64-SSE2-NEXT: retq ; -; X64-AVX2-LABEL: length24_eq_const: -; X64-AVX2: # %bb.0: -; X64-AVX2-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX2-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %xmm1, %xmm1 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX2-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX2-NEXT: cmpl $65535, %eax # imm = 0xFFFF -; X64-AVX2-NEXT: setne %al -; X64-AVX2-NEXT: retq +; X64-AVX-LABEL: length24_eq_const: +; X64-AVX: # %bb.0: +; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX-NEXT: vmovq 16(%rdi), %xmm1 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm1, %xmm1 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 +; X64-AVX-NEXT: setne %al +; X64-AVX-NEXT: retq %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 24) nounwind %c = icmp ne i32 %m, 0 ret i1 %c @@ -817,12 +814,22 @@ ; X64-SSE2-NEXT: sete %al ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length32_eq: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX1-NEXT: vmovdqu 16(%rdi), %xmm1 +; X64-AVX1-NEXT: vpxor 16(%rsi), %xmm1, %xmm1 +; X64-AVX1-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vptest %xmm0, %xmm0 +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length32_eq: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: sete %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -869,12 +876,22 @@ ; X64-SSE2-NEXT: setne %al ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length32_eq_const: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: vmovdqu (%rdi), %xmm0 +; X64-AVX1-NEXT: vmovdqu 16(%rdi), %xmm1 +; X64-AVX1-NEXT: vpxor {{.*}}(%rip), %xmm1, %xmm1 +; X64-AVX1-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vptest %xmm0, %xmm0 +; X64-AVX1-NEXT: setne %al +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length32_eq_const: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: setne %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -925,15 +942,24 @@ ; X64-SSE2-NEXT: popq %rcx ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length64_eq: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: pushq %rax +; X64-AVX1-NEXT: movl $64, %edx +; X64-AVX1-NEXT: callq memcmp +; X64-AVX1-NEXT: testl %eax, %eax +; X64-AVX1-NEXT: setne %al +; X64-AVX1-NEXT: popq %rcx +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length64_eq: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 ; X64-AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 -; X64-AVX2-NEXT: vpcmpeqb 32(%rsi), %ymm1, %ymm1 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: setne %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -966,15 +992,25 @@ ; X64-SSE2-NEXT: popq %rcx ; X64-SSE2-NEXT: retq ; +; X64-AVX1-LABEL: length64_eq_const: +; X64-AVX1: # %bb.0: +; X64-AVX1-NEXT: pushq %rax +; X64-AVX1-NEXT: movl $.L.str, %esi +; X64-AVX1-NEXT: movl $64, %edx +; X64-AVX1-NEXT: callq memcmp +; X64-AVX1-NEXT: testl %eax, %eax +; X64-AVX1-NEXT: sete %al +; X64-AVX1-NEXT: popq %rcx +; X64-AVX1-NEXT: retq +; ; X64-AVX2-LABEL: length64_eq_const: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 ; X64-AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm1, %ymm1 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: sete %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq diff --git a/llvm/test/CodeGen/X86/memcmp.ll b/test/CodeGen/X86/memcmp.ll --- a/llvm/test/CodeGen/X86/memcmp.ll +++ b/test/CodeGen/X86/memcmp.ll @@ -1003,9 +1003,8 @@ ; X64-AVX-LABEL: length16_eq: ; X64-AVX: # %bb.0: ; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 ; X64-AVX-NEXT: setne %al ; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16) nounwind @@ -1060,9 +1059,8 @@ ; X64-AVX-LABEL: length16_eq_const: ; X64-AVX: # %bb.0: ; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 ; X64-AVX-NEXT: sete %al ; X64-AVX-NEXT: retq %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 16) nounwind @@ -1149,13 +1147,12 @@ ; X64-AVX-LABEL: length24_eq: ; X64-AVX: # %bb.0: ; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; X64-AVX-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero -; X64-AVX-NEXT: vpcmpeqb %xmm2, %xmm1, %xmm1 -; X64-AVX-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX-NEXT: vmovq 16(%rdi), %xmm1 +; X64-AVX-NEXT: vmovq 16(%rsi), %xmm2 +; X64-AVX-NEXT: vpxor %xmm2, %xmm1, %xmm1 +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 ; X64-AVX-NEXT: sete %al ; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 24) nounwind @@ -1216,12 +1213,11 @@ ; X64-AVX-LABEL: length24_eq_const: ; X64-AVX: # %bb.0: ; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 -; X64-AVX-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; X64-AVX-NEXT: vpcmpeqb {{.*}}(%rip), %xmm1, %xmm1 -; X64-AVX-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX-NEXT: vmovq 16(%rdi), %xmm1 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm1, %xmm1 +; X64-AVX-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 ; X64-AVX-NEXT: setne %al ; X64-AVX-NEXT: retq %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 24) nounwind @@ -1309,20 +1305,18 @@ ; X64-AVX1: # %bb.0: ; X64-AVX1-NEXT: vmovdqu (%rdi), %xmm0 ; X64-AVX1-NEXT: vmovdqu 16(%rdi), %xmm1 -; X64-AVX1-NEXT: vpcmpeqb 16(%rsi), %xmm1, %xmm1 -; X64-AVX1-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX1-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX1-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX1-NEXT: vpxor 16(%rsi), %xmm1, %xmm1 +; X64-AVX1-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vptest %xmm0, %xmm0 ; X64-AVX1-NEXT: sete %al ; X64-AVX1-NEXT: retq ; ; X64-AVX2-LABEL: length32_eq: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: sete %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -1390,11 +1384,10 @@ ; X64-AVX: # %bb.0: ; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0 ; X64-AVX-NEXT: vmovdqu 16(%rdi), %xmm1 -; X64-AVX-NEXT: vpcmpeqb 16(%rsi), %xmm1, %xmm1 -; X64-AVX-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; X64-AVX-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX-NEXT: vpxor 16(%rsi), %xmm1, %xmm1 +; X64-AVX-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; X64-AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX-NEXT: vptest %xmm0, %xmm0 ; X64-AVX-NEXT: sete %al ; X64-AVX-NEXT: retq %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 32) nounwind @@ -1456,20 +1449,18 @@ ; X64-AVX1: # %bb.0: ; X64-AVX1-NEXT: vmovdqu (%rdi), %xmm0 ; X64-AVX1-NEXT: vmovdqu 16(%rdi), %xmm1 -; X64-AVX1-NEXT: vpcmpeqb {{.*}}(%rip), %xmm1, %xmm1 -; X64-AVX1-NEXT: vpcmpeqb {{.*}}(%rip), %xmm0, %xmm0 -; X64-AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 -; X64-AVX1-NEXT: vpmovmskb %xmm0, %eax -; X64-AVX1-NEXT: cmpl $65535, %eax # imm = 0xFFFF +; X64-AVX1-NEXT: vpxor {{.*}}(%rip), %xmm1, %xmm1 +; X64-AVX1-NEXT: vpxor {{.*}}(%rip), %xmm0, %xmm0 +; X64-AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; X64-AVX1-NEXT: vptest %xmm0, %xmm0 ; X64-AVX1-NEXT: setne %al ; X64-AVX1-NEXT: retq ; ; X64-AVX2-LABEL: length32_eq_const: ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: setne %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -1534,11 +1525,10 @@ ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 ; X64-AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 -; X64-AVX2-NEXT: vpcmpeqb 32(%rsi), %ymm1, %ymm1 -; X64-AVX2-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: setne %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq @@ -1604,11 +1594,10 @@ ; X64-AVX2: # %bb.0: ; X64-AVX2-NEXT: vmovdqu (%rdi), %ymm0 ; X64-AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm1, %ymm1 -; X64-AVX2-NEXT: vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0 -; X64-AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 -; X64-AVX2-NEXT: vpmovmskb %ymm0, %eax -; X64-AVX2-NEXT: cmpl $-1, %eax +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm1, %ymm1 +; X64-AVX2-NEXT: vpxor {{.*}}(%rip), %ymm0, %ymm0 +; X64-AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; X64-AVX2-NEXT: vptest %ymm0, %ymm0 ; X64-AVX2-NEXT: sete %al ; X64-AVX2-NEXT: vzeroupper ; X64-AVX2-NEXT: retq diff --git a/llvm/test/CodeGen/X86/setcc-wide-types.ll b/test/CodeGen/X86/setcc-wide-types.ll --- a/llvm/test/CodeGen/X86/setcc-wide-types.ll +++ b/test/CodeGen/X86/setcc-wide-types.ll @@ -1,9 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=ANY --check-prefix=NO512 --check-prefix=SSE2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefix=ANY --check-prefix=NO512 --check-prefix=SSE41 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=ANY --check-prefix=NO512 --check-prefix=AVXANY --check-prefix=AVX1 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=ANY --check-prefix=NO512 --check-prefix=AVXANY --check-prefix=AVX256 --check-prefix=AVX2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefix=ANY --check-prefix=AVXANY --check-prefix=AVX256 --check-prefix=AVX512 --check-prefix=AVX512F -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefix=ANY --check-prefix=AVXANY --check-prefix=AVX256 --check-prefix=AVX512 --check-prefix=AVX512BW +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=ANY --check-prefix=NO512 --check-prefix=AVXANY --check-prefix=AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefix=ANY --check-prefix=AVXANY --check-prefix=AVX512 --check-prefix=AVX512F +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefix=ANY --check-prefix=AVXANY --check-prefix=AVX512 --check-prefix=AVX512BW ; Equality checks of 128/256-bit values can use PMOVMSK or PTEST to avoid scalarization. @@ -17,12 +18,19 @@ ; SSE2-NEXT: setne %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: ne_i128: +; SSE41: # %bb.0: +; SSE41-NEXT: pxor %xmm1, %xmm0 +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: ptest %xmm0, %xmm0 +; SSE41-NEXT: setne %al +; SSE41-NEXT: retq +; ; AVXANY-LABEL: ne_i128: ; AVXANY: # %bb.0: -; AVXANY-NEXT: vpcmpeqb %xmm1, %xmm0, %xmm0 -; AVXANY-NEXT: vpmovmskb %xmm0, %ecx +; AVXANY-NEXT: vpxor %xmm1, %xmm0, %xmm0 ; AVXANY-NEXT: xorl %eax, %eax -; AVXANY-NEXT: cmpl $65535, %ecx # imm = 0xFFFF +; AVXANY-NEXT: vptest %xmm0, %xmm0 ; AVXANY-NEXT: setne %al ; AVXANY-NEXT: retq %bcx = bitcast <2 x i64> %x to i128 @@ -42,12 +50,19 @@ ; SSE2-NEXT: sete %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: eq_i128: +; SSE41: # %bb.0: +; SSE41-NEXT: pxor %xmm1, %xmm0 +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: ptest %xmm0, %xmm0 +; SSE41-NEXT: sete %al +; SSE41-NEXT: retq +; ; AVXANY-LABEL: eq_i128: ; AVXANY: # %bb.0: -; AVXANY-NEXT: vpcmpeqb %xmm1, %xmm0, %xmm0 -; AVXANY-NEXT: vpmovmskb %xmm0, %ecx +; AVXANY-NEXT: vpxor %xmm1, %xmm0, %xmm0 ; AVXANY-NEXT: xorl %eax, %eax -; AVXANY-NEXT: cmpl $65535, %ecx # imm = 0xFFFF +; AVXANY-NEXT: vptest %xmm0, %xmm0 ; AVXANY-NEXT: sete %al ; AVXANY-NEXT: retq %bcx = bitcast <2 x i64> %x to i128 @@ -83,39 +98,53 @@ ; SSE2-NEXT: setne %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: ne_i256: +; SSE41: # %bb.0: +; SSE41-NEXT: movq %xmm0, %rax +; SSE41-NEXT: movq %xmm1, %rcx +; SSE41-NEXT: pextrq $1, %xmm0, %rdx +; SSE41-NEXT: pextrq $1, %xmm1, %r8 +; SSE41-NEXT: movq %xmm2, %rdi +; SSE41-NEXT: xorq %rax, %rdi +; SSE41-NEXT: movq %xmm3, %rsi +; SSE41-NEXT: xorq %rcx, %rsi +; SSE41-NEXT: orq %rdi, %rsi +; SSE41-NEXT: pextrq $1, %xmm2, %rax +; SSE41-NEXT: xorq %rdx, %rax +; SSE41-NEXT: pextrq $1, %xmm3, %rcx +; SSE41-NEXT: xorq %r8, %rcx +; SSE41-NEXT: orq %rax, %rcx +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rsi, %rcx +; SSE41-NEXT: setne %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: ne_i256: ; AVX1: # %bb.0: -; AVX1-NEXT: vmovq %xmm0, %rax -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 -; AVX1-NEXT: vmovq %xmm2, %rcx -; AVX1-NEXT: vpextrq $1, %xmm0, %rdx -; AVX1-NEXT: vpextrq $1, %xmm2, %r8 -; AVX1-NEXT: vmovq %xmm1, %rdi -; AVX1-NEXT: xorq %rax, %rdi -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 -; AVX1-NEXT: vmovq %xmm0, %rsi -; AVX1-NEXT: xorq %rcx, %rsi -; AVX1-NEXT: orq %rdi, %rsi -; AVX1-NEXT: vpextrq $1, %xmm1, %rax -; AVX1-NEXT: xorq %rdx, %rax -; AVX1-NEXT: vpextrq $1, %xmm0, %rcx -; AVX1-NEXT: xorq %r8, %rcx -; AVX1-NEXT: orq %rax, %rcx +; AVX1-NEXT: vxorps %ymm1, %ymm0, %ymm0 ; AVX1-NEXT: xorl %eax, %eax -; AVX1-NEXT: orq %rsi, %rcx +; AVX1-NEXT: vptest %ymm0, %ymm0 ; AVX1-NEXT: setne %al ; AVX1-NEXT: vzeroupper ; AVX1-NEXT: retq ; -; AVX256-LABEL: ne_i256: -; AVX256: # %bb.0: -; AVX256-NEXT: vpcmpeqb %ymm1, %ymm0, %ymm0 -; AVX256-NEXT: vpmovmskb %ymm0, %ecx -; AVX256-NEXT: xorl %eax, %eax -; AVX256-NEXT: cmpl $-1, %ecx -; AVX256-NEXT: setne %al -; AVX256-NEXT: vzeroupper -; AVX256-NEXT: retq +; AVX2-LABEL: ne_i256: +; AVX2: # %bb.0: +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: xorl %eax, %eax +; AVX2-NEXT: vptest %ymm0, %ymm0 +; AVX2-NEXT: setne %al +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: ne_i256: +; AVX512: # %bb.0: +; AVX512-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vptest %ymm0, %ymm0 +; AVX512-NEXT: setne %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %bcx = bitcast <4 x i64> %x to i256 %bcy = bitcast <4 x i64> %y to i256 %cmp = icmp ne i256 %bcx, %bcy @@ -149,39 +178,53 @@ ; SSE2-NEXT: sete %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: eq_i256: +; SSE41: # %bb.0: +; SSE41-NEXT: movq %xmm0, %rax +; SSE41-NEXT: movq %xmm1, %rcx +; SSE41-NEXT: pextrq $1, %xmm0, %rdx +; SSE41-NEXT: pextrq $1, %xmm1, %r8 +; SSE41-NEXT: movq %xmm2, %rdi +; SSE41-NEXT: xorq %rax, %rdi +; SSE41-NEXT: movq %xmm3, %rsi +; SSE41-NEXT: xorq %rcx, %rsi +; SSE41-NEXT: orq %rdi, %rsi +; SSE41-NEXT: pextrq $1, %xmm2, %rax +; SSE41-NEXT: xorq %rdx, %rax +; SSE41-NEXT: pextrq $1, %xmm3, %rcx +; SSE41-NEXT: xorq %r8, %rcx +; SSE41-NEXT: orq %rax, %rcx +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rsi, %rcx +; SSE41-NEXT: sete %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: eq_i256: ; AVX1: # %bb.0: -; AVX1-NEXT: vmovq %xmm0, %rax -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 -; AVX1-NEXT: vmovq %xmm2, %rcx -; AVX1-NEXT: vpextrq $1, %xmm0, %rdx -; AVX1-NEXT: vpextrq $1, %xmm2, %r8 -; AVX1-NEXT: vmovq %xmm1, %rdi -; AVX1-NEXT: xorq %rax, %rdi -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 -; AVX1-NEXT: vmovq %xmm0, %rsi -; AVX1-NEXT: xorq %rcx, %rsi -; AVX1-NEXT: orq %rdi, %rsi -; AVX1-NEXT: vpextrq $1, %xmm1, %rax -; AVX1-NEXT: xorq %rdx, %rax -; AVX1-NEXT: vpextrq $1, %xmm0, %rcx -; AVX1-NEXT: xorq %r8, %rcx -; AVX1-NEXT: orq %rax, %rcx +; AVX1-NEXT: vxorps %ymm1, %ymm0, %ymm0 ; AVX1-NEXT: xorl %eax, %eax -; AVX1-NEXT: orq %rsi, %rcx +; AVX1-NEXT: vptest %ymm0, %ymm0 ; AVX1-NEXT: sete %al ; AVX1-NEXT: vzeroupper ; AVX1-NEXT: retq ; -; AVX256-LABEL: eq_i256: -; AVX256: # %bb.0: -; AVX256-NEXT: vpcmpeqb %ymm1, %ymm0, %ymm0 -; AVX256-NEXT: vpmovmskb %ymm0, %ecx -; AVX256-NEXT: xorl %eax, %eax -; AVX256-NEXT: cmpl $-1, %ecx -; AVX256-NEXT: sete %al -; AVX256-NEXT: vzeroupper -; AVX256-NEXT: retq +; AVX2-LABEL: eq_i256: +; AVX2: # %bb.0: +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: xorl %eax, %eax +; AVX2-NEXT: vptest %ymm0, %ymm0 +; AVX2-NEXT: sete %al +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: eq_i256: +; AVX512: # %bb.0: +; AVX512-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vptest %ymm0, %ymm0 +; AVX512-NEXT: sete %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %bcx = bitcast <4 x i64> %x to i256 %bcy = bitcast <4 x i64> %y to i256 %cmp = icmp eq i256 %bcx, %bcy @@ -235,6 +278,43 @@ ; SSE2-NEXT: setne %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: ne_i512: +; SSE41: # %bb.0: +; SSE41-NEXT: movq %xmm0, %rax +; SSE41-NEXT: movq %xmm2, %rcx +; SSE41-NEXT: movq %xmm1, %rdx +; SSE41-NEXT: movq %xmm3, %rsi +; SSE41-NEXT: pextrq $1, %xmm0, %r11 +; SSE41-NEXT: pextrq $1, %xmm2, %r8 +; SSE41-NEXT: pextrq $1, %xmm1, %r9 +; SSE41-NEXT: pextrq $1, %xmm3, %r10 +; SSE41-NEXT: movq %xmm4, %rdi +; SSE41-NEXT: xorq %rax, %rdi +; SSE41-NEXT: movq %xmm6, %rax +; SSE41-NEXT: xorq %rcx, %rax +; SSE41-NEXT: movq %xmm5, %rcx +; SSE41-NEXT: xorq %rdx, %rcx +; SSE41-NEXT: movq %xmm7, %rdx +; SSE41-NEXT: xorq %rsi, %rdx +; SSE41-NEXT: orq %rcx, %rdx +; SSE41-NEXT: orq %rax, %rdx +; SSE41-NEXT: orq %rdi, %rdx +; SSE41-NEXT: pextrq $1, %xmm4, %rax +; SSE41-NEXT: xorq %r11, %rax +; SSE41-NEXT: pextrq $1, %xmm6, %rcx +; SSE41-NEXT: xorq %r8, %rcx +; SSE41-NEXT: pextrq $1, %xmm5, %rsi +; SSE41-NEXT: xorq %r9, %rsi +; SSE41-NEXT: pextrq $1, %xmm7, %rdi +; SSE41-NEXT: xorq %r10, %rdi +; SSE41-NEXT: orq %rsi, %rdi +; SSE41-NEXT: orq %rcx, %rdi +; SSE41-NEXT: orq %rax, %rdi +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rdx, %rdi +; SSE41-NEXT: setne %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: ne_i512: ; AVX1: # %bb.0: ; AVX1-NEXT: vmovq %xmm0, %rax @@ -389,6 +469,43 @@ ; SSE2-NEXT: sete %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: eq_i512: +; SSE41: # %bb.0: +; SSE41-NEXT: movq %xmm0, %rax +; SSE41-NEXT: movq %xmm2, %rcx +; SSE41-NEXT: movq %xmm1, %rdx +; SSE41-NEXT: movq %xmm3, %rsi +; SSE41-NEXT: pextrq $1, %xmm0, %r11 +; SSE41-NEXT: pextrq $1, %xmm2, %r8 +; SSE41-NEXT: pextrq $1, %xmm1, %r9 +; SSE41-NEXT: pextrq $1, %xmm3, %r10 +; SSE41-NEXT: movq %xmm4, %rdi +; SSE41-NEXT: xorq %rax, %rdi +; SSE41-NEXT: movq %xmm6, %rax +; SSE41-NEXT: xorq %rcx, %rax +; SSE41-NEXT: movq %xmm5, %rcx +; SSE41-NEXT: xorq %rdx, %rcx +; SSE41-NEXT: movq %xmm7, %rdx +; SSE41-NEXT: xorq %rsi, %rdx +; SSE41-NEXT: orq %rcx, %rdx +; SSE41-NEXT: orq %rax, %rdx +; SSE41-NEXT: orq %rdi, %rdx +; SSE41-NEXT: pextrq $1, %xmm4, %rax +; SSE41-NEXT: xorq %r11, %rax +; SSE41-NEXT: pextrq $1, %xmm6, %rcx +; SSE41-NEXT: xorq %r8, %rcx +; SSE41-NEXT: pextrq $1, %xmm5, %rsi +; SSE41-NEXT: xorq %r9, %rsi +; SSE41-NEXT: pextrq $1, %xmm7, %rdi +; SSE41-NEXT: xorq %r10, %rdi +; SSE41-NEXT: orq %rsi, %rdi +; SSE41-NEXT: orq %rcx, %rdi +; SSE41-NEXT: orq %rax, %rdi +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rdx, %rdi +; SSE41-NEXT: sete %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: eq_i512: ; AVX1: # %bb.0: ; AVX1-NEXT: vmovq %xmm0, %rax @@ -516,16 +633,29 @@ ; SSE2-NEXT: setne %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: ne_i128_pair: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqu (%rdi), %xmm0 +; SSE41-NEXT: movdqu 16(%rdi), %xmm1 +; SSE41-NEXT: movdqu (%rsi), %xmm2 +; SSE41-NEXT: pxor %xmm0, %xmm2 +; SSE41-NEXT: movdqu 16(%rsi), %xmm0 +; SSE41-NEXT: pxor %xmm1, %xmm0 +; SSE41-NEXT: por %xmm2, %xmm0 +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: ptest %xmm0, %xmm0 +; SSE41-NEXT: setne %al +; SSE41-NEXT: retq +; ; AVXANY-LABEL: ne_i128_pair: ; AVXANY: # %bb.0: ; AVXANY-NEXT: vmovdqu (%rdi), %xmm0 ; AVXANY-NEXT: vmovdqu 16(%rdi), %xmm1 -; AVXANY-NEXT: vpcmpeqb 16(%rsi), %xmm1, %xmm1 -; AVXANY-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; AVXANY-NEXT: vpand %xmm1, %xmm0, %xmm0 -; AVXANY-NEXT: vpmovmskb %xmm0, %ecx +; AVXANY-NEXT: vpxor 16(%rsi), %xmm1, %xmm1 +; AVXANY-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; AVXANY-NEXT: vpor %xmm1, %xmm0, %xmm0 ; AVXANY-NEXT: xorl %eax, %eax -; AVXANY-NEXT: cmpl $65535, %ecx # imm = 0xFFFF +; AVXANY-NEXT: vptest %xmm0, %xmm0 ; AVXANY-NEXT: setne %al ; AVXANY-NEXT: retq %a0 = load i128, i128* %a @@ -561,16 +691,29 @@ ; SSE2-NEXT: sete %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: eq_i128_pair: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqu (%rdi), %xmm0 +; SSE41-NEXT: movdqu 16(%rdi), %xmm1 +; SSE41-NEXT: movdqu (%rsi), %xmm2 +; SSE41-NEXT: pxor %xmm0, %xmm2 +; SSE41-NEXT: movdqu 16(%rsi), %xmm0 +; SSE41-NEXT: pxor %xmm1, %xmm0 +; SSE41-NEXT: por %xmm2, %xmm0 +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: ptest %xmm0, %xmm0 +; SSE41-NEXT: sete %al +; SSE41-NEXT: retq +; ; AVXANY-LABEL: eq_i128_pair: ; AVXANY: # %bb.0: ; AVXANY-NEXT: vmovdqu (%rdi), %xmm0 ; AVXANY-NEXT: vmovdqu 16(%rdi), %xmm1 -; AVXANY-NEXT: vpcmpeqb 16(%rsi), %xmm1, %xmm1 -; AVXANY-NEXT: vpcmpeqb (%rsi), %xmm0, %xmm0 -; AVXANY-NEXT: vpand %xmm1, %xmm0, %xmm0 -; AVXANY-NEXT: vpmovmskb %xmm0, %ecx +; AVXANY-NEXT: vpxor 16(%rsi), %xmm1, %xmm1 +; AVXANY-NEXT: vpxor (%rsi), %xmm0, %xmm0 +; AVXANY-NEXT: vpor %xmm1, %xmm0, %xmm0 ; AVXANY-NEXT: xorl %eax, %eax -; AVXANY-NEXT: cmpl $65535, %ecx # imm = 0xFFFF +; AVXANY-NEXT: vptest %xmm0, %xmm0 ; AVXANY-NEXT: sete %al ; AVXANY-NEXT: retq %a0 = load i128, i128* %a @@ -620,48 +763,73 @@ ; SSE2-NEXT: setne %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: ne_i256_pair: +; SSE41: # %bb.0: +; SSE41-NEXT: movq 16(%rdi), %r9 +; SSE41-NEXT: movq 24(%rdi), %r11 +; SSE41-NEXT: movq (%rdi), %r8 +; SSE41-NEXT: movq 8(%rdi), %r10 +; SSE41-NEXT: xorq 8(%rsi), %r10 +; SSE41-NEXT: xorq 24(%rsi), %r11 +; SSE41-NEXT: xorq (%rsi), %r8 +; SSE41-NEXT: xorq 16(%rsi), %r9 +; SSE41-NEXT: movq 48(%rdi), %rdx +; SSE41-NEXT: movq 32(%rdi), %rax +; SSE41-NEXT: movq 56(%rdi), %rcx +; SSE41-NEXT: movq 40(%rdi), %rdi +; SSE41-NEXT: xorq 40(%rsi), %rdi +; SSE41-NEXT: xorq 56(%rsi), %rcx +; SSE41-NEXT: orq %r11, %rcx +; SSE41-NEXT: orq %rdi, %rcx +; SSE41-NEXT: orq %r10, %rcx +; SSE41-NEXT: xorq 32(%rsi), %rax +; SSE41-NEXT: xorq 48(%rsi), %rdx +; SSE41-NEXT: orq %r9, %rdx +; SSE41-NEXT: orq %rax, %rdx +; SSE41-NEXT: orq %r8, %rdx +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rcx, %rdx +; SSE41-NEXT: setne %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: ne_i256_pair: ; AVX1: # %bb.0: -; AVX1-NEXT: movq 16(%rdi), %r9 -; AVX1-NEXT: movq 24(%rdi), %r11 -; AVX1-NEXT: movq (%rdi), %r8 -; AVX1-NEXT: movq 8(%rdi), %r10 -; AVX1-NEXT: xorq 8(%rsi), %r10 -; AVX1-NEXT: xorq 24(%rsi), %r11 -; AVX1-NEXT: xorq (%rsi), %r8 -; AVX1-NEXT: xorq 16(%rsi), %r9 -; AVX1-NEXT: movq 48(%rdi), %rdx -; AVX1-NEXT: movq 32(%rdi), %rax -; AVX1-NEXT: movq 56(%rdi), %rcx -; AVX1-NEXT: movq 40(%rdi), %rdi -; AVX1-NEXT: xorq 40(%rsi), %rdi -; AVX1-NEXT: xorq 56(%rsi), %rcx -; AVX1-NEXT: orq %r11, %rcx -; AVX1-NEXT: orq %rdi, %rcx -; AVX1-NEXT: orq %r10, %rcx -; AVX1-NEXT: xorq 32(%rsi), %rax -; AVX1-NEXT: xorq 48(%rsi), %rdx -; AVX1-NEXT: orq %r9, %rdx -; AVX1-NEXT: orq %rax, %rdx -; AVX1-NEXT: orq %r8, %rdx +; AVX1-NEXT: vmovups (%rdi), %ymm0 +; AVX1-NEXT: vmovups 32(%rdi), %ymm1 +; AVX1-NEXT: vxorps 32(%rsi), %ymm1, %ymm1 +; AVX1-NEXT: vxorps (%rsi), %ymm0, %ymm0 +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm0 ; AVX1-NEXT: xorl %eax, %eax -; AVX1-NEXT: orq %rcx, %rdx +; AVX1-NEXT: vptest %ymm0, %ymm0 ; AVX1-NEXT: setne %al +; AVX1-NEXT: vzeroupper ; AVX1-NEXT: retq ; -; AVX256-LABEL: ne_i256_pair: -; AVX256: # %bb.0: -; AVX256-NEXT: vmovdqu (%rdi), %ymm0 -; AVX256-NEXT: vmovdqu 32(%rdi), %ymm1 -; AVX256-NEXT: vpcmpeqb 32(%rsi), %ymm1, %ymm1 -; AVX256-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; AVX256-NEXT: vpand %ymm1, %ymm0, %ymm0 -; AVX256-NEXT: vpmovmskb %ymm0, %ecx -; AVX256-NEXT: xorl %eax, %eax -; AVX256-NEXT: cmpl $-1, %ecx -; AVX256-NEXT: setne %al -; AVX256-NEXT: vzeroupper -; AVX256-NEXT: retq +; AVX2-LABEL: ne_i256_pair: +; AVX2: # %bb.0: +; AVX2-NEXT: vmovdqu (%rdi), %ymm0 +; AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 +; AVX2-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: xorl %eax, %eax +; AVX2-NEXT: vptest %ymm0, %ymm0 +; AVX2-NEXT: setne %al +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: ne_i256_pair: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqu (%rdi), %ymm0 +; AVX512-NEXT: vmovdqu 32(%rdi), %ymm1 +; AVX512-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; AVX512-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vptest %ymm0, %ymm0 +; AVX512-NEXT: setne %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %a0 = load i256, i256* %a %b0 = load i256, i256* %b %xor1 = xor i256 %a0, %b0 @@ -709,48 +877,73 @@ ; SSE2-NEXT: sete %al ; SSE2-NEXT: retq ; +; SSE41-LABEL: eq_i256_pair: +; SSE41: # %bb.0: +; SSE41-NEXT: movq 16(%rdi), %r9 +; SSE41-NEXT: movq 24(%rdi), %r11 +; SSE41-NEXT: movq (%rdi), %r8 +; SSE41-NEXT: movq 8(%rdi), %r10 +; SSE41-NEXT: xorq 8(%rsi), %r10 +; SSE41-NEXT: xorq 24(%rsi), %r11 +; SSE41-NEXT: xorq (%rsi), %r8 +; SSE41-NEXT: xorq 16(%rsi), %r9 +; SSE41-NEXT: movq 48(%rdi), %rdx +; SSE41-NEXT: movq 32(%rdi), %rax +; SSE41-NEXT: movq 56(%rdi), %rcx +; SSE41-NEXT: movq 40(%rdi), %rdi +; SSE41-NEXT: xorq 40(%rsi), %rdi +; SSE41-NEXT: xorq 56(%rsi), %rcx +; SSE41-NEXT: orq %r11, %rcx +; SSE41-NEXT: orq %rdi, %rcx +; SSE41-NEXT: orq %r10, %rcx +; SSE41-NEXT: xorq 32(%rsi), %rax +; SSE41-NEXT: xorq 48(%rsi), %rdx +; SSE41-NEXT: orq %r9, %rdx +; SSE41-NEXT: orq %rax, %rdx +; SSE41-NEXT: orq %r8, %rdx +; SSE41-NEXT: xorl %eax, %eax +; SSE41-NEXT: orq %rcx, %rdx +; SSE41-NEXT: sete %al +; SSE41-NEXT: retq +; ; AVX1-LABEL: eq_i256_pair: ; AVX1: # %bb.0: -; AVX1-NEXT: movq 16(%rdi), %r9 -; AVX1-NEXT: movq 24(%rdi), %r11 -; AVX1-NEXT: movq (%rdi), %r8 -; AVX1-NEXT: movq 8(%rdi), %r10 -; AVX1-NEXT: xorq 8(%rsi), %r10 -; AVX1-NEXT: xorq 24(%rsi), %r11 -; AVX1-NEXT: xorq (%rsi), %r8 -; AVX1-NEXT: xorq 16(%rsi), %r9 -; AVX1-NEXT: movq 48(%rdi), %rdx -; AVX1-NEXT: movq 32(%rdi), %rax -; AVX1-NEXT: movq 56(%rdi), %rcx -; AVX1-NEXT: movq 40(%rdi), %rdi -; AVX1-NEXT: xorq 40(%rsi), %rdi -; AVX1-NEXT: xorq 56(%rsi), %rcx -; AVX1-NEXT: orq %r11, %rcx -; AVX1-NEXT: orq %rdi, %rcx -; AVX1-NEXT: orq %r10, %rcx -; AVX1-NEXT: xorq 32(%rsi), %rax -; AVX1-NEXT: xorq 48(%rsi), %rdx -; AVX1-NEXT: orq %r9, %rdx -; AVX1-NEXT: orq %rax, %rdx -; AVX1-NEXT: orq %r8, %rdx +; AVX1-NEXT: vmovups (%rdi), %ymm0 +; AVX1-NEXT: vmovups 32(%rdi), %ymm1 +; AVX1-NEXT: vxorps 32(%rsi), %ymm1, %ymm1 +; AVX1-NEXT: vxorps (%rsi), %ymm0, %ymm0 +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm0 ; AVX1-NEXT: xorl %eax, %eax -; AVX1-NEXT: orq %rcx, %rdx +; AVX1-NEXT: vptest %ymm0, %ymm0 ; AVX1-NEXT: sete %al +; AVX1-NEXT: vzeroupper ; AVX1-NEXT: retq ; -; AVX256-LABEL: eq_i256_pair: -; AVX256: # %bb.0: -; AVX256-NEXT: vmovdqu (%rdi), %ymm0 -; AVX256-NEXT: vmovdqu 32(%rdi), %ymm1 -; AVX256-NEXT: vpcmpeqb 32(%rsi), %ymm1, %ymm1 -; AVX256-NEXT: vpcmpeqb (%rsi), %ymm0, %ymm0 -; AVX256-NEXT: vpand %ymm1, %ymm0, %ymm0 -; AVX256-NEXT: vpmovmskb %ymm0, %ecx -; AVX256-NEXT: xorl %eax, %eax -; AVX256-NEXT: cmpl $-1, %ecx -; AVX256-NEXT: sete %al -; AVX256-NEXT: vzeroupper -; AVX256-NEXT: retq +; AVX2-LABEL: eq_i256_pair: +; AVX2: # %bb.0: +; AVX2-NEXT: vmovdqu (%rdi), %ymm0 +; AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 +; AVX2-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; AVX2-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: xorl %eax, %eax +; AVX2-NEXT: vptest %ymm0, %ymm0 +; AVX2-NEXT: sete %al +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: eq_i256_pair: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqu (%rdi), %ymm0 +; AVX512-NEXT: vmovdqu 32(%rdi), %ymm1 +; AVX512-NEXT: vpxor 32(%rsi), %ymm1, %ymm1 +; AVX512-NEXT: vpxor (%rsi), %ymm0, %ymm0 +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: xorl %eax, %eax +; AVX512-NEXT: vptest %ymm0, %ymm0 +; AVX512-NEXT: sete %al +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %a0 = load i256, i256* %a %b0 = load i256, i256* %b %xor1 = xor i256 %a0, %b0