Instead of eagerly creating new SCEVs to replace all SCEVs that are

affected after a PHI node has been analyzed, just remove affected
SCEVs from the Scalars map, so that they'll be (lazily) recreated as
needed. This avoids creating SCEV objects that aren't actually needed.

Also, rewrite the associated def-use walking code to be non-recursive
and to continue traversing past Instructions that don't have an
entry in the Scalars map.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77032 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2009-07-25 01:13:03 +00:00
parent b140f4907c
commit fef8bb24de
3 changed files with 84 additions and 178 deletions

View File

@ -96,15 +96,9 @@ namespace llvm {
/// ///
bool isAllOnesValue() const; bool isAllOnesValue() const;
/// replaceSymbolicValuesWithConcrete - If this SCEV internally references /// hasOperand - Test whether this SCEV has Op as a direct or
/// the symbolic value "Sym", construct and return a new SCEV that produces /// indirect operand.
/// the same value, but which uses the concrete value Conc instead of the virtual bool hasOperand(const SCEV *Op) const = 0;
/// symbolic value. If this SCEV does not use the symbolic value, it
/// returns itself.
virtual const SCEV *
replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const = 0;
/// dominates - Return true if elements that makes up this SCEV dominates /// dominates - Return true if elements that makes up this SCEV dominates
/// the specified basic block. /// the specified basic block.
@ -145,10 +139,7 @@ namespace llvm {
virtual const Type *getType() const; virtual const Type *getType() const;
virtual bool hasComputableLoopEvolution(const Loop *L) const; virtual bool hasComputableLoopEvolution(const Loop *L) const;
virtual void print(raw_ostream &OS) const; virtual void print(raw_ostream &OS) const;
virtual const SCEV * virtual bool hasOperand(const SCEV *Op) const;
replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const;
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const { virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const {
return true; return true;
@ -252,13 +243,11 @@ namespace llvm {
/// SCEVs. /// SCEVs.
const SCEV *createNodeForGEP(Operator *GEP); const SCEV *createNodeForGEP(Operator *GEP);
/// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value /// ForgetSymbolicValue - This looks up computed SCEV values for all
/// for the specified instruction and replaces any references to the /// instructions that depend on the given instruction and removes them from
/// symbolic value SymName with the specified value. This is used during /// the Scalars map if they reference SymName. This is used during PHI
/// PHI resolution. /// resolution.
void ReplaceSymbolicValueWithConcrete(Instruction *I, void ForgetSymbolicName(Instruction *I, const SCEV *SymName);
const SCEV *SymName,
const SCEV *NewVal);
/// getBECount - Subtract the end and start values and divide by the step, /// getBECount - Subtract the end and start values and divide by the step,
/// rounding up, to get the number of times the backedge is executed. Return /// rounding up, to get the number of times the backedge is executed. Return

View File

@ -52,10 +52,8 @@ namespace llvm {
virtual const Type *getType() const; virtual const Type *getType() const;
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym, virtual bool hasOperand(const SCEV *) const {
const SCEV *Conc, return false;
ScalarEvolution &SE) const {
return this;
} }
bool dominates(BasicBlock *BB, DominatorTree *DT) const { bool dominates(BasicBlock *BB, DominatorTree *DT) const {
@ -94,6 +92,10 @@ namespace llvm {
return Op->hasComputableLoopEvolution(L); return Op->hasComputableLoopEvolution(L);
} }
virtual bool hasOperand(const SCEV *O) const {
return Op == O || Op->hasOperand(O);
}
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -116,15 +118,6 @@ namespace llvm {
const SCEV *op, const Type *ty); const SCEV *op, const Type *ty);
public: public:
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const {
const SCEV *H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
return SE.getTruncateExpr(H, Ty);
}
virtual void print(raw_ostream &OS) const; virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -145,15 +138,6 @@ namespace llvm {
const SCEV *op, const Type *ty); const SCEV *op, const Type *ty);
public: public:
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const {
const SCEV *H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
return SE.getZeroExtendExpr(H, Ty);
}
virtual void print(raw_ostream &OS) const; virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -174,15 +158,6 @@ namespace llvm {
const SCEV *op, const Type *ty); const SCEV *op, const Type *ty);
public: public:
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const {
const SCEV *H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
return SE.getSignExtendExpr(H, Ty);
}
virtual void print(raw_ostream &OS) const; virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -240,6 +215,13 @@ namespace llvm {
return HasVarying; return HasVarying;
} }
virtual bool hasOperand(const SCEV *O) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
if (O == getOperand(i) || getOperand(i)->hasOperand(O))
return true;
return false;
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const; bool dominates(BasicBlock *BB, DominatorTree *DT) const;
virtual const Type *getType() const { return getOperand(0)->getType(); } virtual const Type *getType() const { return getOperand(0)->getType(); }
@ -267,10 +249,6 @@ namespace llvm {
: SCEVNAryExpr(ID, T, ops) {} : SCEVNAryExpr(ID, T, ops) {}
public: public:
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const;
virtual const char *getOperationStr() const = 0; virtual const char *getOperationStr() const = 0;
virtual void print(raw_ostream &OS) const; virtual void print(raw_ostream &OS) const;
@ -353,15 +331,8 @@ namespace llvm {
RHS->hasComputableLoopEvolution(L); RHS->hasComputableLoopEvolution(L);
} }
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym, virtual bool hasOperand(const SCEV *O) const {
const SCEV *Conc, return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O);
ScalarEvolution &SE) const {
const SCEV *L = LHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
const SCEV *R = RHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (L == LHS && R == RHS)
return this;
else
return SE.getUDivExpr(L, R);
} }
bool dominates(BasicBlock *BB, DominatorTree *DT) const; bool dominates(BasicBlock *BB, DominatorTree *DT) const;
@ -449,14 +420,10 @@ namespace llvm {
const SCEV *getNumIterationsInRange(ConstantRange Range, const SCEV *getNumIterationsInRange(ConstantRange Range,
ScalarEvolution &SE) const; ScalarEvolution &SE) const;
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const;
/// getPostIncExpr - Return an expression representing the value of /// getPostIncExpr - Return an expression representing the value of
/// this expression one iteration of the loop ahead. /// this expression one iteration of the loop ahead.
const SCEV *getPostIncExpr(ScalarEvolution &SE) const { const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
return SE.getAddExpr(this, getStepRecurrence(SE)); return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
} }
bool hasNoUnsignedOverflow() const { return SubclassData & (1 << 0); } bool hasNoUnsignedOverflow() const { return SubclassData & (1 << 0); }
@ -542,11 +509,8 @@ namespace llvm {
return false; // not computable return false; // not computable
} }
const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym, virtual bool hasOperand(const SCEV *) const {
const SCEV *Conc, return false;
ScalarEvolution &SE) const {
if (&*Sym == this) return Conc;
return this;
} }
bool dominates(BasicBlock *BB, DominatorTree *DT) const; bool dominates(BasicBlock *BB, DominatorTree *DT) const;

