[llvm] r219834 - Teach ScalarEvolution to sharpen range information.
Sanjoy Das
sanjoy at playingwithpointers.com
Wed Oct 15 12:25:28 PDT 2014
Author: sanjoy
Date: Wed Oct 15 14:25:28 2014
New Revision: 219834
URL: http://llvm.org/viewvc/llvm-project?rev=219834&view=rev
Log:
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
Added:
llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll
Modified:
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=219834&r1=219833&r2=219834&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed Oct 15 14:25:28 2014
@@ -6782,6 +6782,44 @@ bool ScalarEvolution::isImpliedCond(ICmp
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<SCEVConstant>(C)) return false;
+
+ ConstantInt *CI = cast<SCEVConstant>(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))
Added: llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll?rev=219834&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range-metadata.ll Wed Oct 15 14:25:28 2014
@@ -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}
Modified: llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll?rev=219834&r1=219833&r2=219834&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll Wed Oct 15 14:25:28 2014
@@ -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 ]
More information about the llvm-commits
mailing list