mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-21 02:24:22 +00:00
Keep track of register masks in LiveIntervalAnalysis.
Build an ordered vector of register mask operands (i.e., calls) when computing live intervals. Provide a checkRegMaskInterference() function that computes a bit mask of usable registers for a live range. This is a quick way of determining of a live range crosses any calls, and restricting it to the callee saved registers if it does. Previously, we had to discover call clobbers for each candidate register independently. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150077 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -63,6 +63,25 @@ namespace llvm {
|
|||||||
/// allocatableRegs_ - A bit vector of allocatable registers.
|
/// allocatableRegs_ - A bit vector of allocatable registers.
|
||||||
BitVector allocatableRegs_;
|
BitVector allocatableRegs_;
|
||||||
|
|
||||||
|
/// RegMaskSlots - Sorted list of instructions with register mask operands.
|
||||||
|
/// Always use the 'r' slot, RegMasks are normal clobbers, not early
|
||||||
|
/// clobbers.
|
||||||
|
SmallVector<SlotIndex, 8> RegMaskSlots;
|
||||||
|
|
||||||
|
/// RegMaskBits - This vector is parallel to RegMaskSlots, it holds a
|
||||||
|
/// pointer to the corresponding register mask. This pointer can be
|
||||||
|
/// recomputed as:
|
||||||
|
///
|
||||||
|
/// MI = Indexes->getInstructionFromIndex(RegMaskSlot[N]);
|
||||||
|
/// unsigned OpNum = findRegMaskOperand(MI);
|
||||||
|
/// RegMaskBits[N] = MI->getOperand(OpNum).getRegMask();
|
||||||
|
///
|
||||||
|
/// This is kept in a separate vector partly because some standard
|
||||||
|
/// libraries don't support lower_bound() with mixed objects, partly to
|
||||||
|
/// improve locality when searching in RegMaskSlots.
|
||||||
|
/// Also see the comment in LiveInterval::find().
|
||||||
|
SmallVector<const uint32_t*, 8> RegMaskBits;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
LiveIntervals() : MachineFunctionPass(ID) {
|
LiveIntervals() : MachineFunctionPass(ID) {
|
||||||
@ -249,6 +268,30 @@ namespace llvm {
|
|||||||
/// point can be above or below mi, but must be in the same basic block.
|
/// point can be above or below mi, but must be in the same basic block.
|
||||||
void moveInstr(MachineBasicBlock::iterator insertPt, MachineInstr* mi);
|
void moveInstr(MachineBasicBlock::iterator insertPt, MachineInstr* mi);
|
||||||
|
|
||||||
|
// Register mask functions.
|
||||||
|
//
|
||||||
|
// Machine instructions may use a register mask operand to indicate that a
|
||||||
|
// large number of registers are clobbered by the instruction. This is
|
||||||
|
// typically used for calls.
|
||||||
|
//
|
||||||
|
// For compile time performance reasons, these clobbers are not recorded in
|
||||||
|
// the live intervals for individual physical registers. Instead,
|
||||||
|
// LiveIntervalAnalysis maintains a sorted list of instructions with
|
||||||
|
// register mask operands.
|
||||||
|
|
||||||
|
/// getRegMaskSlots - Returns asorted array of slot indices of all
|
||||||
|
/// instructions with register mask operands.
|
||||||
|
ArrayRef<SlotIndex> getRegMaskSlots() const { return RegMaskSlots; }
|
||||||
|
|
||||||
|
/// checkRegMaskInterference - Test if LI is live across any register mask
|
||||||
|
/// instructions, and compute a bit mask of physical registers that are not
|
||||||
|
/// clobbered by any of them.
|
||||||
|
///
|
||||||
|
/// Returns false if LI doesn't cross any register mask instructions. In
|
||||||
|
/// that case, the bit vector is not filled in.
|
||||||
|
bool checkRegMaskInterference(LiveInterval &LI,
|
||||||
|
BitVector &UsableRegs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// computeIntervals - Compute live intervals.
|
/// computeIntervals - Compute live intervals.
|
||||||
void computeIntervals();
|
void computeIntervals();
|
||||||
|
@ -88,6 +88,8 @@ void LiveIntervals::releaseMemory() {
|
|||||||
delete I->second;
|
delete I->second;
|
||||||
|
|
||||||
r2iMap_.clear();
|
r2iMap_.clear();
|
||||||
|
RegMaskSlots.clear();
|
||||||
|
RegMaskBits.clear();
|
||||||
|
|
||||||
// Release VNInfo memory regions, VNInfo objects don't need to be dtor'd.
|
// Release VNInfo memory regions, VNInfo objects don't need to be dtor'd.
|
||||||
VNInfoAllocator.Reset();
|
VNInfoAllocator.Reset();
|
||||||
@ -558,10 +560,20 @@ void LiveIntervals::computeIntervals() {
|
|||||||
DEBUG(dbgs() << MIIndex << "\t" << *MI);
|
DEBUG(dbgs() << MIIndex << "\t" << *MI);
|
||||||
if (MI->isDebugValue())
|
if (MI->isDebugValue())
|
||||||
continue;
|
continue;
|
||||||
|
assert(indexes_->getInstructionFromIndex(MIIndex) == MI &&
|
||||||
|
"Lost SlotIndex synchronization");
|
||||||
|
|
||||||
// Handle defs.
|
// Handle defs.
|
||||||
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
|
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
|
||||||
MachineOperand &MO = MI->getOperand(i);
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
|
|
||||||
|
// Collect register masks.
|
||||||
|
if (MO.isRegMask()) {
|
||||||
|
RegMaskSlots.push_back(MIIndex.getRegSlot());
|
||||||
|
RegMaskBits.push_back(MO.getRegMask());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!MO.isReg() || !MO.getReg())
|
if (!MO.isReg() || !MO.getReg())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1111,3 +1123,53 @@ LiveRange LiveIntervals::addLiveRangeToEndOfBlock(unsigned reg,
|
|||||||
|
|
||||||
return LR;
|
return LR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Register mask functions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
bool LiveIntervals::checkRegMaskInterference(LiveInterval &LI,
|
||||||
|
BitVector &UsableRegs) {
|
||||||
|
if (LI.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We are going to enumerate all the register mask slots contained in LI.
|
||||||
|
// Start with a binary search of RegMaskSlots to find a starting point.
|
||||||
|
LiveInterval::iterator LiveI = LI.begin(), LiveE = LI.end();
|
||||||
|
ArrayRef<SlotIndex> Slots = getRegMaskSlots();
|
||||||
|
ArrayRef<SlotIndex>::iterator SlotI =
|
||||||
|
std::lower_bound(Slots.begin(), Slots.end(), LiveI->start);
|
||||||
|
ArrayRef<SlotIndex>::iterator SlotE = Slots.end();
|
||||||
|
|
||||||
|
// No slots in range, LI begins after the last call.
|
||||||
|
if (SlotI == SlotE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool Found = false;
|
||||||
|
for (;;) {
|
||||||
|
assert(*SlotI >= LiveI->start);
|
||||||
|
// Loop over all slots overlapping this segment.
|
||||||
|
while (*SlotI < LiveI->end) {
|
||||||
|
// *SlotI overlaps LI. Collect mask bits.
|
||||||
|
if (!Found) {
|
||||||
|
// This is the first overlap. Initialize UsableRegs to all ones.
|
||||||
|
UsableRegs.clear();
|
||||||
|
UsableRegs.resize(tri_->getNumRegs(), true);
|
||||||
|
Found = true;
|
||||||
|
}
|
||||||
|
// Remove usable registers clobbered by this mask.
|
||||||
|
UsableRegs.clearBitsNotInMask(RegMaskBits[SlotI-Slots.begin()]);
|
||||||
|
if (++SlotI == SlotE)
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
// *SlotI is beyond the current LI segment.
|
||||||
|
LiveI = LI.advanceTo(LiveI, *SlotI);
|
||||||
|
if (LiveI == LiveE)
|
||||||
|
return Found;
|
||||||
|
// Advance SlotI until it overlaps.
|
||||||
|
while (*SlotI < LiveI->start)
|
||||||
|
if (++SlotI == SlotE)
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user