mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
Tighten physical register invariants: Allocatable physical registers can
only be live in to a block if it is the function entry point or a landing pad. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150494 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -63,6 +63,9 @@ namespace llvm {
|
|||||||
/// allocatableRegs_ - A bit vector of allocatable registers.
|
/// allocatableRegs_ - A bit vector of allocatable registers.
|
||||||
BitVector allocatableRegs_;
|
BitVector allocatableRegs_;
|
||||||
|
|
||||||
|
/// reservedRegs_ - A bit vector of reserved registers.
|
||||||
|
BitVector reservedRegs_;
|
||||||
|
|
||||||
/// RegMaskSlots - Sorted list of instructions with register mask operands.
|
/// RegMaskSlots - Sorted list of instructions with register mask operands.
|
||||||
/// Always use the 'r' slot, RegMasks are normal clobbers, not early
|
/// Always use the 'r' slot, RegMasks are normal clobbers, not early
|
||||||
/// clobbers.
|
/// clobbers.
|
||||||
@@ -128,6 +131,12 @@ namespace llvm {
|
|||||||
return allocatableRegs_.test(reg);
|
return allocatableRegs_.test(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isReserved - is the physical register reg reserved in the current
|
||||||
|
/// function
|
||||||
|
bool isReserved(unsigned reg) const {
|
||||||
|
return reservedRegs_.test(reg);
|
||||||
|
}
|
||||||
|
|
||||||
/// getScaledIntervalSize - get the size of an interval in "units,"
|
/// getScaledIntervalSize - get the size of an interval in "units,"
|
||||||
/// where every function is composed of one thousand units. This
|
/// where every function is composed of one thousand units. This
|
||||||
/// measure scales properly with empty index slots in the function.
|
/// measure scales properly with empty index slots in the function.
|
||||||
|
@@ -94,6 +94,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
|
|||||||
lv_ = &getAnalysis<LiveVariables>();
|
lv_ = &getAnalysis<LiveVariables>();
|
||||||
indexes_ = &getAnalysis<SlotIndexes>();
|
indexes_ = &getAnalysis<SlotIndexes>();
|
||||||
allocatableRegs_ = tri_->getAllocatableSet(fn);
|
allocatableRegs_ = tri_->getAllocatableSet(fn);
|
||||||
|
reservedRegs_ = tri_->getReservedRegs(fn);
|
||||||
|
|
||||||
computeIntervals();
|
computeIntervals();
|
||||||
|
|
||||||
@@ -347,13 +348,24 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
|
|||||||
DEBUG(dbgs() << '\n');
|
DEBUG(dbgs() << '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static bool isRegLiveOutOf(const MachineBasicBlock *MBB, unsigned Reg) {
|
||||||
|
for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(),
|
||||||
|
SE = MBB->succ_end();
|
||||||
|
SI != SE; ++SI) {
|
||||||
|
const MachineBasicBlock* succ = *SI;
|
||||||
|
if (succ->isLiveIn(Reg))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
|
void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
|
||||||
MachineBasicBlock::iterator mi,
|
MachineBasicBlock::iterator mi,
|
||||||
SlotIndex MIIdx,
|
SlotIndex MIIdx,
|
||||||
MachineOperand& MO,
|
MachineOperand& MO,
|
||||||
LiveInterval &interval) {
|
LiveInterval &interval) {
|
||||||
// A physical register cannot be live across basic block, so its
|
|
||||||
// lifetime must end somewhere in its defining basic block.
|
|
||||||
DEBUG(dbgs() << "\t\tregister: " << PrintReg(interval.reg, tri_));
|
DEBUG(dbgs() << "\t\tregister: " << PrintReg(interval.reg, tri_));
|
||||||
|
|
||||||
SlotIndex baseIndex = MIIdx;
|
SlotIndex baseIndex = MIIdx;
|
||||||
@@ -407,12 +419,19 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
|
|||||||
baseIndex = baseIndex.getNextIndex();
|
baseIndex = baseIndex.getNextIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The only case we should have a dead physreg here without a killing or
|
// If we get here the register *should* be live out.
|
||||||
// instruction where we know it's dead is if it is live-in to the function
|
assert(!isAllocatable(interval.reg) && "Physregs shouldn't be live out!");
|
||||||
// and never used. Another possible case is the implicit use of the
|
|
||||||
// physical register has been deleted by two-address pass.
|
|
||||||
end = start.getDeadSlot();
|
|
||||||
|
|
||||||
|
// FIXME: We need saner rules for reserved regs.
|
||||||
|
if (isReserved(interval.reg)) {
|
||||||
|
assert(!isRegLiveOutOf(MBB, interval.reg) && "Reserved reg live-out?");
|
||||||
|
end = start.getDeadSlot();
|
||||||
|
} else {
|
||||||
|
// Unreserved, unallocable registers like EFLAGS can be live across basic
|
||||||
|
// block boundaries.
|
||||||
|
assert(isRegLiveOutOf(MBB, interval.reg) && "Unreserved reg not live-out?");
|
||||||
|
end = getMBBEndIdx(MBB);
|
||||||
|
}
|
||||||
exit:
|
exit:
|
||||||
assert(start < end && "did not find end of interval?");
|
assert(start < end && "did not find end of interval?");
|
||||||
|
|
||||||
@@ -442,6 +461,12 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB,
|
|||||||
void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
||||||
SlotIndex MIIdx,
|
SlotIndex MIIdx,
|
||||||
LiveInterval &interval) {
|
LiveInterval &interval) {
|
||||||
|
assert(TargetRegisterInfo::isPhysicalRegister(interval.reg) &&
|
||||||
|
"Only physical registers can be live in.");
|
||||||
|
assert((!isAllocatable(interval.reg) || MBB->getParent()->begin() ||
|
||||||
|
MBB->isLandingPad()) &&
|
||||||
|
"Allocatable live-ins only valid for entry blocks and landing pads.");
|
||||||
|
|
||||||
DEBUG(dbgs() << "\t\tlivein register: " << PrintReg(interval.reg, tri_));
|
DEBUG(dbgs() << "\t\tlivein register: " << PrintReg(interval.reg, tri_));
|
||||||
|
|
||||||
// Look for kills, if it reaches a def before it's killed, then it shouldn't
|
// Look for kills, if it reaches a def before it's killed, then it shouldn't
|
||||||
@@ -491,8 +516,17 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
|||||||
|
|
||||||
// Live-in register might not be used at all.
|
// Live-in register might not be used at all.
|
||||||
if (!SeenDefUse) {
|
if (!SeenDefUse) {
|
||||||
DEBUG(dbgs() << " live through");
|
if (isAllocatable(interval.reg) || isReserved(interval.reg)) {
|
||||||
end = getMBBEndIdx(MBB);
|
// This must be an entry block or landing pad - we asserted so on entry
|
||||||
|
// to the function. For these blocks the interval is dead on entry.
|
||||||
|
DEBUG(dbgs() << " dead");
|
||||||
|
end = start.getDeadSlot();
|
||||||
|
} else {
|
||||||
|
assert(isRegLiveOutOf(MBB, interval.reg) &&
|
||||||
|
"Live in reg untouched in block should be be live through.");
|
||||||
|
DEBUG(dbgs() << " live through");
|
||||||
|
end = getMBBEndIdx(MBB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotIndex defIdx = getMBBStartIdx(MBB);
|
SlotIndex defIdx = getMBBStartIdx(MBB);
|
||||||
|
@@ -11,7 +11,7 @@ entry:
|
|||||||
|
|
||||||
; THUMB: t:
|
; THUMB: t:
|
||||||
; THUMB-NOT: str r0, [r1], r0
|
; THUMB-NOT: str r0, [r1], r0
|
||||||
; THUMB: str r2, [r1]
|
; THUMB: str r1, [r0]
|
||||||
%0 = getelementptr inbounds %struct.foo* %this, i32 0, i32 1 ; <i64*> [#uses=1]
|
%0 = getelementptr inbounds %struct.foo* %this, i32 0, i32 1 ; <i64*> [#uses=1]
|
||||||
store i32 0, i32* inttoptr (i32 8 to i32*), align 8
|
store i32 0, i32* inttoptr (i32 8 to i32*), align 8
|
||||||
br i1 undef, label %bb.nph96, label %bb3
|
br i1 undef, label %bb.nph96, label %bb3
|
||||||
|
Reference in New Issue
Block a user