<div dir="ltr"><div>Typo'd the formula in the commit title. It should be as shown in the code:<br>min(~a, ~b) --> ~max(a, b)<br></div>...both operands are 'not'<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 5, 2018 at 12:01 PM, Sanjay Patel via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: spatel<br>
Date: Fri Jan  5 11:01:17 2018<br>
New Revision: 321882<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=321882&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=321882&view=rev</a><br>
Log:<br>
[InstCombine] add folds for min(~a, b) --> ~max(a, b)<br>
<br>
Besides the bug of omitting the inverse transform of max(~a, ~b) --> ~min(a, b),<br>
the use checking and operand creation were off. We were potentially creating<br>
repeated identical instructions of existing values. This led to infinite<br>
looping after I added the extra folds.<br>
<br>
By using the simpler m_Not matcher and not creating new 'not' ops for a and b,<br>
we avoid that problem. It's possible that not using IsFreeToInvert() here is<br>
more limiting than the simpler matcher, but there are no tests for anything<br>
more exotic. It's also possible that we should relax the use checking further<br>
to handle a case like PR35834:<br>
<a href="https://bugs.llvm.org/show_bug.cgi?id=35834" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=35834</a><br>
...but we can make that a follow-up if it is needed.<br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineSelect.<wbr>cpp<br>
    llvm/trunk/test/Transforms/<wbr>InstCombine/max-of-nots.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineSelect.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=321882&r1=321881&r2=321882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Transforms/InstCombine/<wbr>InstCombineSelect.cpp?rev=<wbr>321882&r1=321881&r2=321882&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineSelect.<wbr>cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineSelect.<wbr>cpp Fri Jan  5 11:01:17 2018<br>
@@ -1551,6 +1551,18 @@ Instruction *InstCombiner::visitSelectIn<br>
         Value *NewCast = Builder.CreateCast(CastOp, NewSI, SelType);<br>
         return replaceInstUsesWith(SI, NewCast);<br>
       }<br>
+<br>
+      // MAX(~a, ~b) -> ~MIN(a, b)<br>
+      // MIN(~a, ~b) -> ~MAX(a, b)<br>
+      Value *A, *B;<br>
+      if (match(LHS, m_Not(m_Value(A))) && LHS->getNumUses() <= 2 &&<br>
+          match(RHS, m_Not(m_Value(B))) && RHS->getNumUses() <= 2) {<br>
+        CmpInst::Predicate InvertedPred =<br>
+            getCmpPredicateForMinMax(<wbr>getInverseMinMaxSelectPattern(<wbr>SPF));<br>
+        Value *InvertedCmp = Builder.CreateICmp(<wbr>InvertedPred, A, B);<br>
+        Value *NewSel = Builder.CreateSelect(<wbr>InvertedCmp, A, B);<br>
+        return BinaryOperator::CreateNot(<wbr>NewSel);<br>
+      }<br>
     }<br>
<br>
     if (SPF) {<br>
@@ -1570,28 +1582,6 @@ Instruction *InstCombiner::visitSelectIn<br>
           return R;<br>
     }<br>
<br>
-    // MAX(~a, ~b) -> ~MIN(a, b)<br>
-    if ((SPF == SPF_SMAX || SPF == SPF_UMAX) &&<br>
-        IsFreeToInvert(LHS, LHS->hasNUses(2)) &&<br>
-        IsFreeToInvert(RHS, RHS->hasNUses(2))) {<br>
-      // For this transform to be profitable, we need to eliminate at least two<br>
-      // 'not' instructions if we're going to add one 'not' instruction.<br>
-      int NumberOfNots =<br>
-          (LHS->hasNUses(2) && match(LHS, m_Not(m_Value()))) +<br>
-          (RHS->hasNUses(2) && match(RHS, m_Not(m_Value()))) +<br>
-          (SI.hasOneUse() && match(*SI.user_begin(), m_Not(m_Value())));<br>
-<br>
-      if (NumberOfNots >= 2) {<br>
-        Value *NewLHS = Builder.CreateNot(LHS);<br>
-        Value *NewRHS = Builder.CreateNot(RHS);<br>
-        Value *NewCmp = SPF == SPF_SMAX ? Builder.CreateICmpSLT(NewLHS, NewRHS)<br>
-                                        : Builder.CreateICmpULT(NewLHS, NewRHS);<br>
-        Value *NewSI =<br>
-            Builder.CreateNot(Builder.<wbr>CreateSelect(NewCmp, NewLHS, NewRHS));<br>
-        return replaceInstUsesWith(SI, NewSI);<br>
-      }<br>
-    }<br>
-<br>
     // TODO.<br>
     // ABS(-X) -> ABS(X)<br>
   }<br>
<br>
Modified: llvm/trunk/test/Transforms/<wbr>InstCombine/max-of-nots.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll?rev=321882&r1=321881&r2=321882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/InstCombine/max-of-<wbr>nots.ll?rev=321882&r1=321881&<wbr>r2=321882&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>InstCombine/max-of-nots.ll (original)<br>
+++ llvm/trunk/test/Transforms/<wbr>InstCombine/max-of-nots.ll Fri Jan  5 11:01:17 2018<br>
@@ -1,6 +1,34 @@<br>
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py<br>
 ; RUN: opt -S -instcombine < %s | FileCheck %s<br>
<br>
+define <2 x i32> @umin_of_nots(<2 x i32> %x, <2 x i32> %y) {<br>
+; CHECK-LABEL: @umin_of_nots(<br>
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <2 x i32> %x, %y<br>
+; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> %x, <2 x i32> %y<br>
+; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP2]], <i32 -1, i32 -1><br>
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]<br>
+;<br>
+  %notx = xor <2 x i32> %x, <i32 -1, i32 -1><br>
+  %noty = xor <2 x i32> %y, <i32 -1, i32 -1><br>
+  %cmp = icmp ult <2 x i32> %notx, %noty<br>
+  %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty<br>
+  ret <2 x i32> %min<br>
+}<br>
+<br>
+define <2 x i32> @smin_of_nots(<2 x i32> %x, <2 x i32> %y) {<br>
+; CHECK-LABEL: @smin_of_nots(<br>
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <2 x i32> %x, %y<br>
+; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> %x, <2 x i32> %y<br>
+; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP2]], <i32 -1, i32 -1><br>
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]<br>
+;<br>
+  %notx = xor <2 x i32> %x, <i32 -1, i32 -1><br>
+  %noty = xor <2 x i32> %y, <i32 -1, i32 -1><br>
+  %cmp = icmp sle <2 x i32> %notx, %noty<br>
+  %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty<br>
+  ret <2 x i32> %min<br>
+}<br>
+<br>
 define i32 @compute_min_2(i32 %x, i32 %y) {<br>
 ; CHECK-LABEL: @compute_min_2(<br>
 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 %x, %y<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>