forked from OSchip/llvm-project
[SLP] Optimize stacksave dependence handling [NFC]
After writing the commit message for 4b1bace28, realized that the mentioned optimization was rather straight forward. We already have the code for scanning a block during region initialization, we can simply keep track if we've seen a stacksave or stackrestore. If we haven't, none of these dependencies are relevant and we can avoid the relatively expensive scans entirely.
This commit is contained in:
parent
a16308c282
commit
ec858f0201
|
@ -2764,6 +2764,7 @@ private:
|
||||||
ScheduleEnd = nullptr;
|
ScheduleEnd = nullptr;
|
||||||
FirstLoadStoreInRegion = nullptr;
|
FirstLoadStoreInRegion = nullptr;
|
||||||
LastLoadStoreInRegion = nullptr;
|
LastLoadStoreInRegion = nullptr;
|
||||||
|
RegionHasStackSave = false;
|
||||||
|
|
||||||
// Reduce the maximum schedule region size by the size of the
|
// Reduce the maximum schedule region size by the size of the
|
||||||
// previous scheduling run.
|
// previous scheduling run.
|
||||||
|
@ -3032,6 +3033,11 @@ private:
|
||||||
/// (can be null).
|
/// (can be null).
|
||||||
ScheduleData *LastLoadStoreInRegion = nullptr;
|
ScheduleData *LastLoadStoreInRegion = nullptr;
|
||||||
|
|
||||||
|
/// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
|
||||||
|
/// region? Used to optimize the dependence calculation for the
|
||||||
|
/// common case where there isn't.
|
||||||
|
bool RegionHasStackSave = false;
|
||||||
|
|
||||||
/// The current size of the scheduling region.
|
/// The current size of the scheduling region.
|
||||||
int ScheduleRegionSize = 0;
|
int ScheduleRegionSize = 0;
|
||||||
|
|
||||||
|
@ -8016,6 +8022,10 @@ void BoUpSLP::BlockScheduling::initScheduleData(Instruction *FromI,
|
||||||
}
|
}
|
||||||
CurrentLoadStore = SD;
|
CurrentLoadStore = SD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
|
||||||
|
match(I, m_Intrinsic<Intrinsic::stackrestore>()))
|
||||||
|
RegionHasStackSave = true;
|
||||||
}
|
}
|
||||||
if (NextLoadStore) {
|
if (NextLoadStore) {
|
||||||
if (CurrentLoadStore)
|
if (CurrentLoadStore)
|
||||||
|
@ -8099,40 +8109,42 @@ void BoUpSLP::BlockScheduling::calculateDependencies(ScheduleData *SD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have an inalloc alloca instruction, it needs to be scheduled
|
if (RegionHasStackSave) {
|
||||||
// after any preceeding stacksave. We also need to prevent any alloca
|
// If we have an inalloc alloca instruction, it needs to be scheduled
|
||||||
// from reordering above a preceeding stackrestore.
|
// after any preceeding stacksave. We also need to prevent any alloca
|
||||||
if (match(BundleMember->Inst, m_Intrinsic<Intrinsic::stacksave>()) ||
|
// from reordering above a preceeding stackrestore.
|
||||||
match(BundleMember->Inst, m_Intrinsic<Intrinsic::stackrestore>())) {
|
if (match(BundleMember->Inst, m_Intrinsic<Intrinsic::stacksave>()) ||
|
||||||
for (Instruction *I = BundleMember->Inst->getNextNode();
|
match(BundleMember->Inst, m_Intrinsic<Intrinsic::stackrestore>())) {
|
||||||
I != ScheduleEnd; I = I->getNextNode()) {
|
for (Instruction *I = BundleMember->Inst->getNextNode();
|
||||||
if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
|
I != ScheduleEnd; I = I->getNextNode()) {
|
||||||
match(I, m_Intrinsic<Intrinsic::stackrestore>()))
|
if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
|
||||||
// Any allocas past here must be control dependent on I, and I
|
match(I, m_Intrinsic<Intrinsic::stackrestore>()))
|
||||||
// must be memory dependend on BundleMember->Inst.
|
// Any allocas past here must be control dependent on I, and I
|
||||||
break;
|
// must be memory dependend on BundleMember->Inst.
|
||||||
|
break;
|
||||||
|
|
||||||
if (!isa<AllocaInst>(I))
|
if (!isa<AllocaInst>(I))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Add the dependency
|
// Add the dependency
|
||||||
makeControlDependent(I);
|
makeControlDependent(I);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// In addition to the cases handle just above, we need to prevent
|
// In addition to the cases handle just above, we need to prevent
|
||||||
// allocas from moving below a stacksave. The stackrestore case
|
// allocas from moving below a stacksave. The stackrestore case
|
||||||
// is currently thought to be conservatism.
|
// is currently thought to be conservatism.
|
||||||
if (isa<AllocaInst>(BundleMember->Inst)) {
|
if (isa<AllocaInst>(BundleMember->Inst)) {
|
||||||
for (Instruction *I = BundleMember->Inst->getNextNode();
|
for (Instruction *I = BundleMember->Inst->getNextNode();
|
||||||
I != ScheduleEnd; I = I->getNextNode()) {
|
I != ScheduleEnd; I = I->getNextNode()) {
|
||||||
if (!match(I, m_Intrinsic<Intrinsic::stacksave>()) &&
|
if (!match(I, m_Intrinsic<Intrinsic::stacksave>()) &&
|
||||||
!match(I, m_Intrinsic<Intrinsic::stackrestore>()))
|
!match(I, m_Intrinsic<Intrinsic::stackrestore>()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Add the dependency
|
// Add the dependency
|
||||||
makeControlDependent(I);
|
makeControlDependent(I);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue