mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 00:21:03 +00:00
Check TRI->getReservedRegs because other allocators do it. Even though
it makes no sense for allocation_order iterators to visit reserved regs. The inline spiller depends on AliasAnalysis. Manage the Query state to avoid uninitialized or stale results. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118800 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -267,6 +267,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Query(const Query&); // DO NOT IMPLEMENT
|
||||||
|
void operator=(const Query&); // DO NOT IMPLEMENT
|
||||||
|
|
||||||
// Private interface for queries
|
// Private interface for queries
|
||||||
void findIntersection(InterferenceResult &ir) const;
|
void findIntersection(InterferenceResult &ir) const;
|
||||||
};
|
};
|
||||||
|
@@ -106,6 +106,15 @@ protected:
|
|||||||
// A RegAlloc pass should call this before allocatePhysRegs.
|
// A RegAlloc pass should call this before allocatePhysRegs.
|
||||||
void init(const TargetRegisterInfo &tri, VirtRegMap &vrm, LiveIntervals &lis);
|
void init(const TargetRegisterInfo &tri, VirtRegMap &vrm, LiveIntervals &lis);
|
||||||
|
|
||||||
|
// Get an initialized query to check interferences between lvr and preg. Note
|
||||||
|
// that Query::init must be called at least once for each physical register
|
||||||
|
// before querying a new live virtual register. This ties queries_ and
|
||||||
|
// physReg2liu_ together.
|
||||||
|
LiveIntervalUnion::Query &query(LiveInterval &lvr, unsigned preg) {
|
||||||
|
queries_[preg].init(&lvr, &physReg2liu_[preg]);
|
||||||
|
return queries_[preg];
|
||||||
|
}
|
||||||
|
|
||||||
// The top-level driver. The output is a VirtRegMap that us updated with
|
// The top-level driver. The output is a VirtRegMap that us updated with
|
||||||
// physical register assignments.
|
// physical register assignments.
|
||||||
//
|
//
|
||||||
@@ -135,7 +144,7 @@ protected:
|
|||||||
// Helper for spilling all live virtual registers currently unified under preg
|
// Helper for spilling all live virtual registers currently unified under preg
|
||||||
// that interfere with the most recently queried lvr. Return true if spilling
|
// that interfere with the most recently queried lvr. Return true if spilling
|
||||||
// was successful, and append any new spilled/split intervals to splitLVRs.
|
// was successful, and append any new spilled/split intervals to splitLVRs.
|
||||||
bool spillInterferences(unsigned preg,
|
bool spillInterferences(LiveInterval &lvr, unsigned preg,
|
||||||
SmallVectorImpl<LiveInterval*> &splitLVRs);
|
SmallVectorImpl<LiveInterval*> &splitLVRs);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@@ -146,7 +155,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void seedLiveVirtRegs(LiveVirtRegQueue &lvrQ);
|
void seedLiveVirtRegs(LiveVirtRegQueue &lvrQ);
|
||||||
|
|
||||||
void spillReg(unsigned reg, SmallVectorImpl<LiveInterval*> &splitLVRs);
|
void spillReg(LiveInterval &lvr, unsigned reg,
|
||||||
|
SmallVectorImpl<LiveInterval*> &splitLVRs);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "Spiller.h"
|
#include "Spiller.h"
|
||||||
#include "VirtRegMap.h"
|
#include "VirtRegMap.h"
|
||||||
#include "VirtRegRewriter.h"
|
#include "VirtRegRewriter.h"
|
||||||
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/PassAnalysisSupport.h"
|
#include "llvm/PassAnalysisSupport.h"
|
||||||
#include "llvm/CodeGen/CalcSpillWeights.h"
|
#include "llvm/CodeGen/CalcSpillWeights.h"
|
||||||
@@ -75,6 +76,7 @@ class RABasic : public MachineFunctionPass, public RegAllocBase
|
|||||||
MachineFunction *mf_;
|
MachineFunction *mf_;
|
||||||
const TargetMachine *tm_;
|
const TargetMachine *tm_;
|
||||||
MachineRegisterInfo *mri_;
|
MachineRegisterInfo *mri_;
|
||||||
|
BitVector reservedRegs_;
|
||||||
|
|
||||||
// analyses
|
// analyses
|
||||||
LiveStacks *ls_;
|
LiveStacks *ls_;
|
||||||
@@ -145,6 +147,8 @@ RABasic::RABasic(): MachineFunctionPass(ID) {
|
|||||||
|
|
||||||
void RABasic::getAnalysisUsage(AnalysisUsage &au) const {
|
void RABasic::getAnalysisUsage(AnalysisUsage &au) const {
|
||||||
au.setPreservesCFG();
|
au.setPreservesCFG();
|
||||||
|
au.addRequired<AliasAnalysis>();
|
||||||
|
au.addPreserved<AliasAnalysis>();
|
||||||
au.addRequired<LiveIntervals>();
|
au.addRequired<LiveIntervals>();
|
||||||
au.addPreserved<SlotIndexes>();
|
au.addPreserved<SlotIndexes>();
|
||||||
if (StrongPHIElim)
|
if (StrongPHIElim)
|
||||||
@@ -187,8 +191,6 @@ void RegAllocBase::verify() {
|
|||||||
for (LiveIntervals::iterator liItr = lis_->begin(), liEnd = lis_->end();
|
for (LiveIntervals::iterator liItr = lis_->begin(), liEnd = lis_->end();
|
||||||
liItr != liEnd; ++liItr) {
|
liItr != liEnd; ++liItr) {
|
||||||
unsigned reg = liItr->first;
|
unsigned reg = liItr->first;
|
||||||
LiveInterval &li = *liItr->second;
|
|
||||||
if (li.empty() ) continue;
|
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(reg)) continue;
|
if (TargetRegisterInfo::isPhysicalRegister(reg)) continue;
|
||||||
if (!vrm_->hasPhys(reg)) continue; // spilled?
|
if (!vrm_->hasPhys(reg)) continue; // spilled?
|
||||||
unsigned preg = vrm_->getPhys(reg);
|
unsigned preg = vrm_->getPhys(reg);
|
||||||
@@ -271,7 +273,6 @@ void RegAllocBase::seedLiveVirtRegs(LiveVirtRegQueue &lvrQ) {
|
|||||||
liItr != liEnd; ++liItr) {
|
liItr != liEnd; ++liItr) {
|
||||||
unsigned reg = liItr->first;
|
unsigned reg = liItr->first;
|
||||||
LiveInterval &li = *liItr->second;
|
LiveInterval &li = *liItr->second;
|
||||||
if (li.empty()) continue;
|
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(reg)) {
|
if (TargetRegisterInfo::isPhysicalRegister(reg)) {
|
||||||
physReg2liu_[reg].unify(li);
|
physReg2liu_[reg].unify(li);
|
||||||
}
|
}
|
||||||
@@ -314,12 +315,10 @@ void RegAllocBase::allocatePhysRegs() {
|
|||||||
// register. Return the interfering register.
|
// register. Return the interfering register.
|
||||||
unsigned RegAllocBase::checkPhysRegInterference(LiveInterval &lvr,
|
unsigned RegAllocBase::checkPhysRegInterference(LiveInterval &lvr,
|
||||||
unsigned preg) {
|
unsigned preg) {
|
||||||
queries_[preg].init(&lvr, &physReg2liu_[preg]);
|
if (query(lvr, preg).checkInterference())
|
||||||
if (queries_[preg].checkInterference())
|
|
||||||
return preg;
|
return preg;
|
||||||
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI) {
|
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI) {
|
||||||
queries_[*asI].init(&lvr, &physReg2liu_[*asI]);
|
if (query(lvr, *asI).checkInterference())
|
||||||
if (queries_[*asI].checkInterference())
|
|
||||||
return *asI;
|
return *asI;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -334,60 +333,63 @@ struct LessLiveVirtualReg
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Spill all interferences currently assigned to this physical register.
|
// Spill all interferences currently assigned to this physical register.
|
||||||
void RegAllocBase::spillReg(unsigned reg,
|
void RegAllocBase::spillReg(LiveInterval& lvr, unsigned reg,
|
||||||
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
||||||
LiveIntervalUnion::Query &query = queries_[reg];
|
LiveIntervalUnion::Query &Q = query(lvr, reg);
|
||||||
const SmallVectorImpl<LiveInterval*> &pendingSpills =
|
const SmallVectorImpl<LiveInterval*> &pendingSpills = Q.interferingVRegs();
|
||||||
query.interferingVRegs();
|
|
||||||
for (SmallVectorImpl<LiveInterval*>::const_iterator I = pendingSpills.begin(),
|
for (SmallVectorImpl<LiveInterval*>::const_iterator I = pendingSpills.begin(),
|
||||||
E = pendingSpills.end(); I != E; ++I) {
|
E = pendingSpills.end(); I != E; ++I) {
|
||||||
LiveInterval &lvr = **I;
|
LiveInterval &spilledLVR = **I;
|
||||||
DEBUG(dbgs() <<
|
DEBUG(dbgs() << "extracting from " <<
|
||||||
"extracting from " << tri_->getName(reg) << " " << lvr << '\n');
|
tri_->getName(reg) << " " << spilledLVR << '\n');
|
||||||
|
|
||||||
// Deallocate the interfering vreg by removing it from the union.
|
// Deallocate the interfering vreg by removing it from the union.
|
||||||
// A LiveInterval instance may not be in a union during modification!
|
// A LiveInterval instance may not be in a union during modification!
|
||||||
physReg2liu_[reg].extract(lvr);
|
physReg2liu_[reg].extract(spilledLVR);
|
||||||
|
|
||||||
// After extracting segments, the query's results are invalid.
|
|
||||||
query.clear();
|
|
||||||
|
|
||||||
// Clear the vreg assignment.
|
// Clear the vreg assignment.
|
||||||
vrm_->clearVirt(lvr.reg);
|
vrm_->clearVirt(spilledLVR.reg);
|
||||||
|
|
||||||
// Spill the extracted interval.
|
// Spill the extracted interval.
|
||||||
spiller().spill(&lvr, splitLVRs, pendingSpills);
|
spiller().spill(&spilledLVR, splitLVRs, pendingSpills);
|
||||||
}
|
}
|
||||||
|
// After extracting segments, the query's results are invalid. But keep the
|
||||||
|
// contents valid until we're done accessing pendingSpills.
|
||||||
|
Q.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spill or split all live virtual registers currently unified under preg that
|
// Spill or split all live virtual registers currently unified under preg that
|
||||||
// interfere with lvr. The newly spilled or split live intervals are returned by
|
// interfere with lvr. The newly spilled or split live intervals are returned by
|
||||||
// appending them to splitLVRs.
|
// appending them to splitLVRs.
|
||||||
bool
|
bool
|
||||||
RegAllocBase::spillInterferences(unsigned preg,
|
RegAllocBase::spillInterferences(LiveInterval &lvr, unsigned preg,
|
||||||
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
||||||
// Record each interference and determine if all are spillable before mutating
|
// Record each interference and determine if all are spillable before mutating
|
||||||
// either the union or live intervals.
|
// either the union or live intervals.
|
||||||
std::vector<LiveInterval*> spilledLVRs;
|
|
||||||
|
|
||||||
unsigned numInterferences = queries_[preg].collectInterferingVRegs();
|
// Collect interferences assigned to the requested physical register.
|
||||||
if (queries_[preg].seenUnspillableVReg()) {
|
LiveIntervalUnion::Query &QPreg = query(lvr, preg);
|
||||||
|
unsigned numInterferences = QPreg.collectInterferingVRegs();
|
||||||
|
if (QPreg.seenUnspillableVReg()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Collect interferences assigned to any alias of the physical register.
|
||||||
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI) {
|
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI) {
|
||||||
numInterferences += queries_[*asI].collectInterferingVRegs();
|
LiveIntervalUnion::Query &QAlias = query(lvr, *asI);
|
||||||
if (queries_[*asI].seenUnspillableVReg()) {
|
numInterferences += QAlias.collectInterferingVRegs();
|
||||||
|
if (QAlias.seenUnspillableVReg()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG(dbgs() << "spilling " << tri_->getName(preg) <<
|
DEBUG(dbgs() << "spilling " << tri_->getName(preg) <<
|
||||||
" interferences with " << queries_[preg].lvr() << "\n");
|
" interferences with " << lvr << "\n");
|
||||||
assert(numInterferences > 0 && "expect interference");
|
assert(numInterferences > 0 && "expect interference");
|
||||||
|
|
||||||
// Spill each interfering vreg allocated to preg or an alias.
|
// Spill each interfering vreg allocated to preg or an alias.
|
||||||
spillReg(preg, splitLVRs);
|
spillReg(lvr, preg, splitLVRs);
|
||||||
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI)
|
for (const unsigned *asI = tri_->getAliasSet(preg); *asI; ++asI)
|
||||||
spillReg(*asI, splitLVRs);
|
spillReg(lvr, *asI, splitLVRs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +411,7 @@ RegAllocBase::spillInterferences(unsigned preg,
|
|||||||
unsigned RABasic::selectOrSplit(LiveInterval &lvr,
|
unsigned RABasic::selectOrSplit(LiveInterval &lvr,
|
||||||
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
SmallVectorImpl<LiveInterval*> &splitLVRs) {
|
||||||
// Populate a list of physical register spill candidates.
|
// Populate a list of physical register spill candidates.
|
||||||
std::vector<unsigned> pregSpillCands;
|
SmallVector<unsigned, 8> pregSpillCands;
|
||||||
|
|
||||||
// Check for an available register in this class.
|
// Check for an available register in this class.
|
||||||
const TargetRegisterClass *trc = mri_->getRegClass(lvr.reg);
|
const TargetRegisterClass *trc = mri_->getRegClass(lvr.reg);
|
||||||
@@ -417,6 +419,8 @@ unsigned RABasic::selectOrSplit(LiveInterval &lvr,
|
|||||||
trcEnd = trc->allocation_order_end(*mf_);
|
trcEnd = trc->allocation_order_end(*mf_);
|
||||||
trcI != trcEnd; ++trcI) {
|
trcI != trcEnd; ++trcI) {
|
||||||
unsigned preg = *trcI;
|
unsigned preg = *trcI;
|
||||||
|
if (reservedRegs_.test(preg)) continue;
|
||||||
|
|
||||||
// Check interference and intialize queries for this lvr as a side effect.
|
// Check interference and intialize queries for this lvr as a side effect.
|
||||||
unsigned interfReg = checkPhysRegInterference(lvr, preg);
|
unsigned interfReg = checkPhysRegInterference(lvr, preg);
|
||||||
if (interfReg == 0) {
|
if (interfReg == 0) {
|
||||||
@@ -435,17 +439,17 @@ unsigned RABasic::selectOrSplit(LiveInterval &lvr,
|
|||||||
// Try to spill another interfering reg with less spill weight.
|
// Try to spill another interfering reg with less spill weight.
|
||||||
//
|
//
|
||||||
// FIXME: RAGreedy will sort this list by spill weight.
|
// FIXME: RAGreedy will sort this list by spill weight.
|
||||||
for (std::vector<unsigned>::iterator pregI = pregSpillCands.begin(),
|
for (SmallVectorImpl<unsigned>::iterator pregI = pregSpillCands.begin(),
|
||||||
pregE = pregSpillCands.end(); pregI != pregE; ++pregI) {
|
pregE = pregSpillCands.end(); pregI != pregE; ++pregI) {
|
||||||
|
|
||||||
if (!spillInterferences(*pregI, splitLVRs)) continue;
|
if (!spillInterferences(lvr, *pregI, splitLVRs)) continue;
|
||||||
|
|
||||||
unsigned interfReg = checkPhysRegInterference(lvr, *pregI);
|
unsigned interfReg = checkPhysRegInterference(lvr, *pregI);
|
||||||
if (interfReg != 0) {
|
if (interfReg != 0) {
|
||||||
const LiveSegment &seg =
|
const LiveSegment &seg =
|
||||||
*queries_[interfReg].firstInterference().liuSegPos();
|
*queries_[interfReg].firstInterference().liuSegPos();
|
||||||
dbgs() << "spilling cannot free " << tri_->getName(*pregI) <<
|
dbgs() << "spilling cannot free " << tri_->getName(*pregI) <<
|
||||||
" for " << lvr.reg << " with interference " << seg.liveVirtReg << "\n";
|
" for " << lvr.reg << " with interference " << *seg.liveVirtReg << "\n";
|
||||||
llvm_unreachable("Interference after spill.");
|
llvm_unreachable("Interference after spill.");
|
||||||
}
|
}
|
||||||
// Tell the caller to allocate to this newly freed physical register.
|
// Tell the caller to allocate to this newly freed physical register.
|
||||||
@@ -477,10 +481,13 @@ bool RABasic::runOnMachineFunction(MachineFunction &mf) {
|
|||||||
mri_ = &mf.getRegInfo();
|
mri_ = &mf.getRegInfo();
|
||||||
|
|
||||||
DEBUG(rmf_ = &getAnalysis<RenderMachineFunction>());
|
DEBUG(rmf_ = &getAnalysis<RenderMachineFunction>());
|
||||||
|
|
||||||
RegAllocBase::init(*tm_->getRegisterInfo(), getAnalysis<VirtRegMap>(),
|
const TargetRegisterInfo *TRI = tm_->getRegisterInfo();
|
||||||
|
RegAllocBase::init(*TRI, getAnalysis<VirtRegMap>(),
|
||||||
getAnalysis<LiveIntervals>());
|
getAnalysis<LiveIntervals>());
|
||||||
|
|
||||||
|
reservedRegs_ = TRI->getReservedRegs(*mf_);
|
||||||
|
|
||||||
// We may want to force InlineSpiller for this register allocator. For
|
// We may want to force InlineSpiller for this register allocator. For
|
||||||
// now we're also experimenting with the standard spiller.
|
// now we're also experimenting with the standard spiller.
|
||||||
//
|
//
|
||||||
|
Reference in New Issue
Block a user