COWArrayOpt: Fix the array property specializer to recompute the loop tree after cloning

Cloning the loop is going to invalidate the loop tree. Be conservative and
recompute it.

No test case. I did not run into an error but also don't want to in the future.

Swift SVN r25733
This commit is contained in:
Arnold Schwaighofer
2015-03-04 01:06:27 +00:00
parent 5113456d40
commit 411ba4e830

View File

@@ -1245,7 +1245,6 @@ namespace {
/// However, the client needs to update the dominator of the exit blocks. /// However, the client needs to update the dominator of the exit blocks.
class RegionCloner : public SILCloner<RegionCloner> { class RegionCloner : public SILCloner<RegionCloner> {
DominanceInfo &DomTree; DominanceInfo &DomTree;
SILLoopInfo *LoopInfo;
SILBasicBlock *StartBB; SILBasicBlock *StartBB;
SmallPtrSet<SILBasicBlock *, 16> OutsideBBs; SmallPtrSet<SILBasicBlock *, 16> OutsideBBs;
@@ -1254,11 +1253,9 @@ class RegionCloner : public SILCloner<RegionCloner> {
public: public:
RegionCloner(SILBasicBlock *EntryBB, RegionCloner(SILBasicBlock *EntryBB,
SmallVectorImpl<SILBasicBlock *> &ExitBlocks, DominanceInfo &DT, SmallVectorImpl<SILBasicBlock *> &ExitBlocks, DominanceInfo &DT)
SILLoopInfo *LI)
: SILCloner<RegionCloner>(*EntryBB->getParent()), DomTree(DT), : SILCloner<RegionCloner>(*EntryBB->getParent()), DomTree(DT),
LoopInfo(LI), StartBB(EntryBB), StartBB(EntryBB), OutsideBBs(ExitBlocks.begin(), ExitBlocks.end()) {}
OutsideBBs(ExitBlocks.begin(), ExitBlocks.end()) {}
SILBasicBlock *cloneRegion() { SILBasicBlock *cloneRegion() {
assert (DomTree.getNode(StartBB) != nullptr && "Can't cloned dead code"); assert (DomTree.getNode(StartBB) != nullptr && "Can't cloned dead code");
@@ -1409,17 +1406,23 @@ namespace {
/// loop based on array.props calls. /// loop based on array.props calls.
class ArrayPropertiesSpecializer { class ArrayPropertiesSpecializer {
DominanceInfo *DomTree; DominanceInfo *DomTree;
SILLoopInfo *LoopInfo; SILLoopAnalysis *LoopAnalysis;
SILBasicBlock *HoistableLoopPreheader; SILBasicBlock *HoistableLoopPreheader;
public: public:
ArrayPropertiesSpecializer(DominanceInfo *DT, SILLoopInfo *LI, ArrayPropertiesSpecializer(DominanceInfo *DT, SILLoopAnalysis *LA,
SILBasicBlock *Hoistable) SILBasicBlock *Hoistable)
: DomTree(DT), LoopInfo(LI), HoistableLoopPreheader(Hoistable) {} : DomTree(DT), LoopAnalysis(LA), HoistableLoopPreheader(Hoistable) {}
void run() { void run() {
specializeLoopNest(); specializeLoopNest();
} }
SILLoop *getLoop() {
auto *LoopInfo =
LoopAnalysis->getLoopInfo(HoistableLoopPreheader->getParent());
return LoopInfo->getLoopFor(HoistableLoopPreheader->getSingleSuccessor());
}
protected: protected:
void specializeLoopNest(); void specializeLoopNest();
}; };
@@ -1531,6 +1534,9 @@ static void replaceArrayPropsCall(SILBuilder &B, ArraySemanticsCall C) {
} }
void ArrayPropertiesSpecializer::specializeLoopNest() { void ArrayPropertiesSpecializer::specializeLoopNest() {
auto *Lp = getLoop();
assert(Lp);
// Split of a new empty preheader. We don't want to duplicate the whole // Split of a new empty preheader. We don't want to duplicate the whole
// original preheader it might contain instructions that we can't clone. // original preheader it might contain instructions that we can't clone.
// This will be block that will contain the check whether to execute the // This will be block that will contain the check whether to execute the
@@ -1541,8 +1547,6 @@ void ArrayPropertiesSpecializer::specializeLoopNest() {
// Get the exit blocks of the orignal loop. // Get the exit blocks of the orignal loop.
auto *Header = CheckBlock->getSingleSuccessor(); auto *Header = CheckBlock->getSingleSuccessor();
assert(Header); assert(Header);
auto *Lp = LoopInfo->getLoopFor(Header);
assert(Lp);
// Our loop info is not really completedly valid anymore since the cloner does // Our loop info is not really completedly valid anymore since the cloner does
// not update it. However, exit blocks of the original loop are still valid. // not update it. However, exit blocks of the original loop are still valid.
@@ -1555,7 +1559,7 @@ void ArrayPropertiesSpecializer::specializeLoopNest() {
// Clone the region from the new preheader up to (not including) the exit // Clone the region from the new preheader up to (not including) the exit
// blocks. This creates a second loop nest. // blocks. This creates a second loop nest.
RegionCloner Cloner(NewPreheader, ExitBlocks, *DomTree, LoopInfo); RegionCloner Cloner(NewPreheader, ExitBlocks, *DomTree);
auto *ClonedPreheader = Cloner.cloneRegion(); auto *ClonedPreheader = Cloner.cloneRegion();
// Collect the array.props call that we will specialize on that we have // Collect the array.props call that we will specialize on that we have
@@ -1587,6 +1591,10 @@ void ArrayPropertiesSpecializer::specializeLoopNest() {
SILBuilder B2(ClonedPreheader->getTerminator()); SILBuilder B2(ClonedPreheader->getTerminator());
for (auto C : ArrayPropCalls) for (auto C : ArrayPropCalls)
replaceArrayPropsCall(B2, C); replaceArrayPropsCall(B2, C);
// We have potentially cloned a loop - invalidate loop info.
LoopAnalysis->invalidate(Header->getParent(),
SILAnalysis::InvalidationKind::CFG);
} }
namespace { namespace {
@@ -1630,7 +1638,7 @@ class SwiftArrayOptPass : public SILFunctionTransform {
// Process specialized loop-nests in loop-tree post-order (bottom-up). // Process specialized loop-nests in loop-tree post-order (bottom-up).
std::reverse(HoistableLoopNests.begin(), HoistableLoopNests.end()); std::reverse(HoistableLoopNests.begin(), HoistableLoopNests.end());
for (auto &HoistableLoopNest : HoistableLoopNests) for (auto &HoistableLoopNest : HoistableLoopNests)
ArrayPropertiesSpecializer(DT, LI, HoistableLoopNest).run(); ArrayPropertiesSpecializer(DT, LA, HoistableLoopNest).run();
DEBUG(getFunction()->viewCFG()); DEBUG(getFunction()->viewCFG());
} }