diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -48164,6 +48164,25 @@ } } + // cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0) + if (CC == ISD::SETEQ && OpVT.isScalarInteger() && Subtarget.hasBMI()) { + auto MatchOrCmpEq = [&](SDValue N0, SDValue N1) { + if (N0.getOpcode() == ISD::OR && N->isOnlyUserOf(N0.getNode())) { + if (N0.getOperand(0) == N1) + return DAG.getNode(ISD::AND, DL, OpVT, DAG.getNOT(DL, N1, OpVT), + N0.getOperand(1)); + if (N0.getOperand(1) == N1) + return DAG.getNode(ISD::AND, DL, OpVT, DAG.getNOT(DL, N1, OpVT), + N0.getOperand(0)); + } + return SDValue(); + }; + if (SDValue AndN = MatchOrCmpEq(LHS, RHS)) + return DAG.getSetCC(DL, VT, AndN, DAG.getConstant(0, DL, OpVT), CC); + if (SDValue AndN = MatchOrCmpEq(RHS, LHS)) + return DAG.getSetCC(DL, VT, AndN, DAG.getConstant(0, DL, OpVT), CC); + } + if (VT.isVector() && VT.getVectorElementType() == MVT::i1 && (CC == ISD::SETNE || CC == ISD::SETEQ || ISD::isSignedIntSetCC(CC))) { // Using temporaries to avoid messing up operand ordering for later diff --git a/llvm/test/CodeGen/X86/setcc-logic.ll b/llvm/test/CodeGen/X86/setcc-logic.ll --- a/llvm/test/CodeGen/X86/setcc-logic.ll +++ b/llvm/test/CodeGen/X86/setcc-logic.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=CHECK,NOBMI +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefixes=CHECK,BMI define zeroext i1 @all_bits_clear(i32 %P, i32 %Q) nounwind { ; CHECK-LABEL: all_bits_clear: @@ -607,51 +607,77 @@ ret i1 %r } -; TODO: PR44136 - fold cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0) +; PR44136 - fold cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0) define i1 @or_cmp_eq_i64(i64 %x, i64 %y) { -; CHECK-LABEL: or_cmp_eq_i64: -; CHECK: # %bb.0: -; CHECK-NEXT: orq %rdi, %rsi -; CHECK-NEXT: cmpq %rdi, %rsi -; CHECK-NEXT: sete %al -; CHECK-NEXT: retq +; NOBMI-LABEL: or_cmp_eq_i64: +; NOBMI: # %bb.0: +; NOBMI-NEXT: orq %rdi, %rsi +; NOBMI-NEXT: cmpq %rdi, %rsi +; NOBMI-NEXT: sete %al +; NOBMI-NEXT: retq +; +; BMI-LABEL: or_cmp_eq_i64: +; BMI: # %bb.0: +; BMI-NEXT: andnq %rsi, %rdi, %rax +; BMI-NEXT: sete %al +; BMI-NEXT: retq %o = or i64 %x, %y %c = icmp eq i64 %o, %x ret i1 %c } define i1 @or_cmp_eq_i32(i32 %x, i32 %y) { -; CHECK-LABEL: or_cmp_eq_i32: -; CHECK: # %bb.0: -; CHECK-NEXT: orl %esi, %edi -; CHECK-NEXT: cmpl %esi, %edi -; CHECK-NEXT: sete %al -; CHECK-NEXT: retq +; NOBMI-LABEL: or_cmp_eq_i32: +; NOBMI: # %bb.0: +; NOBMI-NEXT: orl %esi, %edi +; NOBMI-NEXT: cmpl %esi, %edi +; NOBMI-NEXT: sete %al +; NOBMI-NEXT: retq +; +; BMI-LABEL: or_cmp_eq_i32: +; BMI: # %bb.0: +; BMI-NEXT: andnl %edi, %esi, %eax +; BMI-NEXT: sete %al +; BMI-NEXT: retq %o = or i32 %x, %y %c = icmp eq i32 %o, %y ret i1 %c } define i1 @or_cmp_eq_i16(i16 zeroext %x, i16 zeroext %y) { -; CHECK-LABEL: or_cmp_eq_i16: -; CHECK: # %bb.0: -; CHECK-NEXT: orl %edi, %esi -; CHECK-NEXT: cmpw %si, %di -; CHECK-NEXT: sete %al -; CHECK-NEXT: retq +; NOBMI-LABEL: or_cmp_eq_i16: +; NOBMI: # %bb.0: +; NOBMI-NEXT: orl %edi, %esi +; NOBMI-NEXT: cmpw %si, %di +; NOBMI-NEXT: sete %al +; NOBMI-NEXT: retq +; +; BMI-LABEL: or_cmp_eq_i16: +; BMI: # %bb.0: +; BMI-NEXT: notl %edi +; BMI-NEXT: testw %si, %di +; BMI-NEXT: sete %al +; BMI-NEXT: retq %o = or i16 %x, %y %c = icmp eq i16 %x, %o ret i1 %c } define i1 @or_cmp_eq_i8(i8 zeroext %x, i8 zeroext %y) { -; CHECK-LABEL: or_cmp_eq_i8: -; CHECK: # %bb.0: -; CHECK-NEXT: orl %esi, %edi -; CHECK-NEXT: cmpb %dil, %sil -; CHECK-NEXT: sete %al -; CHECK-NEXT: retq +; NOBMI-LABEL: or_cmp_eq_i8: +; NOBMI: # %bb.0: +; NOBMI-NEXT: orl %esi, %edi +; NOBMI-NEXT: cmpb %dil, %sil +; NOBMI-NEXT: sete %al +; NOBMI-NEXT: retq +; +; BMI-LABEL: or_cmp_eq_i8: +; BMI: # %bb.0: +; BMI-NEXT: notb %sil +; BMI-NEXT: testb %dil, %sil +; BMI-NEXT: sete %al +; BMI-NEXT: retq %o = or i8 %x, %y %c = icmp eq i8 %y, %o ret i1 %c