diff options
-rw-r--r-- | include/llvm/Analysis/ScalarEvolution.h | 4 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 30 | ||||
-rw-r--r-- | test/Analysis/ScalarEvolution/scev-invalid.ll | 34 |
3 files changed, 68 insertions, 0 deletions
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 42fd392..306549f 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -338,6 +338,10 @@ namespace llvm { /// getMax - Get the max backedge taken count for the loop. const SCEV *getMax(ScalarEvolution *SE) const; + /// Return true if any backedge taken count expressions refer to the given + /// subexpression. + bool hasOperand(const SCEV *S, ScalarEvolution *SE) const; + /// clear - Invalidate this result and free associated memory. void clear(); }; diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 07d8329..6ea915f 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -4230,6 +4230,25 @@ ScalarEvolution::BackedgeTakenInfo::getMax(ScalarEvolution *SE) const { return Max ? Max : SE->getCouldNotCompute(); } +bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S, + ScalarEvolution *SE) const { + if (Max && Max != SE->getCouldNotCompute() && SE->hasOperand(Max, S)) + return true; + + if (!ExitNotTaken.ExitingBlock) + return false; + + for (const ExitNotTakenInfo *ENT = &ExitNotTaken; + ENT != 0; ENT = ENT->getNextExit()) { + + if (ENT->ExactNotTaken != SE->getCouldNotCompute() + && SE->hasOperand(ENT->ExactNotTaken, S)) { + return true; + } + } + return false; +} + /// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each /// computable exit into a persistent ExitNotTakenInfo array. ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo( @@ -6940,6 +6959,17 @@ void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { BlockDispositions.erase(S); UnsignedRanges.erase(S); SignedRanges.erase(S); + + for (DenseMap<const Loop*, BackedgeTakenInfo>::iterator I = + BackedgeTakenCounts.begin(), E = BackedgeTakenCounts.end(); I != E; ) { + BackedgeTakenInfo &BEInfo = I->second; + if (BEInfo.hasOperand(S, this)) { + BEInfo.clear(); + BackedgeTakenCounts.erase(I++); + } + else + ++I; + } } typedef DenseMap<const Loop *, std::string> VerifyMap; diff --git a/test/Analysis/ScalarEvolution/scev-invalid.ll b/test/Analysis/ScalarEvolution/scev-invalid.ll new file mode 100644 index 0000000..aac0d31 --- /dev/null +++ b/test/Analysis/ScalarEvolution/scev-invalid.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -S -indvars -loop-unroll | FileCheck %s +; +; PR15570: SEGV: SCEV back-edge info invalid after dead code removal. +; +; Indvars creates a SCEV expression for the loop's back edge taken +; count, then determines that the comparison is always true and +; removes it. +; +; When loop-unroll asks for the expression, it contains a NULL +; SCEVUnknkown (as a CallbackVH). +; +; forgetMemoizedResults should invalidate the backedge taken count expression. + +; CHECK: @test +; CHECK-NOT: phi +; CHECK-NOT: icmp +; CHECK: ret void +define void @test() { +entry: + %xor1 = xor i32 0, 1 + br label %b17 + +b17: + br i1 undef, label %b22, label %b18 + +b18: + %phi1 = phi i32 [ %add1, %b18 ], [ %xor1, %b17 ] + %add1 = add nsw i32 %phi1, -1 + %cmp1 = icmp sgt i32 %add1, 0 + br i1 %cmp1, label %b18, label %b22 + +b22: + ret void +} |