mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
Merge the implementations of isLoopInvariant and hasComputableLoopEvolution, and
memoize the results. This improves compile time in code which highly complex expressions which get queried many times. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119584 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e7c682b543
commit
714b5290b0
@ -142,6 +142,16 @@ namespace llvm {
|
||||
/// they must ask this class for services.
|
||||
///
|
||||
class ScalarEvolution : public FunctionPass {
|
||||
public:
|
||||
/// LoopDisposition - An enum describing the relationship between a
|
||||
/// SCEV and a loop.
|
||||
enum LoopDisposition {
|
||||
LoopVariant, ///< The SCEV is loop-variant (unknown).
|
||||
LoopInvariant, ///< The SCEV is loop-invariant.
|
||||
LoopComputable ///< The SCEV varies predictably with the loop.
|
||||
};
|
||||
|
||||
private:
|
||||
/// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
|
||||
/// notified whenever a Value is deleted.
|
||||
class SCEVCallbackVH : public CallbackVH {
|
||||
@ -229,6 +239,13 @@ namespace llvm {
|
||||
std::map<const SCEV *,
|
||||
std::map<const Loop *, const SCEV *> > ValuesAtScopes;
|
||||
|
||||
/// LoopDispositions - Memoized computeLoopDisposition results.
|
||||
std::map<const SCEV *,
|
||||
std::map<const Loop *, LoopDisposition> > LoopDispositions;
|
||||
|
||||
/// computeLoopDisposition - Compute a LoopDisposition value.
|
||||
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
|
||||
|
||||
/// UnsignedRanges - Memoized results from getUnsignedRange
|
||||
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
|
||||
|
||||
@ -663,6 +680,10 @@ namespace llvm {
|
||||
const SCEV *&LHS,
|
||||
const SCEV *&RHS);
|
||||
|
||||
/// getLoopDisposition - Return the "disposition" of the given SCEV with
|
||||
/// respect to the given loop.
|
||||
LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
|
||||
|
||||
/// isLoopInvariant - Return true if the value of the given SCEV is
|
||||
/// unchanging in the specified loop.
|
||||
bool isLoopInvariant(const SCEV *S, const Loop *L);
|
||||
|
@ -326,6 +326,7 @@ SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
void SCEVUnknown::deleted() {
|
||||
// Clear this SCEVUnknown from various maps.
|
||||
SE->ValuesAtScopes.erase(this);
|
||||
SE->LoopDispositions.erase(this);
|
||||
SE->UnsignedRanges.erase(this);
|
||||
SE->SignedRanges.erase(this);
|
||||
|
||||
@ -339,6 +340,7 @@ void SCEVUnknown::deleted() {
|
||||
void SCEVUnknown::allUsesReplacedWith(Value *New) {
|
||||
// Clear this SCEVUnknown from various maps.
|
||||
SE->ValuesAtScopes.erase(this);
|
||||
SE->LoopDispositions.erase(this);
|
||||
SE->UnsignedRanges.erase(this);
|
||||
SE->SignedRanges.erase(this);
|
||||
|
||||
@ -2635,6 +2637,7 @@ ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) {
|
||||
!isa<SCEVUnknown>(Old) ||
|
||||
(I != PN && Old == SymName)) {
|
||||
ValuesAtScopes.erase(Old);
|
||||
LoopDispositions.erase(Old);
|
||||
UnsignedRanges.erase(Old);
|
||||
SignedRanges.erase(Old);
|
||||
ValueExprMap.erase(It);
|
||||
@ -3675,6 +3678,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
|
||||
// own when it gets to that point.
|
||||
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
|
||||
ValuesAtScopes.erase(Old);
|
||||
LoopDispositions.erase(Old);
|
||||
UnsignedRanges.erase(Old);
|
||||
SignedRanges.erase(Old);
|
||||
ValueExprMap.erase(It);
|
||||
@ -3710,6 +3714,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
|
||||
if (It != ValueExprMap.end()) {
|
||||
const SCEV *Old = It->second;
|
||||
ValuesAtScopes.erase(Old);
|
||||
LoopDispositions.erase(Old);
|
||||
UnsignedRanges.erase(Old);
|
||||
SignedRanges.erase(Old);
|
||||
ValueExprMap.erase(It);
|
||||
@ -3746,6 +3751,7 @@ void ScalarEvolution::forgetValue(Value *V) {
|
||||
if (It != ValueExprMap.end()) {
|
||||
const SCEV *Old = It->second;
|
||||
ValuesAtScopes.erase(Old);
|
||||
LoopDispositions.erase(Old);
|
||||
UnsignedRanges.erase(Old);
|
||||
SignedRanges.erase(Old);
|
||||
ValueExprMap.erase(It);
|
||||
@ -5803,6 +5809,7 @@ void ScalarEvolution::releaseMemory() {
|
||||
BackedgeTakenCounts.clear();
|
||||
ConstantEvolutionLoopExitValue.clear();
|
||||
ValuesAtScopes.clear();
|
||||
LoopDispositions.clear();
|
||||
UnsignedRanges.clear();
|
||||
SignedRanges.clear();
|
||||
UniqueSCEVs.clear();
|
||||
@ -5901,126 +5908,106 @@ void ScalarEvolution::print(raw_ostream &OS, const Module *) const {
|
||||
PrintLoopInfo(OS, &SE, *I);
|
||||
}
|
||||
|
||||
bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
|
||||
ScalarEvolution::LoopDisposition
|
||||
ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
|
||||
std::map<const Loop *, LoopDisposition> &Values = LoopDispositions[S];
|
||||
std::pair<std::map<const Loop *, LoopDisposition>::iterator, bool> Pair =
|
||||
Values.insert(std::make_pair(L, LoopVariant));
|
||||
if (!Pair.second)
|
||||
return Pair.first->second;
|
||||
|
||||
LoopDisposition D = computeLoopDisposition(S, L);
|
||||
return LoopDispositions[S][L] = D;
|
||||
}
|
||||
|
||||
ScalarEvolution::LoopDisposition
|
||||
ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
|
||||
switch (S->getSCEVType()) {
|
||||
case scConstant:
|
||||
return true;
|
||||
return LoopInvariant;
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
return isLoopInvariant(cast<SCEVCastExpr>(S)->getOperand(), L);
|
||||
return getLoopDisposition(cast<SCEVCastExpr>(S)->getOperand(), L);
|
||||
case scAddRecExpr: {
|
||||
const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
|
||||
|
||||
// If L is the addrec's loop, it's computable.
|
||||
if (AR->getLoop() == L)
|
||||
return LoopComputable;
|
||||
|
||||
// Add recurrences are never invariant in the function-body (null loop).
|
||||
if (!L)
|
||||
return false;
|
||||
return LoopVariant;
|
||||
|
||||
// This recurrence is variant w.r.t. L if L contains AR's loop.
|
||||
if (L->contains(AR->getLoop()))
|
||||
return false;
|
||||
return LoopVariant;
|
||||
|
||||
// This recurrence is invariant w.r.t. L if AR's loop contains L.
|
||||
if (AR->getLoop()->contains(L))
|
||||
return true;
|
||||
return LoopInvariant;
|
||||
|
||||
// This recurrence is variant w.r.t. L if any of its operands
|
||||
// are variant.
|
||||
for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end();
|
||||
I != E; ++I)
|
||||
if (!isLoopInvariant(*I, L))
|
||||
return false;
|
||||
return LoopVariant;
|
||||
|
||||
// Otherwise it's loop-invariant.
|
||||
return true;
|
||||
return LoopInvariant;
|
||||
}
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
case scUMaxExpr:
|
||||
case scSMaxExpr: {
|
||||
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
|
||||
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
|
||||
I != E; ++I)
|
||||
if (!isLoopInvariant(*I, L))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
case scUDivExpr: {
|
||||
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
|
||||
return isLoopInvariant(UDiv->getLHS(), L) &&
|
||||
isLoopInvariant(UDiv->getRHS(), L);
|
||||
}
|
||||
case scUnknown:
|
||||
// All non-instruction values are loop invariant. All instructions are loop
|
||||
// invariant if they are not contained in the specified loop.
|
||||
// Instructions are never considered invariant in the function body
|
||||
// (null loop) because they are defined within the "loop".
|
||||
if (Instruction *I = dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
|
||||
return L && !L->contains(I);
|
||||
return true;
|
||||
case scCouldNotCompute:
|
||||
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
|
||||
return false;
|
||||
default: break;
|
||||
}
|
||||
llvm_unreachable("Unknown SCEV kind!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
|
||||
switch (S->getSCEVType()) {
|
||||
case scConstant:
|
||||
return false;
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
return hasComputableLoopEvolution(cast<SCEVCastExpr>(S)->getOperand(), L);
|
||||
case scAddRecExpr:
|
||||
return cast<SCEVAddRecExpr>(S)->getLoop() == L;
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
case scUMaxExpr:
|
||||
case scSMaxExpr: {
|
||||
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
|
||||
bool HasVarying = false;
|
||||
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
|
||||
I != E; ++I) {
|
||||
const SCEV *Op = *I;
|
||||
if (!isLoopInvariant(Op, L)) {
|
||||
if (hasComputableLoopEvolution(Op, L))
|
||||
HasVarying = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
LoopDisposition D = getLoopDisposition(*I, L);
|
||||
if (D == LoopVariant)
|
||||
return LoopVariant;
|
||||
if (D == LoopComputable)
|
||||
HasVarying = true;
|
||||
}
|
||||
return HasVarying;
|
||||
return HasVarying ? LoopComputable : LoopInvariant;
|
||||
}
|
||||
case scUDivExpr: {
|
||||
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
|
||||
bool HasVarying = false;
|
||||
if (!isLoopInvariant(UDiv->getLHS(), L)) {
|
||||
if (hasComputableLoopEvolution(UDiv->getLHS(), L))
|
||||
HasVarying = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!isLoopInvariant(UDiv->getRHS(), L)) {
|
||||
if (hasComputableLoopEvolution(UDiv->getRHS(), L))
|
||||
HasVarying = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return HasVarying;
|
||||
LoopDisposition LD = getLoopDisposition(UDiv->getLHS(), L);
|
||||
if (LD == LoopVariant)
|
||||
return LoopVariant;
|
||||
LoopDisposition RD = getLoopDisposition(UDiv->getRHS(), L);
|
||||
if (RD == LoopVariant)
|
||||
return LoopVariant;
|
||||
return (LD == LoopInvariant && RD == LoopInvariant) ?
|
||||
LoopInvariant : LoopComputable;
|
||||
}
|
||||
case scUnknown:
|
||||
return false;
|
||||
// All non-instruction values are loop invariant. All instructions are loop
|
||||
// invariant if they are not contained in the specified loop.
|
||||
// Instructions are never considered invariant in the function body
|
||||
// (null loop) because they are defined within the "loop".
|
||||
if (Instruction *I = dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
|
||||
return (L && !L->contains(I)) ? LoopInvariant : LoopVariant;
|
||||
return LoopInvariant;
|
||||
case scCouldNotCompute:
|
||||
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
|
||||
return false;
|
||||
return LoopVariant;
|
||||
default: break;
|
||||
}
|
||||
llvm_unreachable("Unknown SCEV kind!");
|
||||
return false;
|
||||
return LoopVariant;
|
||||
}
|
||||
|
||||
bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
|
||||
return getLoopDisposition(S, L) == LoopInvariant;
|
||||
}
|
||||
|
||||
bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
|
||||
return getLoopDisposition(S, L) == LoopComputable;
|
||||
}
|
||||
|
||||
bool ScalarEvolution::dominates(const SCEV *S, BasicBlock *BB) const {
|
||||
|
Loading…
Reference in New Issue
Block a user