From: Sanjoy Das Date: Wed, 15 Oct 2014 19:25:28 +0000 (+0000) Subject: Teach ScalarEvolution to sharpen range information. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=90c2f1455ae1e88aa31e68f4e7cdcdf955c945ed;p=platform%2Fupstream%2Fllvm.git Teach ScalarEvolution to sharpen range information. If x is known to have the range [a, b) in a loop predicated by (icmp ne x, a), its range can be sharpened to [a + 1, b). Get ScalarEvolution and hence IndVars to exploit this fact. This change triggers an optimization to widen-loop-comp.ll, so it had to be edited to get it to pass. phabricator: http://reviews.llvm.org/D5639 llvm-svn: 219834 --- diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index b015481..8d1c632 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6782,6 +6782,44 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, RHS, LHS, FoundLHS, FoundRHS); } + if (FoundPred == ICmpInst::ICMP_NE) { + // If we are predicated on something with range [a, b) known not + // equal to a, the range can be sharpened to [a + 1, b). Use this + // fact. + auto CheckRange = [this, Pred, LHS, RHS](const SCEV *C, const SCEV *V) { + if (!isa(C)) return false; + + ConstantInt *CI = cast(C)->getValue(); + APInt Min = ICmpInst::isSigned(Pred) ? + getSignedRange(V).getSignedMin() : getUnsignedRange(V).getUnsignedMin(); + + if (Min!= CI->getValue()) return false; // nothing to sharpen + Min++; + + // We know V >= Min, in the same signedness as in Pred. We can + // use this to simplify slt and ult. If the range had a single + // value, Min, we now know that FoundValue can never be true; + // and any answer is a correct answer. + + switch (Pred) { + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_UGT: + return isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min)); + + default: + llvm_unreachable("don't call with predicates other than ICMP_SGT " + "and ICMP_UGT"); + } + }; + + if ((Pred == ICmpInst::ICMP_SGT) || (Pred == ICmpInst::ICMP_UGT)) { + // Inequality is reflexive -- check both the combinations. + if (CheckRange(FoundLHS, FoundRHS) || CheckRange(FoundRHS, FoundLHS)) { + return true; + } + } + } + // Check whether the actual condition is beyond sufficient. if (FoundPred == ICmpInst::ICMP_EQ) if (ICmpInst::isTrueWhenEqual(Pred)) diff --git a/llvm/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll b/llvm/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll new file mode 100644 index 0000000..5faafe6 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll @@ -0,0 +1,39 @@ +;; RUN: opt -S < %s -indvars | FileCheck %s + +;; Check if llvm can narrow !range metadata based on loop entry +;; predicates. + +declare void @abort() + +define i1 @bounded_below(i32* nocapture readonly %buffer) { +entry: + %length = load i32* %buffer, !range !0 + %entry.pred = icmp eq i32 %length, 0 + br i1 %entry.pred, label %abort, label %loop.preheader + +loop.preheader: + br label %loop + +loop: + %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] + %oob.pred = icmp slt i32 %idx, %length + br i1 %oob.pred, label %loop.next, label %oob +; CHECK: br i1 true, label %loop.next, label %oob + +loop.next: + %idx.inc = add i32 %idx, 1 + %exit.pred = icmp slt i32 %idx.inc, %length + br i1 %exit.pred, label %loop, label %abort.loopexit + +abort.loopexit: + br label %abort + +abort: + ret i1 false + +oob: + tail call void @abort() + ret i1 false +} + +!0 = metadata !{i32 0, i32 100} diff --git a/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll b/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll index bfe74af..0930a0c 100644 --- a/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll +++ b/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll @@ -67,8 +67,7 @@ for.end: define void @test2([8 x i8]* %a, i8* %b, i8 %limit) { entry: %conv = zext i8 %limit to i32 - %cmp23 = icmp eq i8 %limit, 0 - br i1 %cmp23, label %for.cond1.preheader, label %for.cond1.preheader.us + br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us for.cond1.preheader.us: %storemerge5.us = phi i32 [ 0, %entry ], [ %inc14.us, %for.inc13.us ]