[llvm] r353859 - [DAGCombiner] convert logic-of-setcc into bit magic (PR40611)
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 12 09:07:47 PST 2019
Author: spatel
Date: Tue Feb 12 09:07:47 2019
New Revision: 353859
URL: http://llvm.org/viewvc/llvm-project?rev=353859&view=rev
Log:
[DAGCombiner] convert logic-of-setcc into bit magic (PR40611)
If we're comparing some value for equality against 2 constants
and those constants have an absolute difference of just 1 bit,
then we can offset and mask off that 1 bit and reduce to a single
compare against zero:
and/or (setcc X, C0, ne), (setcc X, C1, ne/eq) -->
setcc ((add X, -C1), ~(C0 - C1)), 0, ne/eq
https://rise4fun.com/Alive/XslKj
This transform is disabled by default using a TLI hook
("convertSetCCLogicToBitwiseLogic()").
That should be overridden for AArch64, MIPS, Sparc and possibly
others based on the asm shown in:
https://bugs.llvm.org/show_bug.cgi?id=40611
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/trunk/test/CodeGen/PowerPC/setcc-logic.ll
llvm/trunk/test/CodeGen/X86/setcc-logic.ll
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=353859&r1=353858&r2=353859&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Feb 12 09:07:47 2019
@@ -4123,6 +4123,32 @@ SDValue DAGCombiner::foldLogicOfSetCCs(b
SDValue Zero = DAG.getConstant(0, DL, OpVT);
return DAG.getSetCC(DL, VT, Or, Zero, CC1);
}
+
+ // Turn compare of constants whose difference is 1 bit into add+and+setcc.
+ if ((IsAnd && CC1 == ISD::SETNE) || (!IsAnd && CC1 == ISD::SETEQ)) {
+ // Match a shared variable operand and 2 non-opaque constant operands.
+ ConstantSDNode *C0 = isConstOrConstSplat(LR);
+ ConstantSDNode *C1 = isConstOrConstSplat(RR);
+ if (LL == RL && C0 && C1 && !C0->isOpaque() && !C1->isOpaque()) {
+ // Canonicalize larger constant as C0.
+ if (C1->getAPIntValue().ugt(C0->getAPIntValue()))
+ std::swap(C0, C1);
+
+ // The difference of the constants must be a single bit.
+ const APInt &C0Val = C0->getAPIntValue();
+ const APInt &C1Val = C1->getAPIntValue();
+ if ((C0Val - C1Val).isPowerOf2()) {
+ // and/or (setcc X, C0, ne), (setcc X, C1, ne/eq) -->
+ // setcc ((add X, -C1), ~(C0 - C1)), 0, ne/eq
+ SDValue OffsetC = DAG.getConstant(-C1Val, DL, OpVT);
+ SDValue Add = DAG.getNode(ISD::ADD, DL, OpVT, LL, OffsetC);
+ SDValue MaskC = DAG.getConstant(~(C0Val - C1Val), DL, OpVT);
+ SDValue And = DAG.getNode(ISD::AND, DL, OpVT, Add, MaskC);
+ SDValue Zero = DAG.getConstant(0, DL, OpVT);
+ return DAG.getSetCC(DL, VT, And, Zero, CC0);
+ }
+ }
+ }
}
// Canonicalize equivalent operands to LL == RL.
Modified: llvm/trunk/test/CodeGen/PowerPC/setcc-logic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/setcc-logic.ll?rev=353859&r1=353858&r2=353859&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/setcc-logic.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/setcc-logic.ll Tue Feb 12 09:07:47 2019
@@ -481,11 +481,11 @@ define <4 x i1> @and_eq_vec(<4 x i32> %a
define i1 @or_icmps_const_1bit_diff(i64 %x) {
; CHECK-LABEL: or_icmps_const_1bit_diff:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpdi 3, 17
-; CHECK-NEXT: cmpdi 1, 3, 13
-; CHECK-NEXT: li 3, 1
-; CHECK-NEXT: crnor 20, 2, 6
-; CHECK-NEXT: isel 3, 0, 3, 20
+; CHECK-NEXT: li 4, -5
+; CHECK-NEXT: addi 3, 3, -13
+; CHECK-NEXT: and 3, 3, 4
+; CHECK-NEXT: cntlzd 3, 3
+; CHECK-NEXT: rldicl 3, 3, 58, 63
; CHECK-NEXT: blr
%a = icmp eq i64 %x, 17
%b = icmp eq i64 %x, 13
@@ -496,11 +496,11 @@ define i1 @or_icmps_const_1bit_diff(i64
define i1 @and_icmps_const_1bit_diff(i32 %x) {
; CHECK-LABEL: and_icmps_const_1bit_diff:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpwi 3, 4625
-; CHECK-NEXT: cmpwi 1, 3, 4641
-; CHECK-NEXT: li 3, 1
-; CHECK-NEXT: cror 20, 6, 2
-; CHECK-NEXT: isel 3, 0, 3, 20
+; CHECK-NEXT: addi 3, 3, -4625
+; CHECK-NEXT: rlwinm 3, 3, 0, 28, 26
+; CHECK-NEXT: cntlzw 3, 3
+; CHECK-NEXT: nor 3, 3, 3
+; CHECK-NEXT: rlwinm 3, 3, 27, 31, 31
; CHECK-NEXT: blr
%a = icmp ne i32 %x, 4625
%b = icmp ne i32 %x, 4641
Modified: llvm/trunk/test/CodeGen/X86/setcc-logic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc-logic.ll?rev=353859&r1=353858&r2=353859&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/setcc-logic.ll (original)
+++ llvm/trunk/test/CodeGen/X86/setcc-logic.ll Tue Feb 12 09:07:47 2019
@@ -485,11 +485,9 @@ define <4 x i1> @and_eq_vec(<4 x i32> %a
define i1 @or_icmps_const_1bit_diff(i8 %x) {
; CHECK-LABEL: or_icmps_const_1bit_diff:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpb $43, %dil
-; CHECK-NEXT: sete %cl
-; CHECK-NEXT: cmpb $45, %dil
+; CHECK-NEXT: addb $-43, %dil
+; CHECK-NEXT: testb $-3, %dil
; CHECK-NEXT: sete %al
-; CHECK-NEXT: orb %cl, %al
; CHECK-NEXT: retq
%a = icmp eq i8 %x, 43
%b = icmp eq i8 %x, 45
@@ -500,11 +498,9 @@ define i1 @or_icmps_const_1bit_diff(i8 %
define i1 @and_icmps_const_1bit_diff(i32 %x) {
; CHECK-LABEL: and_icmps_const_1bit_diff:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpl $44, %edi
-; CHECK-NEXT: setne %cl
-; CHECK-NEXT: cmpl $60, %edi
+; CHECK-NEXT: addl $-44, %edi
+; CHECK-NEXT: testl $-17, %edi
; CHECK-NEXT: setne %al
-; CHECK-NEXT: andb %cl, %al
; CHECK-NEXT: retq
%a = icmp ne i32 %x, 44
%b = icmp ne i32 %x, 60
More information about the llvm-commits
mailing list