forked from OSchip/llvm-project
[X86][BMI] Fold cmpeq/ne(or(X,Y),X) --> cmpeq/ne(and(~X,Y),0) (PR44136)
I've initially just enabled this for BMI which has the ANDN instruction for i32/i64 - the i16/i8 cases give an idea of what'd we get when we enable it in all cases (I'll do this as a later commit). Additionally, the i16/i8 cases could be freely promoted to i32 (as the args are already zeroext) and we could then make use of ANDN + the free cmp0 there as well - this has come up in PR48768 and PR49028 so I'm going to look at this soon. https://alive2.llvm.org/ce/z/QVWHP_ https://alive2.llvm.org/ce/z/pLngT- Vector cases do not appear to benefit from this as we end up with having to generate the zero vector as well - this is one of the reasons I didn't try to tie this into hasAndNot/hasAndNotCompare. Differential Revision: https://reviews.llvm.org/D100177
This commit is contained in:
parent
f3d7536b24
commit
245036950a
|
@ -48162,6 +48162,26 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
|
||||||
return DAG.getNode(ISD::TRUNCATE, DL, VT,
|
return DAG.getNode(ISD::TRUNCATE, DL, VT,
|
||||||
DAG.getNode(X86ISD::SETCC, DL, MVT::i8, X86CC, V));
|
DAG.getNode(X86ISD::SETCC, DL, MVT::i8, X86CC, V));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0)
|
||||||
|
// cmpne(or(X,Y),X) --> cmpne(and(~X,Y),0)
|
||||||
|
if (OpVT.isScalarInteger() && Subtarget.hasBMI()) {
|
||||||
|
auto MatchOrCmpEq = [&](SDValue N0, SDValue N1) {
|
||||||
|
if (N0.getOpcode() == ISD::OR && N0->hasOneUse()) {
|
||||||
|
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 &&
|
if (VT.isVector() && VT.getVectorElementType() == MVT::i1 &&
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
; 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 | FileCheck %s --check-prefixes=CHECK,NOBMI
|
||||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s
|
; 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 {
|
define zeroext i1 @all_bits_clear(i32 %P, i32 %Q) nounwind {
|
||||||
; CHECK-LABEL: all_bits_clear:
|
; CHECK-LABEL: all_bits_clear:
|
||||||
|
@ -607,51 +607,77 @@ define i1 @and_icmps_const_1bit_diff_common_op(i32 %x, i32 %y) {
|
||||||
ret i1 %r
|
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) {
|
define i1 @or_cmp_eq_i64(i64 %x, i64 %y) {
|
||||||
; CHECK-LABEL: or_cmp_eq_i64:
|
; NOBMI-LABEL: or_cmp_eq_i64:
|
||||||
; CHECK: # %bb.0:
|
; NOBMI: # %bb.0:
|
||||||
; CHECK-NEXT: orq %rdi, %rsi
|
; NOBMI-NEXT: orq %rdi, %rsi
|
||||||
; CHECK-NEXT: cmpq %rdi, %rsi
|
; NOBMI-NEXT: cmpq %rdi, %rsi
|
||||||
; CHECK-NEXT: sete %al
|
; NOBMI-NEXT: sete %al
|
||||||
; CHECK-NEXT: retq
|
; 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
|
%o = or i64 %x, %y
|
||||||
%c = icmp eq i64 %o, %x
|
%c = icmp eq i64 %o, %x
|
||||||
ret i1 %c
|
ret i1 %c
|
||||||
}
|
}
|
||||||
|
|
||||||
define i1 @or_cmp_ne_i32(i32 %x, i32 %y) {
|
define i1 @or_cmp_ne_i32(i32 %x, i32 %y) {
|
||||||
; CHECK-LABEL: or_cmp_ne_i32:
|
; NOBMI-LABEL: or_cmp_ne_i32:
|
||||||
; CHECK: # %bb.0:
|
; NOBMI: # %bb.0:
|
||||||
; CHECK-NEXT: orl %esi, %edi
|
; NOBMI-NEXT: orl %esi, %edi
|
||||||
; CHECK-NEXT: cmpl %esi, %edi
|
; NOBMI-NEXT: cmpl %esi, %edi
|
||||||
; CHECK-NEXT: setne %al
|
; NOBMI-NEXT: setne %al
|
||||||
; CHECK-NEXT: retq
|
; NOBMI-NEXT: retq
|
||||||
|
;
|
||||||
|
; BMI-LABEL: or_cmp_ne_i32:
|
||||||
|
; BMI: # %bb.0:
|
||||||
|
; BMI-NEXT: andnl %edi, %esi, %eax
|
||||||
|
; BMI-NEXT: setne %al
|
||||||
|
; BMI-NEXT: retq
|
||||||
%o = or i32 %x, %y
|
%o = or i32 %x, %y
|
||||||
%c = icmp ne i32 %o, %y
|
%c = icmp ne i32 %o, %y
|
||||||
ret i1 %c
|
ret i1 %c
|
||||||
}
|
}
|
||||||
|
|
||||||
define i1 @or_cmp_eq_i16(i16 zeroext %x, i16 zeroext %y) {
|
define i1 @or_cmp_eq_i16(i16 zeroext %x, i16 zeroext %y) {
|
||||||
; CHECK-LABEL: or_cmp_eq_i16:
|
; NOBMI-LABEL: or_cmp_eq_i16:
|
||||||
; CHECK: # %bb.0:
|
; NOBMI: # %bb.0:
|
||||||
; CHECK-NEXT: orl %edi, %esi
|
; NOBMI-NEXT: orl %edi, %esi
|
||||||
; CHECK-NEXT: cmpw %si, %di
|
; NOBMI-NEXT: cmpw %si, %di
|
||||||
; CHECK-NEXT: sete %al
|
; NOBMI-NEXT: sete %al
|
||||||
; CHECK-NEXT: retq
|
; 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
|
%o = or i16 %x, %y
|
||||||
%c = icmp eq i16 %x, %o
|
%c = icmp eq i16 %x, %o
|
||||||
ret i1 %c
|
ret i1 %c
|
||||||
}
|
}
|
||||||
|
|
||||||
define i1 @or_cmp_ne_i8(i8 zeroext %x, i8 zeroext %y) {
|
define i1 @or_cmp_ne_i8(i8 zeroext %x, i8 zeroext %y) {
|
||||||
; CHECK-LABEL: or_cmp_ne_i8:
|
; NOBMI-LABEL: or_cmp_ne_i8:
|
||||||
; CHECK: # %bb.0:
|
; NOBMI: # %bb.0:
|
||||||
; CHECK-NEXT: orl %esi, %edi
|
; NOBMI-NEXT: orl %esi, %edi
|
||||||
; CHECK-NEXT: cmpb %dil, %sil
|
; NOBMI-NEXT: cmpb %dil, %sil
|
||||||
; CHECK-NEXT: setne %al
|
; NOBMI-NEXT: setne %al
|
||||||
; CHECK-NEXT: retq
|
; NOBMI-NEXT: retq
|
||||||
|
;
|
||||||
|
; BMI-LABEL: or_cmp_ne_i8:
|
||||||
|
; BMI: # %bb.0:
|
||||||
|
; BMI-NEXT: notb %sil
|
||||||
|
; BMI-NEXT: testb %dil, %sil
|
||||||
|
; BMI-NEXT: setne %al
|
||||||
|
; BMI-NEXT: retq
|
||||||
%o = or i8 %x, %y
|
%o = or i8 %x, %y
|
||||||
%c = icmp ne i8 %y, %o
|
%c = icmp ne i8 %y, %o
|
||||||
ret i1 %c
|
ret i1 %c
|
||||||
|
|
Loading…
Reference in New Issue