Fix SCEV forgetMemoizedResults should search and destroy backedge exprs.

Fixes 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 loop back edges expression.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177986 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-03-26 03:14:53 +00:00
parent 7fc162f893
commit e74c2e86cb
3 changed files with 68 additions and 0 deletions

View File

@ -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();
};

View File

@ -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;

View File

@ -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
}