<div dir="ltr"><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, May 22, 2022 at 6:11 PM Nikita Popov <<a href="mailto:nikita.ppv@gmail.com">nikita.ppv@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div dir="ltr" class="gmail_attr">On Sun, May 22, 2022 at 5:54 PM Sanjay Patel via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Sanjay Patel<br>
Date: 2022-05-22T11:51:07-04:00<br>
New Revision: 4069cccf3b4ff4afb743d3d371ead9e2d5491e3a<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a.diff</a><br>
<br>
LOG: [InstCombine] fold icmp with sub and bool<br>
<br>
This is the specific pattern seen in #53432, but it can be extended<br>
in multiple ways:<br>
1. The 'zext' could be an 'and'<br>
2. The 'sub' could be some other binop with a similar ==0 property (udiv).<br>
<br>
There might be some way to generalize using knownbits, but that<br>
would require checking that the 'bool' value is created with<br>
some instruction that can be replaced with new icmp+logic.<br>
<br>
<a href="https://alive2.llvm.org/ce/z/-KCfpa" rel="noreferrer" target="_blank">https://alive2.llvm.org/ce/z/-KCfpa</a><br></blockquote><div><br></div><div>Are the multi-use cases here motivating? Otherwise, I would have found it more intuitive to use a pattern like <a href="https://alive2.llvm.org/ce/z/XqbXm4" target="_blank">https://alive2.llvm.org/ce/z/XqbXm4</a> that is not specific to sub.</div></div></div></blockquote><div><br></div><div>Also, isn't this missing a check that the zext is from i1 rather than some other type?</div><div><br></div><div>Nikita<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Added: <br>
<br>
<br>
Modified: <br>
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
    llvm/test/Transforms/InstCombine/icmp-range.ll<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
index 4f20a0699ec50..e2a6b6b1495b8 100644<br>
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
@@ -5631,6 +5631,29 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {<br>
   return nullptr;<br>
 }<br>
<br>
+/// If one operand of an icmp is effectively a bool (value range of {0,1}),<br>
+/// then try to reduce patterns based on that limit.<br>
+static Instruction *foldICmpUsingBoolRange(ICmpInst &I,<br>
+                                           InstCombiner::BuilderTy &Builder) {<br>
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);<br>
+  const ICmpInst::Predicate Pred = I.getPredicate();<br>
+<br>
+  Value *X, *Y, *Z;<br>
+  if (Pred != ICmpInst::ICMP_ULT || !match(Op0, m_Sub(m_Value(X), m_Value(Y))))<br>
+    return nullptr;<br>
+<br>
+  unsigned ExtraUses = !Op0->hasOneUse() + !Op1->hasOneUse();<br>
+<br>
+  // Sub must be 0 and bool must be true for "ULT":<br>
+  // (sub X, Y) <u (zext i1 Z) --> (X == Y) && Z<br>
+  if (match(Op1, m_ZExt(m_Value(Z))) && ExtraUses < 2) {<br>
+    Value *EqXY = Builder.CreateICmpEQ(X, Y);<br>
+    return BinaryOperator::CreateAnd(EqXY, Z);<br>
+  }<br>
+<br>
+  return nullptr;<br>
+}<br>
+<br>
 llvm::Optional<std::pair<CmpInst::Predicate, Constant *>><br>
 InstCombiner::getFlippedStrictnessPredicateAndConstant(CmpInst::Predicate Pred,<br>
                                                        Constant *C) {<br>
@@ -6058,6 +6081,9 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {<br>
   if (Instruction *Res = foldICmpWithDominatingICmp(I))<br>
     return Res;<br>
<br>
+  if (Instruction *Res = foldICmpUsingBoolRange(I, Builder))<br>
+    return Res;<br>
+<br>
   if (Instruction *Res = foldICmpUsingKnownBits(I))<br>
     return Res;<br>
<br>
<br>
diff  --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll<br>
index b67356675eba6..a29d4cd81b9d1 100644<br>
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll<br>
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll<br>
@@ -173,9 +173,8 @@ define i1 @test_two_ranges3(i32* nocapture readonly %arg1, i32* nocapture readon<br>
<br>
 define i1 @sub_ult_zext(i1 %b, i8 %x, i8 %y) {<br>
 ; CHECK-LABEL: @sub_ult_zext(<br>
-; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8<br>
-; CHECK-NEXT:    [[S:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]<br>
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[S]], [[Z]]<br>
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]<br>
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[B:%.*]]<br>
 ; CHECK-NEXT:    ret i1 [[R]]<br>
 ;<br>
   %z = zext i1 %b to i8<br>
@@ -188,8 +187,8 @@ define i1 @sub_ult_zext_use1(i1 %b, i8 %x, i8 %y) {<br>
 ; CHECK-LABEL: @sub_ult_zext_use1(<br>
 ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8<br>
 ; CHECK-NEXT:    call void @use(i8 [[Z]])<br>
-; CHECK-NEXT:    [[S:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]<br>
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[S]], [[Z]]<br>
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]<br>
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[B]]<br>
 ; CHECK-NEXT:    ret i1 [[R]]<br>
 ;<br>
   %z = zext i1 %b to i8<br>
@@ -201,10 +200,10 @@ define i1 @sub_ult_zext_use1(i1 %b, i8 %x, i8 %y) {<br>
<br>
 define <2 x i1> @zext_ugt_sub_use2(<2 x i1> %b, <2 x i8> %x, <2 x i8> %y) {<br>
 ; CHECK-LABEL: @zext_ugt_sub_use2(<br>
-; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8><br>
 ; CHECK-NEXT:    [[S:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]]<br>
 ; CHECK-NEXT:    call void @use_vec(<2 x i8> [[S]])<br>
-; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[S]], [[Z]]<br>
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X]], [[Y]]<br>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i1> [[TMP1]], [[B:%.*]]<br>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]<br>
 ;<br>
   %z = zext <2 x i1> %b to <2 x i8><br>
@@ -214,6 +213,8 @@ define <2 x i1> @zext_ugt_sub_use2(<2 x i1> %b, <2 x i8> %x, <2 x i8> %y) {<br>
   ret <2 x i1> %r<br>
 }<br>
<br>
+; negative test - too many extra uses<br>
+<br>
 define i1 @sub_ult_zext_use3(i1 %b, i8 %x, i8 %y) {<br>
 ; CHECK-LABEL: @sub_ult_zext_use3(<br>
 ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8<br>
@@ -231,6 +232,8 @@ define i1 @sub_ult_zext_use3(i1 %b, i8 %x, i8 %y) {<br>
   ret i1 %r<br>
 }<br>
<br>
+; negative test - wrong predicate<br>
+<br>
 define i1 @sub_ule_zext(i1 %b, i8 %x, i8 %y) {<br>
 ; CHECK-LABEL: @sub_ule_zext(<br>
 ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>
</blockquote></div></div>