From eb6dd23c95c1df08a4a924e2125158c5203b0991 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 26 Mar 2012 22:33:59 +0000 Subject: [PATCH] SCEV fix: Handle loop invariant loads. Fixes PR11882: NULL dereference in ComputeLoadConstantCompareExitLimit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153480 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ScalarEvolution.cpp | 6 ++- .../2012-03-26-LoadConstant.ll | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 test/Analysis/ScalarEvolution/2012-03-26-LoadConstant.ll diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 0c0ceeb9516..8b5397946ec 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -4619,6 +4619,10 @@ ScalarEvolution::ComputeLoadConstantCompareExitLimit( Indexes.push_back(0); } + // Loop-invariant loads may be a byproduct of loop optimization. Skip them. + if (!VarIdx) + return getCouldNotCompute(); + // Okay, we know we have a (load (gep GV, 0, X)) comparison with a constant. // Check to see if X is a loop variant variable value now. const SCEV *Idx = getSCEV(VarIdx); @@ -6845,7 +6849,7 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) { return ProperlyDominatesBlock; case scCouldNotCompute: llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); - default: + default: llvm_unreachable("Unknown SCEV kind!"); } } diff --git a/test/Analysis/ScalarEvolution/2012-03-26-LoadConstant.ll b/test/Analysis/ScalarEvolution/2012-03-26-LoadConstant.ll new file mode 100644 index 00000000000..138c015f12c --- /dev/null +++ b/test/Analysis/ScalarEvolution/2012-03-26-LoadConstant.ll @@ -0,0 +1,47 @@ +; RUN: opt < %s -basicaa -globalopt -instcombine -loop-rotate -licm -instcombine -indvars -loop-deletion -constmerge -S +; PR11882: ComputeLoadConstantCompareExitLimit crash. +; +; for.body is deleted leaving a loop-invariant load. +; CHECK-NOT: for.body +target datalayout = "e-p:64:64:64-n32:64" + +@func_21_l_773 = external global i32, align 4 +@g_814 = external global i32, align 4 +@g_244 = internal global [1 x [0 x i32]] zeroinitializer, align 4 + +define void @func_21() nounwind uwtable ssp { +entry: + br label %lbl_818 + +lbl_818: ; preds = %for.end, %entry + call void (...)* @func_27() + store i32 0, i32* @g_814, align 4, !tbaa !0 + br label %for.cond + +for.cond: ; preds = %for.body, %lbl_818 + %0 = load i32* @g_814, align 4, !tbaa !0 + %cmp = icmp sle i32 %0, 0 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %idxprom = sext i32 %0 to i64 + %arrayidx = getelementptr inbounds [0 x i32]* getelementptr inbounds ([1 x [0 x i32]]* @g_244, i32 0, i64 0), i32 0, i64 %idxprom + %1 = load i32* %arrayidx, align 1, !tbaa !0 + store i32 %1, i32* @func_21_l_773, align 4, !tbaa !0 + store i32 1, i32* @g_814, align 4, !tbaa !0 + br label %for.cond + +for.end: ; preds = %for.cond + %2 = load i32* @func_21_l_773, align 4, !tbaa !0 + %tobool = icmp ne i32 %2, 0 + br i1 %tobool, label %lbl_818, label %if.end + +if.end: ; preds = %for.end + ret void +} + +declare void @func_27(...) + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null}