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