Make the code that updates ScalarEvolution's internal state in response

to a loop deletion more thorough. Don't prune the def-use tree search at
instructions that don't have SCEVs computed, because an instruction with
a user that has a computed SCEV may itself lack a computed SCEV.  Also,
remove loop-related values from the ValuesAtScopes and
ConstantEvolutionLoopExitValues maps as well.

This fixes a regression in 483.xalancbmk.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75030 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2009-07-08 19:23:34 +00:00
parent 85ebb0f66c
commit 59ae6b9987
2 changed files with 70 additions and 35 deletions

View File

@ -346,11 +346,6 @@ namespace llvm {
Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs,
const Loop *L);
/// forgetLoopPHIs - Delete the memoized SCEVs associated with the
/// PHI nodes in the given loop. This is used when the trip count of
/// the loop may have changed.
void forgetLoopPHIs(const Loop *L);
public:
static char ID; // Pass identification, replacement for typeid
ScalarEvolution();

View File

@ -81,6 +81,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <algorithm>
using namespace llvm;
@ -2856,6 +2857,29 @@ const SCEV *ScalarEvolution::getMaxBackedgeTakenCount(const Loop *L) {
return getBackedgeTakenInfo(L).Max;
}
/// PushLoopPHIs - Push PHI nodes in the header of the given loop
/// onto the given Worklist.
static void
PushLoopPHIs(const Loop *L, SmallVectorImpl<Instruction *> &Worklist) {
BasicBlock *Header = L->getHeader();
// Push all Loop-header PHIs onto the Worklist stack.
for (BasicBlock::iterator I = Header->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I)
Worklist.push_back(PN);
}
/// PushDefUseChildren - Push users of the given Instruction
/// onto the given Worklist.
static void
PushDefUseChildren(Instruction *I,
SmallVectorImpl<Instruction *> &Worklist) {
// Push the def-use children onto the Worklist stack.
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
UI != UE; ++UI)
Worklist.push_back(cast<Instruction>(UI));
}
const ScalarEvolution::BackedgeTakenInfo &
ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// Initially insert a CouldNotCompute for this loop. If the insertion
@ -2886,10 +2910,38 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// Now that we know more about the trip count for this loop, forget any
// existing SCEV values for PHI nodes in this loop since they are only
// conservative estimates made without the benefit
// of trip count information.
if (ItCount.hasAnyInfo())
forgetLoopPHIs(L);
// conservative estimates made without the benefit of trip count
// information. This is similar to the code in
// forgetLoopBackedgeTakenCount, except that it handles SCEVUnknown PHI
// nodes specially.
if (ItCount.hasAnyInfo()) {
SmallVector<Instruction *, 16> Worklist;
PushLoopPHIs(L, Worklist);
SmallPtrSet<Instruction *, 8> Visited;
while (!Worklist.empty()) {
Instruction *I = Worklist.pop_back_val();
if (!Visited.insert(I)) continue;
std::map<SCEVCallbackVH, const SCEV*>::iterator It =
Scalars.find(static_cast<Value *>(I));
if (It != Scalars.end()) {
// SCEVUnknown for a PHI either means that it has an unrecognized
// structure, or it's a PHI that's in the progress of being computed
// by createNodeForPHI. In the former case, additional loop trip count
// information isn't going to change anything. In the later case,
// createNodeForPHI will perform the necessary updates on its own when
// it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(It->second))
Scalars.erase(It);
ValuesAtScopes.erase(I);
if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN);
}
PushDefUseChildren(I, Worklist);
}
}
}
return Pair.first->second;
}
@ -2900,37 +2952,25 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
/// is deleted.
void ScalarEvolution::forgetLoopBackedgeTakenCount(const Loop *L) {
BackedgeTakenCounts.erase(L);
forgetLoopPHIs(L);
}
/// forgetLoopPHIs - Delete the memoized SCEVs associated with the
/// PHI nodes in the given loop. This is used when the trip count of
/// the loop may have changed.
void ScalarEvolution::forgetLoopPHIs(const Loop *L) {
BasicBlock *Header = L->getHeader();
// Push all Loop-header PHIs onto the Worklist stack, except those
// that are presently represented via a SCEVUnknown. SCEVUnknown for
// a PHI either means that it has an unrecognized structure, or it's
// a PHI that's in the progress of being computed by createNodeForPHI.
// In the former case, additional loop trip count information isn't
// going to change anything. In the later case, createNodeForPHI will
// perform the necessary updates on its own when it gets to that point.
SmallVector<Instruction *, 16> Worklist;
for (BasicBlock::iterator I = Header->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I) {
std::map<SCEVCallbackVH, const SCEV *>::iterator It =
Scalars.find((Value*)I);
if (It != Scalars.end() && !isa<SCEVUnknown>(It->second))
Worklist.push_back(PN);
}
PushLoopPHIs(L, Worklist);
SmallPtrSet<Instruction *, 8> Visited;
while (!Worklist.empty()) {
Instruction *I = Worklist.pop_back_val();
if (Scalars.erase(I))
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
UI != UE; ++UI)
Worklist.push_back(cast<Instruction>(UI));
if (!Visited.insert(I)) continue;
std::map<SCEVCallbackVH, const SCEV*>::iterator It =
Scalars.find(static_cast<Value *>(I));
if (It != Scalars.end()) {
Scalars.erase(It);
ValuesAtScopes.erase(I);
if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN);
}
PushDefUseChildren(I, Worklist);
}
}