Skip to content

Commit 2450369

Browse files
committed
[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
1 parent f3d7536 commit 2450369

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48162,6 +48162,26 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
4816248162
return DAG.getNode(ISD::TRUNCATE, DL, VT,
4816348163
DAG.getNode(X86ISD::SETCC, DL, MVT::i8, X86CC, V));
4816448164
}
48165+
48166+
// cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0)
48167+
// cmpne(or(X,Y),X) --> cmpne(and(~X,Y),0)
48168+
if (OpVT.isScalarInteger() && Subtarget.hasBMI()) {
48169+
auto MatchOrCmpEq = [&](SDValue N0, SDValue N1) {
48170+
if (N0.getOpcode() == ISD::OR && N0->hasOneUse()) {
48171+
if (N0.getOperand(0) == N1)
48172+
return DAG.getNode(ISD::AND, DL, OpVT, DAG.getNOT(DL, N1, OpVT),
48173+
N0.getOperand(1));
48174+
if (N0.getOperand(1) == N1)
48175+
return DAG.getNode(ISD::AND, DL, OpVT, DAG.getNOT(DL, N1, OpVT),
48176+
N0.getOperand(0));
48177+
}
48178+
return SDValue();
48179+
};
48180+
if (SDValue AndN = MatchOrCmpEq(LHS, RHS))
48181+
return DAG.getSetCC(DL, VT, AndN, DAG.getConstant(0, DL, OpVT), CC);
48182+
if (SDValue AndN = MatchOrCmpEq(RHS, LHS))
48183+
return DAG.getSetCC(DL, VT, AndN, DAG.getConstant(0, DL, OpVT), CC);
48184+
}
4816548185
}
4816648186

4816748187
if (VT.isVector() && VT.getVectorElementType() == MVT::i1 &&

llvm/test/CodeGen/X86/setcc-logic.ll

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2-
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
3-
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s
2+
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=CHECK,NOBMI
3+
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefixes=CHECK,BMI
44

55
define zeroext i1 @all_bits_clear(i32 %P, i32 %Q) nounwind {
66
; CHECK-LABEL: all_bits_clear:
@@ -607,51 +607,77 @@ define i1 @and_icmps_const_1bit_diff_common_op(i32 %x, i32 %y) {
607607
ret i1 %r
608608
}
609609

610-
; TODO: PR44136 - fold cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0)
610+
; PR44136 - fold cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0)
611611

612612
define i1 @or_cmp_eq_i64(i64 %x, i64 %y) {
613-
; CHECK-LABEL: or_cmp_eq_i64:
614-
; CHECK: # %bb.0:
615-
; CHECK-NEXT: orq %rdi, %rsi
616-
; CHECK-NEXT: cmpq %rdi, %rsi
617-
; CHECK-NEXT: sete %al
618-
; CHECK-NEXT: retq
613+
; NOBMI-LABEL: or_cmp_eq_i64:
614+
; NOBMI: # %bb.0:
615+
; NOBMI-NEXT: orq %rdi, %rsi
616+
; NOBMI-NEXT: cmpq %rdi, %rsi
617+
; NOBMI-NEXT: sete %al
618+
; NOBMI-NEXT: retq
619+
;
620+
; BMI-LABEL: or_cmp_eq_i64:
621+
; BMI: # %bb.0:
622+
; BMI-NEXT: andnq %rsi, %rdi, %rax
623+
; BMI-NEXT: sete %al
624+
; BMI-NEXT: retq
619625
%o = or i64 %x, %y
620626
%c = icmp eq i64 %o, %x
621627
ret i1 %c
622628
}
623629

624630
define i1 @or_cmp_ne_i32(i32 %x, i32 %y) {
625-
; CHECK-LABEL: or_cmp_ne_i32:
626-
; CHECK: # %bb.0:
627-
; CHECK-NEXT: orl %esi, %edi
628-
; CHECK-NEXT: cmpl %esi, %edi
629-
; CHECK-NEXT: setne %al
630-
; CHECK-NEXT: retq
631+
; NOBMI-LABEL: or_cmp_ne_i32:
632+
; NOBMI: # %bb.0:
633+
; NOBMI-NEXT: orl %esi, %edi
634+
; NOBMI-NEXT: cmpl %esi, %edi
635+
; NOBMI-NEXT: setne %al
636+
; NOBMI-NEXT: retq
637+
;
638+
; BMI-LABEL: or_cmp_ne_i32:
639+
; BMI: # %bb.0:
640+
; BMI-NEXT: andnl %edi, %esi, %eax
641+
; BMI-NEXT: setne %al
642+
; BMI-NEXT: retq
631643
%o = or i32 %x, %y
632644
%c = icmp ne i32 %o, %y
633645
ret i1 %c
634646
}
635647

636648
define i1 @or_cmp_eq_i16(i16 zeroext %x, i16 zeroext %y) {
637-
; CHECK-LABEL: or_cmp_eq_i16:
638-
; CHECK: # %bb.0:
639-
; CHECK-NEXT: orl %edi, %esi
640-
; CHECK-NEXT: cmpw %si, %di
641-
; CHECK-NEXT: sete %al
642-
; CHECK-NEXT: retq
649+
; NOBMI-LABEL: or_cmp_eq_i16:
650+
; NOBMI: # %bb.0:
651+
; NOBMI-NEXT: orl %edi, %esi
652+
; NOBMI-NEXT: cmpw %si, %di
653+
; NOBMI-NEXT: sete %al
654+
; NOBMI-NEXT: retq
655+
;
656+
; BMI-LABEL: or_cmp_eq_i16:
657+
; BMI: # %bb.0:
658+
; BMI-NEXT: notl %edi
659+
; BMI-NEXT: testw %si, %di
660+
; BMI-NEXT: sete %al
661+
; BMI-NEXT: retq
643662
%o = or i16 %x, %y
644663
%c = icmp eq i16 %x, %o
645664
ret i1 %c
646665
}
647666

648667
define i1 @or_cmp_ne_i8(i8 zeroext %x, i8 zeroext %y) {
649-
; CHECK-LABEL: or_cmp_ne_i8:
650-
; CHECK: # %bb.0:
651-
; CHECK-NEXT: orl %esi, %edi
652-
; CHECK-NEXT: cmpb %dil, %sil
653-
; CHECK-NEXT: setne %al
654-
; CHECK-NEXT: retq
668+
; NOBMI-LABEL: or_cmp_ne_i8:
669+
; NOBMI: # %bb.0:
670+
; NOBMI-NEXT: orl %esi, %edi
671+
; NOBMI-NEXT: cmpb %dil, %sil
672+
; NOBMI-NEXT: setne %al
673+
; NOBMI-NEXT: retq
674+
;
675+
; BMI-LABEL: or_cmp_ne_i8:
676+
; BMI: # %bb.0:
677+
; BMI-NEXT: notb %sil
678+
; BMI-NEXT: testb %dil, %sil
679+
; BMI-NEXT: setne %al
680+
; BMI-NEXT: retq
655681
%o = or i8 %x, %y
656682
%c = icmp ne i8 %y, %o
657683
ret i1 %c

0 commit comments

Comments
 (0)