View File

@ -163,12 +163,9 @@ bool SCEVCouldNotCompute::hasComputableLoopEvolution(const Loop *L) const {
return false; return false;
} }
const SCEV * bool SCEVCouldNotCompute::hasOperand(const SCEV *) const {
SCEVCouldNotCompute::replaceSymbolicValuesWithConcrete( llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
const SCEV *Sym, return false;
const SCEV *Conc,
ScalarEvolution &SE) const {
return this;
} }
void SCEVCouldNotCompute::print(raw_ostream &OS) const { void SCEVCouldNotCompute::print(raw_ostream &OS) const {
@ -260,39 +257,6 @@ void SCEVCommutativeExpr::print(raw_ostream &OS) const {
OS << ")"; OS << ")";
} }
const SCEV *
SCEVCommutativeExpr::replaceSymbolicValuesWithConcrete(
const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
const SCEV *H =
getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
SmallVector<const SCEV *, 8> NewOps;
NewOps.reserve(getNumOperands());
for (unsigned j = 0; j != i; ++j)
NewOps.push_back(getOperand(j));
NewOps.push_back(H);
for (++i; i != e; ++i)
NewOps.push_back(getOperand(i)->
replaceSymbolicValuesWithConcrete(Sym, Conc, SE));
if (isa<SCEVAddExpr>(this))
return SE.getAddExpr(NewOps);
else if (isa<SCEVMulExpr>(this))
return SE.getMulExpr(NewOps);
else if (isa<SCEVSMaxExpr>(this))
return SE.getSMaxExpr(NewOps);
else if (isa<SCEVUMaxExpr>(this))
return SE.getUMaxExpr(NewOps);
else
llvm_unreachable("Unknown commutative expr!");
}
}
return this;
}
bool SCEVNAryExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { bool SCEVNAryExpr::dominates(BasicBlock *BB, DominatorTree *DT) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
if (!getOperand(i)->dominates(BB, DT)) if (!getOperand(i)->dominates(BB, DT))
@ -318,30 +282,6 @@ const Type *SCEVUDivExpr::getType() const {
return RHS->getType(); return RHS->getType();
} }
const SCEV *
SCEVAddRecExpr::replaceSymbolicValuesWithConcrete(const SCEV *Sym,
const SCEV *Conc,
ScalarEvolution &SE) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
const SCEV *H =
getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
SmallVector<const SCEV *, 8> NewOps;
NewOps.reserve(getNumOperands());
for (unsigned j = 0; j != i; ++j)
NewOps.push_back(getOperand(j));
NewOps.push_back(H);
for (++i; i != e; ++i)
NewOps.push_back(getOperand(i)->
replaceSymbolicValuesWithConcrete(Sym, Conc, SE));
return SE.getAddRecExpr(NewOps, L);
}
}
return this;
}
bool SCEVAddRecExpr::isLoopInvariant(const Loop *QueryLoop) const { bool SCEVAddRecExpr::isLoopInvariant(const Loop *QueryLoop) const {
// Add recurrences are never invariant in the function-body (null loop). // Add recurrences are never invariant in the function-body (null loop).
if (!QueryLoop) if (!QueryLoop)
@ -2301,28 +2241,53 @@ const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS,
return getUMinExpr(PromotedLHS, PromotedRHS); return getUMinExpr(PromotedLHS, PromotedRHS);
} }
/// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value for /// PushDefUseChildren - Push users of the given Instruction
/// the specified instruction and replaces any references to the symbolic value /// onto the given Worklist.
/// SymName with the specified value. This is used during PHI resolution. 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));
}
/// ForgetSymbolicValue - This looks up computed SCEV values for all
/// instructions that depend on the given instruction and removes them from
/// the Scalars map if they reference SymName. This is used during PHI
/// resolution.
void void
ScalarEvolution::ReplaceSymbolicValueWithConcrete(Instruction *I, ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
const SCEV *SymName, SmallVector<Instruction *, 16> Worklist;
const SCEV *NewVal) { PushDefUseChildren(I, Worklist);
std::map<SCEVCallbackVH, const SCEV *>::iterator SI =
Scalars.find(SCEVCallbackVH(I, this));
if (SI == Scalars.end()) return;
const SCEV *NV = SmallPtrSet<Instruction *, 8> Visited;
SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal, *this); Visited.insert(I);
if (NV == SI->second) return; // No change. while (!Worklist.empty()) {
Instruction *I = Worklist.pop_back_val();
if (!Visited.insert(I)) continue;
SI->second = NV; // Update the scalars map! std::map<SCEVCallbackVH, const SCEV*>::iterator It =
Scalars.find(static_cast<Value *>(I));
if (It != Scalars.end()) {
// Short-circuit the def-use traversal if the symbolic name
// ceases to appear in expressions.
if (!It->second->hasOperand(SymName))
continue;
// Any instruction values that use this instruction might also need to be // SCEVUnknown for a PHI either means that it has an unrecognized
// updated! // structure, or it's a PHI that's in the progress of being computed
for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); // by createNodeForPHI. In the former case, additional loop trip
UI != E; ++UI) // count information isn't going to change anything. In the later
ReplaceSymbolicValueWithConcrete(cast<Instruction>(*UI), SymName, NewVal); // 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);
}
PushDefUseChildren(I, Worklist);
}
} }
/// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in /// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in
@ -2345,7 +2310,8 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
// Using this symbolic name for the PHI, analyze the value coming around // Using this symbolic name for the PHI, analyze the value coming around
// the back-edge. // the back-edge.
const SCEV *BEValue = getSCEV(PN->getIncomingValue(BackEdge)); Value *BEValueV = PN->getIncomingValue(BackEdge);
const SCEV *BEValue = getSCEV(BEValueV);
// NOTE: If BEValue is loop invariant, we know that the PHI node just // NOTE: If BEValue is loop invariant, we know that the PHI node just
// has a special value for the first iteration of the loop. // has a special value for the first iteration of the loop.
@ -2382,11 +2348,10 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
getAddRecExpr(StartVal, Accum, L); getAddRecExpr(StartVal, Accum, L);
// Okay, for the entire analysis of this edge we assumed the PHI // Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and update all of the // to be symbolic. We now need to go back and purge all of the
// entries for the scalars that use the PHI (except for the PHI // entries for the scalars that use the symbolic expression.
// itself) to use the new analyzed value instead of the "symbolic" ForgetSymbolicName(PN, SymbolicName);
// value. Scalars[SCEVCallbackVH(PN, this)] = PHISCEV;
ReplaceSymbolicValueWithConcrete(PN, SymbolicName, PHISCEV);
return PHISCEV; return PHISCEV;
} }
} }
@ -2408,11 +2373,10 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
getAddRecExpr(StartVal, AddRec->getOperand(1), L); getAddRecExpr(StartVal, AddRec->getOperand(1), L);
// Okay, for the entire analysis of this edge we assumed the PHI // Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and update all of the // to be symbolic. We now need to go back and purge all of the
// entries for the scalars that use the PHI (except for the PHI // entries for the scalars that use the symbolic expression.
// itself) to use the new analyzed value instead of the "symbolic" ForgetSymbolicName(PN, SymbolicName);
// value. Scalars[SCEVCallbackVH(PN, this)] = PHISCEV;
ReplaceSymbolicValueWithConcrete(PN, SymbolicName, PHISCEV);
return PHISCEV; return PHISCEV;
} }
} }
@ -3058,17 +3022,6 @@ PushLoopPHIs(const Loop *L, SmallVectorImpl<Instruction *> &Worklist) {
Worklist.push_back(PN); 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 & const ScalarEvolution::BackedgeTakenInfo &
ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// Initially insert a CouldNotCompute for this loop. If the insertion // Initially insert a CouldNotCompute for this loop. If the insertion