<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>