[llvm] r251050 - [SCEV] Teach SCEV some axioms about non-wrapping arithmetic

Richard Trieu via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 5 15:24:14 PST 2015


This has been reverted in r252231 to fix a miscompile.  See bug:
https://llvm.org/bugs/show_bug.cgi?id=25421

On Thu, Oct 22, 2015 at 12:57 PM, Sanjoy Das via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: sanjoy
> Date: Thu Oct 22 14:57:29 2015
> New Revision: 251050
>
> URL: http://llvm.org/viewvc/llvm-project?rev=251050&view=rev
> Log:
> [SCEV] Teach SCEV some axioms about non-wrapping arithmetic
>
> Summary:
>  - A s<  (A + C)<nsw> if C >  0
>  - A s<= (A + C)<nsw> if C >= 0
>  - (A + C)<nsw> s<  A if C <  0
>  - (A + C)<nsw> s<= A if C <= 0
>
> Right now `C` needs to be a constant, but we can later generalize it to
> be a non-constant if needed.
>
> Reviewers: atrick, hfinkel, reames, nlewycky
>
> Subscribers: sanjoy, llvm-commits
>
> Differential Revision: http://reviews.llvm.org/D13686
>
> Modified:
>     llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
>     llvm/trunk/lib/Analysis/ScalarEvolution.cpp
>     llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll
>
> Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=251050&r1=251049&r2=251050&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
> +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Thu Oct 22 14:57:29
> 2015
> @@ -576,6 +576,14 @@ namespace llvm {
>      bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
>                                      const SCEV *LHS, const SCEV *RHS);
>
> +    /// Try to prove the condition described by "LHS Pred RHS" by ruling
> out
> +    /// integer overflow.
> +    ///
> +    /// For instance, this will return true for "A s< (A + C)<nsw>" if C
> is
> +    /// positive.
> +    bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
> +                                       const SCEV *LHS, const SCEV *RHS);
> +
>      /// Try to split Pred LHS RHS into logical conjunctions (and's) and
> try to
>      /// prove them individually.
>      bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, const
> SCEV *LHS,
>
> Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=251050&r1=251049&r2=251050&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
> +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Oct 22 14:57:29 2015
> @@ -7162,6 +7162,60 @@ ScalarEvolution::isKnownPredicateWithRan
>    return false;
>  }
>
> +bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate
> Pred,
> +                                                    const SCEV *LHS,
> +                                                    const SCEV *RHS) {
> +
> +  // Match Result to (X + Y)<ExpectedFlags> where Y is a constant integer.
> +  // Return Y via OutY.
> +  auto MatchBinaryAddToConst =
> +      [this](const SCEV *Result, const SCEV *X, APInt &OutY,
> +             SCEV::NoWrapFlags ExpectedFlags) {
> +    const SCEV *NonConstOp, *ConstOp;
> +    SCEV::NoWrapFlags FlagsPresent;
> +
> +    if (!splitBinaryAdd(Result, ConstOp, NonConstOp, FlagsPresent) ||
> +        !isa<SCEVConstant>(ConstOp) || NonConstOp != X)
> +      return false;
> +
> +    OutY = cast<SCEVConstant>(ConstOp)->getValue()->getValue();
> +    return (FlagsPresent & ExpectedFlags) != 0;
> +  };
> +
> +  APInt C;
> +
> +  switch (Pred) {
> +  default:
> +    break;
> +
> +  case ICmpInst::ICMP_SGE:
> +    std::swap(LHS, RHS);
> +  case ICmpInst::ICMP_SLE:
> +    // X s<= (X + C)<nsw> if C >= 0
> +    if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&
> C.isNonNegative())
> +      return true;
> +
> +    // (X + C)<nsw> s<= X if C <= 0
> +    if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) &&
> +        !C.isStrictlyPositive())
> +      return true;
> +
> +  case ICmpInst::ICMP_SGT:
> +    std::swap(LHS, RHS);
> +  case ICmpInst::ICMP_SLT:
> +    // X s< (X + C)<nsw> if C > 0
> +    if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&
> +        C.isStrictlyPositive())
> +      return true;
> +
> +    // (X + C)<nsw> s< X if C < 0
> +    if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) &&
> C.isNegative())
> +      return true;
> +  }
> +
> +  return false;
> +}
> +
>  bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate
> Pred,
>                                                     const SCEV *LHS,
>                                                     const SCEV *RHS) {
> @@ -7811,8 +7865,9 @@ ScalarEvolution::isImpliedCondOperandsHe
>    auto IsKnownPredicateFull =
>        [this](ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {
>      return isKnownPredicateWithRanges(Pred, LHS, RHS) ||
> -        IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
> -        IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS);
> +           IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
> +           IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
> +           isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
>    };
>
>    switch (Pred) {
>
> Modified: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll?rev=251050&r1=251049&r2=251050&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll
> (original)
> +++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll Thu
> Oct 22 14:57:29 2015
> @@ -477,4 +477,63 @@ define void @func_21(i32* %length.ptr, i
>    ret void
>  }
>
> +define void @func_22(i32* %length.ptr) {
> +; CHECK-LABEL: @func_22(
> +
> +; This checks that the backedge condition, (I + 1) < Length - 1 implies
> +; (I + 1) < Length
> + entry:
> +  %length = load i32, i32* %length.ptr, !range !0
> +  %lim = sub i32 %length, 1
> +  %entry.cond = icmp sgt i32 %length, 1
> +  br i1 %entry.cond, label %loop, label %leave
> +
> + loop:
> +; CHECK: loop:
> +  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
> +  %iv.inc = add i32 %iv, 1
> +  %range.check = icmp slt i32 %iv, %length
> +  br i1 %range.check, label %be, label %leave
> +; CHECK:   br i1 true, label %be, label %leave.loopexit
> +; CHECK: be:
> +
> + be:
> +  call void @side_effect()
> +  %be.cond = icmp slt i32 %iv.inc, %lim
> +  br i1 %be.cond, label %loop, label %leave
> +
> + leave:
> +  ret void
> +}
> +
> +define void @func_23(i32* %length.ptr) {
> +; CHECK-LABEL: @func_23(
> +
> +; This checks that the backedge condition, (I + 1) < Length - 1 implies
> +; (I + 1) < Length
> + entry:
> +  %length = load i32, i32* %length.ptr, !range !0
> +  %lim = sub i32 %length, 1
> +  %entry.cond = icmp sgt i32 %length, 1
> +  br i1 %entry.cond, label %loop, label %leave
> +
> + loop:
> +; CHECK: loop:
> +  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
> +  %iv.inc = add i32 %iv, 1
> +  %range.check = icmp sle i32 %iv, %length
> +  br i1 %range.check, label %be, label %leave
> +; CHECK:   br i1 true, label %be, label %leave.loopexit
> +; CHECK: be:
> +
> + be:
> +  call void @side_effect()
> +  %be.cond = icmp sle i32 %iv.inc, %lim
> +  br i1 %be.cond, label %loop, label %leave
> +
> + leave:
> +  ret void
> +}
> +
> +
>  !0 = !{i32 0, i32 2147483647}
>
>
> _______________________________________________
> 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/20151105/51eb7f66/attachment.html>


More information about the llvm-commits mailing list