[llvm] 2450369 - [X86][BMI] Fold cmpeq/ne(or(X,Y),X) --> cmpeq/ne(and(~X,Y),0) (PR44136)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 9 07:52:11 PDT 2021
Author: Simon Pilgrim
Date: 2021-04-09T15:52:03+01:00
New Revision: 245036950a7a63f77aa1f06f46dfe2fbb2cafc0f
URL: https://github.com/llvm/llvm-project/commit/245036950a7a63f77aa1f06f46dfe2fbb2cafc0f
DIFF: https://github.com/llvm/llvm-project/commit/245036950a7a63f77aa1f06f46dfe2fbb2cafc0f.diff
LOG: [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
Added:
Modified:
llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/setcc-logic.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7c0ec182865c..12f97372859b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -48162,6 +48162,26 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(ISD::TRUNCATE, DL, VT,
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 &&
diff --git a/llvm/test/CodeGen/X86/setcc-logic.ll b/llvm/test/CodeGen/X86/setcc-logic.ll
index 8fc0da5ae406..b32d625ab619 100644
--- 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 @@ define i1 @and_icmps_const_1bit_
diff _common_op(i32 %x, i32 %y) {
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_ne_i32(i32 %x, i32 %y) {
-; CHECK-LABEL: or_cmp_ne_i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: orl %esi, %edi
-; CHECK-NEXT: cmpl %esi, %edi
-; CHECK-NEXT: setne %al
-; CHECK-NEXT: retq
+; NOBMI-LABEL: or_cmp_ne_i32:
+; NOBMI: # %bb.0:
+; NOBMI-NEXT: orl %esi, %edi
+; NOBMI-NEXT: cmpl %esi, %edi
+; NOBMI-NEXT: setne %al
+; 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
%c = icmp ne 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_ne_i8(i8 zeroext %x, i8 zeroext %y) {
-; CHECK-LABEL: or_cmp_ne_i8:
-; CHECK: # %bb.0:
-; CHECK-NEXT: orl %esi, %edi
-; CHECK-NEXT: cmpb %dil, %sil
-; CHECK-NEXT: setne %al
-; CHECK-NEXT: retq
+; NOBMI-LABEL: or_cmp_ne_i8:
+; NOBMI: # %bb.0:
+; NOBMI-NEXT: orl %esi, %edi
+; NOBMI-NEXT: cmpb %dil, %sil
+; NOBMI-NEXT: setne %al
+; 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
%c = icmp ne i8 %y, %o
ret i1 %c
More information about the llvm-commits
mailing list