summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Analysis/LazyValueInfo.cpp29
-rw-r--r--llvm/test/Transforms/CorrelatedValuePropagation/alloca.ll48
2 files changed, 77 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index cf7c3f90abf..98831545f10 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -1601,8 +1601,26 @@ LazyValueInfo LazyValueAnalysis::run(Function &F, FunctionAnalysisManager &FAM)
return LazyValueInfo(&AC, &TLI, DT);
}
+/// Returns true if we can statically tell that this value will never be a
+/// "useful" constant. In practice, this means we've got something like an
+/// alloca or a malloc call for which a comparison against a constant can
+/// only be guarding dead code. Note that we are potentially giving up some
+/// precision in dead code (a constant result) in favour of avoiding a
+/// expensive search for a easily answered common query.
+static bool isKnownNonConstant(Value *V) {
+ V = V->stripPointerCasts();
+ // The return val of alloc cannot be a Constant.
+ if (isa<AllocaInst>(V))
+ return true;
+ return false;
+}
+
Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB,
Instruction *CxtI) {
+ // Bail out early if V is known not to be a Constant.
+ if (isKnownNonConstant(V))
+ return nullptr;
+
const DataLayout &DL = BB->getModule()->getDataLayout();
LVILatticeVal Result =
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
@@ -1738,6 +1756,17 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
LazyValueInfo::Tristate
LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI) {
+ // Is or is not NonNull are common predicates being queried. If
+ // isKnownNonNull can tell us the result of the predicate, we can
+ // return it quickly. But this is only a fastpath, and falling
+ // through would still be correct.
+ if (V->getType()->isPointerTy() && C->isNullValue() &&
+ isKnownNonNull(V->stripPointerCasts())) {
+ if (Pred == ICmpInst::ICMP_EQ)
+ return LazyValueInfo::False;
+ else if (Pred == ICmpInst::ICMP_NE)
+ return LazyValueInfo::True;
+ }
const DataLayout &DL = CxtI->getModule()->getDataLayout();
LVILatticeVal Result = getImpl(PImpl, AC, &DL, DT).getValueAt(V, CxtI);
Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/alloca.ll b/llvm/test/Transforms/CorrelatedValuePropagation/alloca.ll
new file mode 100644
index 00000000000..2ae1664fdee
--- /dev/null
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/alloca.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -correlated-propagation -debug-only=lazy-value-info <%s 2>&1 | FileCheck %s
+;
+; Shortcut in Correlated Value Propagation ensures not to take Lazy Value Info
+; analysis for %a.i and %tmp because %a.i is defined by alloca and %tmp is
+; defined by alloca + bitcast. We know the ret value of alloca is nonnull.
+;
+; CHECK-NOT: LVI Getting edge value %a.i = alloca i64, align 8 at 'for.body'
+; CHECK-NOT: LVI Getting edge value %tmp = bitcast i64* %a.i to i8* from 'for.cond' to 'for.body'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@.str = private unnamed_addr constant [8 x i8] c"a = %l\0A\00", align 1
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start(i64, i8* nocapture)
+
+declare void @hoo(i64*)
+
+declare i32 @printf(i8* nocapture readonly, ...)
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end(i64, i8* nocapture)
+
+define void @goo(i32 %N, i64* %b) {
+entry:
+ %a.i = alloca i64, align 8
+ %tmp = bitcast i64* %a.i to i8*
+ %c = getelementptr inbounds i64, i64* %b, i64 0
+ br label %for.cond
+
+for.cond: ; preds = %for.body, %entry
+ %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+ %cmp = icmp slt i32 %i.0, %N
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ call void @llvm.lifetime.start(i64 8, i8* %tmp)
+ call void @hoo(i64* %a.i)
+ call void @hoo(i64* %c)
+ %tmp1 = load volatile i64, i64* %a.i, align 8
+ %call.i = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i64 %tmp1)
+ call void @llvm.lifetime.end(i64 8, i8* %tmp)
+ %inc = add nsw i32 %i.0, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
OpenPOWER on IntegriCloud