mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-13 07:50:41 +00:00
[SCEV] Combine two predicates into one; NFC
Both `loopHasNoSideEffects` and `loopHasNoAbnormalExits` involve walking the loop and maintaining similar sorts of caches. This commit changes SCEV to compute both the predicates via a single walk, and maintain a single cache instead of two. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282375 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
98e898ce46
commit
a80a7d1c30
@ -725,22 +725,32 @@ private:
|
||||
SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
|
||||
LoopDispositions;
|
||||
|
||||
/// Cache for \c loopHasNoAbnormalExits.
|
||||
DenseMap<const Loop *, bool> LoopHasNoAbnormalExits;
|
||||
struct LoopProperties {
|
||||
/// Set to true if the loop contains no instruction that can have side
|
||||
/// effects (i.e. via throwing an exception, volatile or atomic access).
|
||||
bool HasNoAbnormalExits;
|
||||
|
||||
/// Cache for \c loopHasNoSideEffects.
|
||||
DenseMap<const Loop *, bool> LoopHasNoSideEffects;
|
||||
/// Set to true if the loop contains no instruction that can abnormally exit
|
||||
/// the loop (i.e. via throwing an exception, by terminating the thread
|
||||
/// cleanly or by infinite looping in a called function). Strictly
|
||||
/// speaking, the last one is not leaving the loop, but is identical to
|
||||
/// leaving the loop for reasoning about undefined behavior.
|
||||
bool HasNoSideEffects;
|
||||
};
|
||||
|
||||
/// Returns true if \p L contains no instruction that can have side effects
|
||||
/// (i.e. via throwing an exception, volatile or atomic access).
|
||||
bool loopHasNoSideEffects(const Loop *L);
|
||||
/// Cache for \c getLoopProperties.
|
||||
DenseMap<const Loop *, LoopProperties> LoopPropertiesCache;
|
||||
|
||||
/// Returns true if \p L contains no instruction that can abnormally exit
|
||||
/// the loop (i.e. via throwing an exception, by terminating the thread
|
||||
/// cleanly or by infinite looping in a called function). Strictly
|
||||
/// speaking, the last one is not leaving the loop, but is identical to
|
||||
/// leaving the loop for reasoning about undefined behavior.
|
||||
bool loopHasNoAbnormalExits(const Loop *L);
|
||||
/// Return a \c LoopProperties instance for \p L, creating one if necessary.
|
||||
LoopProperties getLoopProperties(const Loop *L);
|
||||
|
||||
bool loopHasNoSideEffects(const Loop *L) {
|
||||
return getLoopProperties(L).HasNoSideEffects;
|
||||
}
|
||||
|
||||
bool loopHasNoAbnormalExits(const Loop *L) {
|
||||
return getLoopProperties(L).HasNoAbnormalExits;
|
||||
}
|
||||
|
||||
/// Compute a LoopDisposition value.
|
||||
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
|
||||
|
@ -4953,39 +4953,33 @@ bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) {
|
||||
return LatchControlDependentOnPoison && loopHasNoAbnormalExits(L);
|
||||
}
|
||||
|
||||
bool ScalarEvolution::loopHasNoSideEffects(const Loop *L) {
|
||||
auto Itr = LoopHasNoSideEffects.find(L);
|
||||
if (Itr == LoopHasNoSideEffects.end()) {
|
||||
auto NoSideEffectsInBB = [&](BasicBlock *BB) {
|
||||
return all_of(*BB, [](Instruction &I) {
|
||||
// Non-atomic, non-volatile stores are ok.
|
||||
if (auto *SI = dyn_cast<StoreInst>(&I))
|
||||
return SI->isSimple();
|
||||
ScalarEvolution::LoopProperties
|
||||
ScalarEvolution::getLoopProperties(const Loop *L) {
|
||||
typedef ScalarEvolution::LoopProperties LoopProperties;
|
||||
|
||||
return !I.mayHaveSideEffects();
|
||||
});
|
||||
auto Itr = LoopPropertiesCache.find(L);
|
||||
if (Itr == LoopPropertiesCache.end()) {
|
||||
auto HasSideEffects = [](Instruction *I) {
|
||||
if (auto *SI = dyn_cast<StoreInst>(I))
|
||||
return !SI->isSimple();
|
||||
|
||||
return I->mayHaveSideEffects();
|
||||
};
|
||||
|
||||
auto InsertPair = LoopHasNoSideEffects.insert(
|
||||
{L, all_of(L->getBlocks(), NoSideEffectsInBB)});
|
||||
assert(InsertPair.second && "We just checked!");
|
||||
Itr = InsertPair.first;
|
||||
}
|
||||
LoopProperties LP = {/* HasNoAbnormalExits */ true,
|
||||
/*HasNoSideEffects*/ true};
|
||||
|
||||
return Itr->second;
|
||||
}
|
||||
for (auto *BB : L->getBlocks())
|
||||
for (auto &I : *BB) {
|
||||
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
|
||||
LP.HasNoAbnormalExits = false;
|
||||
if (HasSideEffects(&I))
|
||||
LP.HasNoSideEffects = false;
|
||||
if (!LP.HasNoAbnormalExits && !LP.HasNoSideEffects)
|
||||
break; // We're already as pessimistic as we can get.
|
||||
}
|
||||
|
||||
bool ScalarEvolution::loopHasNoAbnormalExits(const Loop *L) {
|
||||
auto Itr = LoopHasNoAbnormalExits.find(L);
|
||||
if (Itr == LoopHasNoAbnormalExits.end()) {
|
||||
auto NoAbnormalExitInBB = [&](BasicBlock *BB) {
|
||||
return all_of(*BB, [](Instruction &I) {
|
||||
return isGuaranteedToTransferExecutionToSuccessor(&I);
|
||||
});
|
||||
};
|
||||
|
||||
auto InsertPair = LoopHasNoAbnormalExits.insert(
|
||||
{L, all_of(L->getBlocks(), NoAbnormalExitInBB)});
|
||||
auto InsertPair = LoopPropertiesCache.insert({L, LP});
|
||||
assert(InsertPair.second && "We just checked!");
|
||||
Itr = InsertPair.first;
|
||||
}
|
||||
@ -5561,8 +5555,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
|
||||
for (Loop *I : *L)
|
||||
forgetLoop(I);
|
||||
|
||||
LoopHasNoAbnormalExits.erase(L);
|
||||
LoopHasNoSideEffects.erase(L);
|
||||
LoopPropertiesCache.erase(L);
|
||||
}
|
||||
|
||||
void ScalarEvolution::forgetValue(Value *V) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user