///
bool isAllOnesValue() const;
- /// replaceSymbolicValuesWithConcrete - If this SCEV internally references
- /// the symbolic value "Sym", construct and return a new SCEV that produces
- /// the same value, but which uses the concrete value Conc instead of the
- /// 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;
+ /// hasOperand - Test whether this SCEV has Op as a direct or
+ /// indirect operand.
+ virtual bool hasOperand(const SCEV *Op) const = 0;
/// dominates - Return true if elements that makes up this SCEV dominates
/// the specified basic block.
virtual const Type *getType() const;
virtual bool hasComputableLoopEvolution(const Loop *L) const;
virtual void print(raw_ostream &OS) const;
- virtual const SCEV *
- replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const;
+ virtual bool hasOperand(const SCEV *Op) const;
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const {
return true;
/// SCEVs.
const SCEV *createNodeForGEP(Operator *GEP);
- /// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value
- /// for the specified instruction and replaces any references to the
- /// symbolic value SymName with the specified value. This is used during
- /// PHI resolution.
- void ReplaceSymbolicValueWithConcrete(Instruction *I,
- const SCEV *SymName,
- const SCEV *NewVal);
+ /// 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 ForgetSymbolicName(Instruction *I, const SCEV *SymName);
/// 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
virtual const Type *getType() const;
- const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const {
- return this;
+ virtual bool hasOperand(const SCEV *) const {
+ return false;
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const {
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;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
const SCEV *op, const Type *ty);
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;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
const SCEV *op, const Type *ty);
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;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
const SCEV *op, const Type *ty);
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;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
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;
virtual const Type *getType() const { return getOperand(0)->getType(); }
: SCEVNAryExpr(ID, T, ops) {}
public:
- const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const;
-
virtual const char *getOperationStr() const = 0;
virtual void print(raw_ostream &OS) const;
RHS->hasComputableLoopEvolution(L);
}
- const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- 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);
+ virtual bool hasOperand(const SCEV *O) const {
+ return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O);
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
const SCEV *getNumIterationsInRange(ConstantRange Range,
ScalarEvolution &SE) const;
- const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const;
-
/// getPostIncExpr - Return an expression representing the value of
/// this expression one iteration of the loop ahead.
- const SCEV *getPostIncExpr(ScalarEvolution &SE) const {
- return SE.getAddExpr(this, getStepRecurrence(SE));
+ const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
+ return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
}
bool hasNoUnsignedOverflow() const { return SubclassData & (1 << 0); }
return false; // not computable
}
- const SCEV *replaceSymbolicValuesWithConcrete(const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const {
- if (&*Sym == this) return Conc;
- return this;
+ virtual bool hasOperand(const SCEV *) const {
+ return false;
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
return false;
}
-const SCEV *
-SCEVCouldNotCompute::replaceSymbolicValuesWithConcrete(
- const SCEV *Sym,
- const SCEV *Conc,
- ScalarEvolution &SE) const {
- return this;
+bool SCEVCouldNotCompute::hasOperand(const SCEV *) const {
+ llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
+ return false;
}
void SCEVCouldNotCompute::print(raw_ostream &OS) const {
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 {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
if (!getOperand(i)->dominates(BB, DT))
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 {
// Add recurrences are never invariant in the function-body (null loop).
if (!QueryLoop)
return getUMinExpr(PromotedLHS, PromotedRHS);
}
-/// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value for
-/// the specified instruction and replaces any references to the symbolic value
-/// SymName with the specified value. This is used during PHI resolution.
+/// 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));
+}
+
+/// 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
-ScalarEvolution::ReplaceSymbolicValueWithConcrete(Instruction *I,
- const SCEV *SymName,
- const SCEV *NewVal) {
- std::map<SCEVCallbackVH, const SCEV *>::iterator SI =
- Scalars.find(SCEVCallbackVH(I, this));
- if (SI == Scalars.end()) return;
+ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
+ SmallVector<Instruction *, 16> Worklist;
+ PushDefUseChildren(I, Worklist);
- const SCEV *NV =
- SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal, *this);
- if (NV == SI->second) return; // No change.
+ SmallPtrSet<Instruction *, 8> Visited;
+ Visited.insert(I);
+ 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;
+
+ // 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);
+ }
- // Any instruction values that use this instruction might also need to be
- // updated!
- for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
- UI != E; ++UI)
- ReplaceSymbolicValueWithConcrete(cast<Instruction>(*UI), SymName, NewVal);
+ PushDefUseChildren(I, Worklist);
+ }
}
/// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in
// Using this symbolic name for the PHI, analyze the value coming around
// 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
// has a special value for the first iteration of the loop.
getAddRecExpr(StartVal, Accum, L);
// 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
- // entries for the scalars that use the PHI (except for the PHI
- // itself) to use the new analyzed value instead of the "symbolic"
- // value.
- ReplaceSymbolicValueWithConcrete(PN, SymbolicName, PHISCEV);
+ // to be symbolic. We now need to go back and purge all of the
+ // entries for the scalars that use the symbolic expression.
+ ForgetSymbolicName(PN, SymbolicName);
+ Scalars[SCEVCallbackVH(PN, this)] = PHISCEV;
return PHISCEV;
}
}
getAddRecExpr(StartVal, AddRec->getOperand(1), L);
// 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
- // entries for the scalars that use the PHI (except for the PHI
- // itself) to use the new analyzed value instead of the "symbolic"
- // value.
- ReplaceSymbolicValueWithConcrete(PN, SymbolicName, PHISCEV);
+ // to be symbolic. We now need to go back and purge all of the
+ // entries for the scalars that use the symbolic expression.
+ ForgetSymbolicName(PN, SymbolicName);
+ Scalars[SCEVCallbackVH(PN, this)] = PHISCEV;
return PHISCEV;
}
}
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