forked from OSchip/llvm-project
Recommit "[SCEV] Support clearing Block/LoopDispositions for a single value."
This reverts commit92f698f01f
. The updated version of the patch includes handling for non-SCEVable types. A test case has been added inec86e9a99b
.
This commit is contained in:
parent
fe50eac85c
commit
19ad1cd5ce
|
@ -944,7 +944,7 @@ public:
|
||||||
///
|
///
|
||||||
/// We don't have a way to invalidate per-loop/per-block dispositions. Clear
|
/// We don't have a way to invalidate per-loop/per-block dispositions. Clear
|
||||||
/// and recompute is simpler.
|
/// and recompute is simpler.
|
||||||
void forgetBlockAndLoopDispositions();
|
void forgetBlockAndLoopDispositions(Value *V = nullptr);
|
||||||
|
|
||||||
/// Determine the minimum number of zero bits that S is guaranteed to end in
|
/// Determine the minimum number of zero bits that S is guaranteed to end in
|
||||||
/// (at every loop iteration). It is, at the same time, the minimum number
|
/// (at every loop iteration). It is, at the same time, the minimum number
|
||||||
|
|
|
@ -8384,9 +8384,39 @@ void ScalarEvolution::forgetValue(Value *V) {
|
||||||
|
|
||||||
void ScalarEvolution::forgetLoopDispositions() { LoopDispositions.clear(); }
|
void ScalarEvolution::forgetLoopDispositions() { LoopDispositions.clear(); }
|
||||||
|
|
||||||
void ScalarEvolution::forgetBlockAndLoopDispositions() {
|
void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
|
||||||
BlockDispositions.clear();
|
// Unless a specific value is passed to invalidation, completely clear both
|
||||||
LoopDispositions.clear();
|
// caches.
|
||||||
|
if (!V) {
|
||||||
|
BlockDispositions.clear();
|
||||||
|
LoopDispositions.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSCEVable(V->getType()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SCEV *S = getExistingSCEV(V);
|
||||||
|
if (!S)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Invalidate the block and loop dispositions cached for S. Dispositions of
|
||||||
|
// S's users may change if S's disposition changes (i.e. a user may change to
|
||||||
|
// loop-invariant, if S changes to loop invariant), so also invalidate
|
||||||
|
// dispositions of S's users recursively.
|
||||||
|
SmallVector<const SCEV *, 8> Worklist = {S};
|
||||||
|
SmallPtrSet<const SCEV *, 8> Seen = {S};
|
||||||
|
while (!Worklist.empty()) {
|
||||||
|
const SCEV *Curr = Worklist.pop_back_val();
|
||||||
|
if (!LoopDispositions.erase(Curr) && !BlockDispositions.erase(S))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto Users = SCEVUsers.find(Curr);
|
||||||
|
if (Users != SCEVUsers.end())
|
||||||
|
for (const auto *User : Users->second)
|
||||||
|
if (Seen.insert(User).second)
|
||||||
|
Worklist.push_back(User);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the exact loop backedge taken count considering all loop exits. A
|
/// Get the exact loop backedge taken count considering all loop exits. A
|
||||||
|
|
|
@ -90,22 +90,21 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (Instruction *I = dyn_cast<Instruction>(incoming)) {
|
if (Instruction *I = dyn_cast<Instruction>(incoming)) {
|
||||||
if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) {
|
bool InstrMoved = false;
|
||||||
|
if (!L->makeLoopInvariant(I, InstrMoved, Preheader->getTerminator())) {
|
||||||
AllEntriesInvariant = false;
|
AllEntriesInvariant = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Changed) {
|
Changed |= InstrMoved;
|
||||||
|
if (InstrMoved) {
|
||||||
// Moving I to a different location may change its block disposition,
|
// Moving I to a different location may change its block disposition,
|
||||||
// so invalidate its SCEV.
|
// so invalidate its SCEV.
|
||||||
SE.forgetValue(I);
|
SE.forgetBlockAndLoopDispositions(I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Changed)
|
|
||||||
SE.forgetLoopDispositions();
|
|
||||||
|
|
||||||
if (!AllEntriesInvariant || !AllOutgoingValuesSame)
|
if (!AllEntriesInvariant || !AllOutgoingValuesSame)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -312,12 +312,13 @@ static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
|
||||||
if (!canSinkOrHoistInst(I, &AA, &DT, &L, MSSAU, false, LICMFlags))
|
if (!canSinkOrHoistInst(I, &AA, &DT, &L, MSSAU, false, LICMFlags))
|
||||||
continue;
|
continue;
|
||||||
if (sinkInstruction(L, I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI,
|
if (sinkInstruction(L, I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI,
|
||||||
&MSSAU))
|
&MSSAU)) {
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
if (SE)
|
||||||
|
SE->forgetBlockAndLoopDispositions(&I);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Changed && SE)
|
|
||||||
SE->forgetLoopDispositions();
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -647,20 +647,22 @@ ReprocessLoop:
|
||||||
Instruction *Inst = &*I++;
|
Instruction *Inst = &*I++;
|
||||||
if (Inst == CI)
|
if (Inst == CI)
|
||||||
continue;
|
continue;
|
||||||
|
bool InstInvariant = false;
|
||||||
if (!L->makeLoopInvariant(
|
if (!L->makeLoopInvariant(
|
||||||
Inst, AnyInvariant,
|
Inst, InstInvariant,
|
||||||
Preheader ? Preheader->getTerminator() : nullptr, MSSAU)) {
|
Preheader ? Preheader->getTerminator() : nullptr, MSSAU)) {
|
||||||
AllInvariant = false;
|
AllInvariant = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (InstInvariant && SE) {
|
||||||
|
// The loop disposition of all SCEV expressions that depend on any
|
||||||
|
// hoisted values have also changed.
|
||||||
|
SE->forgetBlockAndLoopDispositions(Inst);
|
||||||
|
}
|
||||||
|
AnyInvariant |= InstInvariant;
|
||||||
}
|
}
|
||||||
if (AnyInvariant) {
|
if (AnyInvariant)
|
||||||
Changed = true;
|
Changed = true;
|
||||||
// The loop disposition of all SCEV expressions that depend on any
|
|
||||||
// hoisted values have also changed.
|
|
||||||
if (SE)
|
|
||||||
SE->forgetLoopDispositions();
|
|
||||||
}
|
|
||||||
if (!AllInvariant) continue;
|
if (!AllInvariant) continue;
|
||||||
|
|
||||||
// The block has now been cleared of all instructions except for
|
// The block has now been cleared of all instructions except for
|
||||||
|
|
Loading…
Reference in New Issue