[PATCH] D133919: [InstCombine] Fold ((x?1:4)&(y?1:4))==0 to x^y
Marc Auberer via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 15 00:39:05 PDT 2022
marcauberer created this revision.
marcauberer added reviewers: spatel, RKSimon.
Herald added a subscriber: hiraditya.
Herald added a project: All.
marcauberer requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Fixes issue #57666: https://github.com/llvm/llvm-project/issues/57666
The optimization applies to all constant values that equal to zero when
applied to an bitwise and instruction.
Alive2: https://alive2.llvm.org/ce/z/RrVEyX
Minimalistic Godbolt example: https://godbolt.org/z/3d6h9z4de
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D133919
Files:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
Index: llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
===================================================================
--- llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
+++ llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
@@ -8,10 +8,7 @@
define i1 @select_and_icmpeq_i32_commuted1(i1 %x, i1 %y) {
; CHECK-LABEL: @select_and_icmpeq_i32_commuted1(
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i32 2, i32 1
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i32 2, i32 1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[S1]], [[S2]]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[ICMP]]
;
%s1 = select i1 %x, i32 2, i32 1
@@ -23,10 +20,7 @@
define i1 @select_and_icmpeq_i32_commuted2(i1 %x, i1 %y) {
; CHECK-LABEL: @select_and_icmpeq_i32_commuted2(
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 4, i32 1
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 4, i32 1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[ICMP]]
;
%s1 = select i1 %y, i32 4, i32 1
@@ -38,10 +32,7 @@
define i1 @select_and_icmpeq_i32_commuted3(i1 %x, i1 %y) {
; CHECK-LABEL: @select_and_icmpeq_i32_commuted3(
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 12
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 12
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[S1]], [[S2]]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[ICMP]]
;
%s1 = select i1 %y, i32 3, i32 12
@@ -53,10 +44,7 @@
define i1 @select_and_icmpeq_i32_commuted4(i1 %x, i1 %y) {
; CHECK-LABEL: @select_and_icmpeq_i32_commuted4(
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 16
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 16
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[ICMP]]
;
%s1 = select i1 %y, i32 3, i32 16
@@ -68,10 +56,7 @@
define i1 @select_and_icmpeq_i9(i1 %x, i1 %y) {
; CHECK-LABEL: @select_and_icmpeq_i9(
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i9 3, i9 16
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i9 3, i9 16
-; CHECK-NEXT: [[AND:%.*]] = and i9 [[S2]], [[S1]]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i9 [[AND]], 0
+; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[ICMP]]
;
%s1 = select i1 %y, i9 3, i9 16
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6464,6 +6464,22 @@
if (Instruction *Res = foldReductionIdiom(I, Builder, DL))
return Res;
+ {
+ Value *A, *B;
+ const APInt *C, *D;
+ // Find hidden xor optimization (only works if `and C, D` equals `0`)
+ // (icmp (and (select A, C, D), (select B, C, D)), 0) --> (xor A, B)
+ if (I.getPredicate() == ICmpInst::ICMP_EQ && match(Op0,
+ m_OneUse(m_c_And(
+ m_OneUse(m_Select(m_Value(A), m_APInt(C), m_APInt(D))),
+ m_OneUse(m_Select(m_Value(B), m_APInt(C), m_APInt(D)))
+ ))
+ ) && match(Op1, m_Zero())) {
+ if ((*C & *D) == 0)
+ return BinaryOperator::CreateXor(A, B);
+ }
+ }
+
return Changed ? &I : nullptr;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D133919.460313.patch
Type: text/x-patch
Size: 3693 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220915/13bd6346/attachment.bin>
More information about the llvm-commits
mailing list