forked from OSchip/llvm-project
Reapply r135074 and r135080 with a fix.
The cache entry referenced by the best split candidate could become clobbered by an unsuccessful candidate. The correct fix here is to use reference counts on the cache entries. Coming up. llvm-svn: 135113
This commit is contained in:
parent
56a20a492b
commit
d7e9937175
|
@ -127,10 +127,14 @@ public:
|
||||||
Entry *CacheEntry;
|
Entry *CacheEntry;
|
||||||
BlockInterference *Current;
|
BlockInterference *Current;
|
||||||
public:
|
public:
|
||||||
/// Cursor - Create a cursor for the interference allocated to PhysReg and
|
/// Cursor - Create a dangling cursor.
|
||||||
/// all its aliases.
|
Cursor() : CacheEntry(0), Current(0) {}
|
||||||
Cursor(InterferenceCache &Cache, unsigned PhysReg)
|
|
||||||
: CacheEntry(Cache.get(PhysReg)), Current(0) {}
|
/// setPhysReg - Point this cursor to PhysReg's interference.
|
||||||
|
void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) {
|
||||||
|
CacheEntry = Cache.get(PhysReg);
|
||||||
|
Current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// moveTo - Move cursor to basic block MBBNum.
|
/// moveTo - Move cursor to basic block MBBNum.
|
||||||
void moveToBlock(unsigned MBBNum) {
|
void moveToBlock(unsigned MBBNum) {
|
||||||
|
|
|
@ -160,11 +160,13 @@ class RAGreedy : public MachineFunctionPass,
|
||||||
/// Global live range splitting candidate info.
|
/// Global live range splitting candidate info.
|
||||||
struct GlobalSplitCandidate {
|
struct GlobalSplitCandidate {
|
||||||
unsigned PhysReg;
|
unsigned PhysReg;
|
||||||
|
InterferenceCache::Cursor Intf;
|
||||||
BitVector LiveBundles;
|
BitVector LiveBundles;
|
||||||
SmallVector<unsigned, 8> ActiveBlocks;
|
SmallVector<unsigned, 8> ActiveBlocks;
|
||||||
|
|
||||||
void reset(unsigned Reg) {
|
void reset(InterferenceCache &Cache, unsigned Reg) {
|
||||||
PhysReg = Reg;
|
PhysReg = Reg;
|
||||||
|
Intf.setPhysReg(Cache, Reg);
|
||||||
LiveBundles.clear();
|
LiveBundles.clear();
|
||||||
ActiveBlocks.clear();
|
ActiveBlocks.clear();
|
||||||
}
|
}
|
||||||
|
@ -206,8 +208,8 @@ private:
|
||||||
float calcSpillCost();
|
float calcSpillCost();
|
||||||
bool addSplitConstraints(InterferenceCache::Cursor, float&);
|
bool addSplitConstraints(InterferenceCache::Cursor, float&);
|
||||||
void addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
|
void addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
|
||||||
void growRegion(GlobalSplitCandidate &Cand, InterferenceCache::Cursor);
|
void growRegion(GlobalSplitCandidate &Cand);
|
||||||
float calcGlobalSplitCost(GlobalSplitCandidate&, InterferenceCache::Cursor);
|
float calcGlobalSplitCost(GlobalSplitCandidate&);
|
||||||
void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&,
|
void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&,
|
||||||
SmallVectorImpl<LiveInterval*>&);
|
SmallVectorImpl<LiveInterval*>&);
|
||||||
void calcGapWeights(unsigned, SmallVectorImpl<float>&);
|
void calcGapWeights(unsigned, SmallVectorImpl<float>&);
|
||||||
|
@ -720,8 +722,7 @@ void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf,
|
||||||
SpillPlacer->addLinks(ArrayRef<unsigned>(TBS, T));
|
SpillPlacer->addLinks(ArrayRef<unsigned>(TBS, T));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RAGreedy::growRegion(GlobalSplitCandidate &Cand,
|
void RAGreedy::growRegion(GlobalSplitCandidate &Cand) {
|
||||||
InterferenceCache::Cursor Intf) {
|
|
||||||
// Keep track of through blocks that have not been added to SpillPlacer.
|
// Keep track of through blocks that have not been added to SpillPlacer.
|
||||||
BitVector Todo = SA->getThroughBlocks();
|
BitVector Todo = SA->getThroughBlocks();
|
||||||
SmallVectorImpl<unsigned> &ActiveBlocks = Cand.ActiveBlocks;
|
SmallVectorImpl<unsigned> &ActiveBlocks = Cand.ActiveBlocks;
|
||||||
|
@ -753,7 +754,7 @@ void RAGreedy::growRegion(GlobalSplitCandidate &Cand,
|
||||||
// Any new blocks to add?
|
// Any new blocks to add?
|
||||||
if (ActiveBlocks.size() == AddedTo)
|
if (ActiveBlocks.size() == AddedTo)
|
||||||
break;
|
break;
|
||||||
addThroughConstraints(Intf,
|
addThroughConstraints(Cand.Intf,
|
||||||
ArrayRef<unsigned>(ActiveBlocks).slice(AddedTo));
|
ArrayRef<unsigned>(ActiveBlocks).slice(AddedTo));
|
||||||
AddedTo = ActiveBlocks.size();
|
AddedTo = ActiveBlocks.size();
|
||||||
|
|
||||||
|
@ -794,8 +795,7 @@ float RAGreedy::calcSpillCost() {
|
||||||
/// pattern in LiveBundles. This cost should be added to the local cost of the
|
/// pattern in LiveBundles. This cost should be added to the local cost of the
|
||||||
/// interference pattern in SplitConstraints.
|
/// interference pattern in SplitConstraints.
|
||||||
///
|
///
|
||||||
float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand,
|
float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand) {
|
||||||
InterferenceCache::Cursor Intf) {
|
|
||||||
float GlobalCost = 0;
|
float GlobalCost = 0;
|
||||||
const BitVector &LiveBundles = Cand.LiveBundles;
|
const BitVector &LiveBundles = Cand.LiveBundles;
|
||||||
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
|
||||||
|
@ -822,8 +822,8 @@ float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand,
|
||||||
continue;
|
continue;
|
||||||
if (RegIn && RegOut) {
|
if (RegIn && RegOut) {
|
||||||
// We need double spill code if this block has interference.
|
// We need double spill code if this block has interference.
|
||||||
Intf.moveToBlock(Number);
|
Cand.Intf.moveToBlock(Number);
|
||||||
if (Intf.hasInterference())
|
if (Cand.Intf.hasInterference())
|
||||||
GlobalCost += 2*SpillPlacer->getBlockFrequency(Number);
|
GlobalCost += 2*SpillPlacer->getBlockFrequency(Number);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -853,7 +853,12 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
|
||||||
dbgs() << ".\n";
|
dbgs() << ".\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
InterferenceCache::Cursor Intf(IntfCache, Cand.PhysReg);
|
InterferenceCache::Cursor &Intf = Cand.Intf;
|
||||||
|
|
||||||
|
// FIXME: We need cache reference counts to guarantee that Intf hasn't been
|
||||||
|
// clobbered.
|
||||||
|
Intf.setPhysReg(IntfCache, Cand.PhysReg);
|
||||||
|
|
||||||
LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
|
LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
|
||||||
SE->reset(LREdit);
|
SE->reset(LREdit);
|
||||||
|
|
||||||
|
@ -1243,17 +1248,18 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
||||||
DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n');
|
DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n');
|
||||||
const unsigned NoCand = ~0u;
|
const unsigned NoCand = ~0u;
|
||||||
unsigned BestCand = NoCand;
|
unsigned BestCand = NoCand;
|
||||||
|
unsigned NumCands = 0;
|
||||||
|
|
||||||
Order.rewind();
|
Order.rewind();
|
||||||
for (unsigned Cand = 0; unsigned PhysReg = Order.next(); ++Cand) {
|
while (unsigned PhysReg = Order.next()) {
|
||||||
if (GlobalCand.size() <= Cand)
|
if (GlobalCand.size() <= NumCands)
|
||||||
GlobalCand.resize(Cand+1);
|
GlobalCand.resize(NumCands+1);
|
||||||
GlobalCand[Cand].reset(PhysReg);
|
GlobalSplitCandidate &Cand = GlobalCand[NumCands];
|
||||||
|
Cand.reset(IntfCache, PhysReg);
|
||||||
|
|
||||||
SpillPlacer->prepare(GlobalCand[Cand].LiveBundles);
|
SpillPlacer->prepare(Cand.LiveBundles);
|
||||||
float Cost;
|
float Cost;
|
||||||
InterferenceCache::Cursor Intf(IntfCache, PhysReg);
|
if (!addSplitConstraints(Cand.Intf, Cost)) {
|
||||||
if (!addSplitConstraints(Intf, Cost)) {
|
|
||||||
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tno positive bundles\n");
|
DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tno positive bundles\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1268,28 +1274,29 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
growRegion(GlobalCand[Cand], Intf);
|
growRegion(Cand);
|
||||||
|
|
||||||
SpillPlacer->finish();
|
SpillPlacer->finish();
|
||||||
|
|
||||||
// No live bundles, defer to splitSingleBlocks().
|
// No live bundles, defer to splitSingleBlocks().
|
||||||
if (!GlobalCand[Cand].LiveBundles.any()) {
|
if (!Cand.LiveBundles.any()) {
|
||||||
DEBUG(dbgs() << " no bundles.\n");
|
DEBUG(dbgs() << " no bundles.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cost += calcGlobalSplitCost(GlobalCand[Cand], Intf);
|
Cost += calcGlobalSplitCost(Cand);
|
||||||
DEBUG({
|
DEBUG({
|
||||||
dbgs() << ", total = " << Cost << " with bundles";
|
dbgs() << ", total = " << Cost << " with bundles";
|
||||||
for (int i = GlobalCand[Cand].LiveBundles.find_first(); i>=0;
|
for (int i = Cand.LiveBundles.find_first(); i>=0;
|
||||||
i = GlobalCand[Cand].LiveBundles.find_next(i))
|
i = Cand.LiveBundles.find_next(i))
|
||||||
dbgs() << " EB#" << i;
|
dbgs() << " EB#" << i;
|
||||||
dbgs() << ".\n";
|
dbgs() << ".\n";
|
||||||
});
|
});
|
||||||
if (Cost < BestCost) {
|
if (Cost < BestCost) {
|
||||||
BestCand = Cand;
|
BestCand = NumCands;
|
||||||
BestCost = Hysteresis * Cost; // Prevent rounding effects.
|
BestCost = Hysteresis * Cost; // Prevent rounding effects.
|
||||||
}
|
}
|
||||||
|
++NumCands;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BestCand == NoCand)
|
if (BestCand == NoCand)
|
||||||
|
|
Loading…
Reference in New Issue