mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 04:38:24 +00:00
Fixup register kills after scheduling.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80002 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -40,6 +40,7 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumNoops, "Number of noops inserted");
|
||||
@ -140,6 +141,11 @@ namespace {
|
||||
/// Schedule - Schedule the instruction range using list scheduling.
|
||||
///
|
||||
void Schedule();
|
||||
|
||||
/// FixupKills - Fix register kill flags that have been made
|
||||
/// invalid due to scheduling
|
||||
///
|
||||
void FixupKills(MachineBasicBlock *MBB);
|
||||
|
||||
/// Observe - Update liveness information to account for the current
|
||||
/// instruction, which will not be scheduled.
|
||||
@ -150,6 +156,11 @@ namespace {
|
||||
///
|
||||
void FinishBlock();
|
||||
|
||||
/// GenerateLivenessForKills - If true then generate Def/Kill
|
||||
/// information for use in updating register kill. If false then
|
||||
/// generate Def/Kill information for anti-dependence breaking.
|
||||
bool GenerateLivenessForKills;
|
||||
|
||||
private:
|
||||
void PrescanInstruction(MachineInstr *MI);
|
||||
void ScanInstruction(MachineInstr *MI, unsigned Count);
|
||||
@ -202,6 +213,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
|
||||
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
|
||||
MBB != MBBe; ++MBB) {
|
||||
// Initialize register live-range state for scheduling in this block.
|
||||
Scheduler.GenerateLivenessForKills = false;
|
||||
Scheduler.StartBlock(MBB);
|
||||
|
||||
// Schedule each sequence of instructions not interrupted by a label
|
||||
@ -228,6 +240,12 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
// Clean up register live-range state.
|
||||
Scheduler.FinishBlock();
|
||||
|
||||
// Initialize register live-range state again and update register kills
|
||||
Scheduler.GenerateLivenessForKills = true;
|
||||
Scheduler.StartBlock(MBB);
|
||||
Scheduler.FixupKills(MBB);
|
||||
Scheduler.FinishBlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -287,26 +305,28 @@ void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) {
|
||||
}
|
||||
}
|
||||
|
||||
// Consider callee-saved registers as live-out, since we're running after
|
||||
// prologue/epilogue insertion so there's no way to add additional
|
||||
// saved registers.
|
||||
//
|
||||
// TODO: If the callee saves and restores these, then we can potentially
|
||||
// use them between the save and the restore. To do that, we could scan
|
||||
// the exit blocks to see which of these registers are defined.
|
||||
// Alternatively, callee-saved registers that aren't saved and restored
|
||||
// could be marked live-in in every block.
|
||||
for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {
|
||||
unsigned Reg = *I;
|
||||
Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
|
||||
KillIndices[Reg] = BB->size();
|
||||
DefIndices[Reg] = ~0u;
|
||||
// Repeat, for all aliases.
|
||||
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
|
||||
unsigned AliasReg = *Alias;
|
||||
Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);
|
||||
KillIndices[AliasReg] = BB->size();
|
||||
DefIndices[AliasReg] = ~0u;
|
||||
if (!GenerateLivenessForKills) {
|
||||
// Consider callee-saved registers as live-out, since we're running after
|
||||
// prologue/epilogue insertion so there's no way to add additional
|
||||
// saved registers.
|
||||
//
|
||||
// TODO: If the callee saves and restores these, then we can potentially
|
||||
// use them between the save and the restore. To do that, we could scan
|
||||
// the exit blocks to see which of these registers are defined.
|
||||
// Alternatively, callee-saved registers that aren't saved and restored
|
||||
// could be marked live-in in every block.
|
||||
for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {
|
||||
unsigned Reg = *I;
|
||||
Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
|
||||
KillIndices[Reg] = BB->size();
|
||||
DefIndices[Reg] = ~0u;
|
||||
// Repeat, for all aliases.
|
||||
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
|
||||
unsigned AliasReg = *Alias;
|
||||
Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);
|
||||
KillIndices[AliasReg] = BB->size();
|
||||
DefIndices[AliasReg] = ~0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -467,11 +487,17 @@ void SchedulePostRATDList::ScanInstruction(MachineInstr *MI,
|
||||
Classes[SubregReg] = 0;
|
||||
RegRefs.erase(SubregReg);
|
||||
}
|
||||
// Conservatively mark super-registers as unusable.
|
||||
// Conservatively mark super-registers as unusable. If
|
||||
// initializing for kill updating, then mark all supers as defined
|
||||
// as well.
|
||||
for (const unsigned *Super = TRI->getSuperRegisters(Reg);
|
||||
*Super; ++Super) {
|
||||
unsigned SuperReg = *Super;
|
||||
Classes[SuperReg] = reinterpret_cast<TargetRegisterClass *>(-1);
|
||||
if (GenerateLivenessForKills) {
|
||||
DefIndices[SuperReg] = Count;
|
||||
KillIndices[SuperReg] = ~0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
@ -753,6 +779,53 @@ bool SchedulePostRATDList::BreakAntiDependencies() {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// FixupKills - Fix the register kill flags, they may have been made
|
||||
/// incorrect by instruction reordering.
|
||||
///
|
||||
void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) {
|
||||
DEBUG(errs() << "Fixup kills for BB ID#" << MBB->getNumber() << '\n');
|
||||
|
||||
std::set<unsigned> killedRegs;
|
||||
BitVector ReservedRegs = TRI->getReservedRegs(MF);
|
||||
|
||||
unsigned Count = MBB->size();
|
||||
for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin();
|
||||
I != E; --Count) {
|
||||
MachineInstr *MI = --I;
|
||||
|
||||
// After regalloc, IMPLICIT_DEF instructions aren't safe to treat as
|
||||
// dependence-breaking. In the case of an INSERT_SUBREG, the IMPLICIT_DEF
|
||||
// is left behind appearing to clobber the super-register, while the
|
||||
// subregister needs to remain live. So we just ignore them.
|
||||
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
|
||||
continue;
|
||||
|
||||
PrescanInstruction(MI);
|
||||
ScanInstruction(MI, Count);
|
||||
|
||||
// Examine all used registers and set kill flag. When a register
|
||||
// is used multiple times we only set the kill flag on the first
|
||||
// use.
|
||||
killedRegs.clear();
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
if (!MO.isReg() || !MO.isUse()) continue;
|
||||
unsigned Reg = MO.getReg();
|
||||
if ((Reg == 0) || ReservedRegs.test(Reg)) continue;
|
||||
|
||||
bool kill = ((KillIndices[Reg] == Count) &&
|
||||
(killedRegs.find(Reg) == killedRegs.end()));
|
||||
if (MO.isKill() != kill) {
|
||||
MO.setIsKill(kill);
|
||||
DEBUG(errs() << "Fixed " << MO << " in ");
|
||||
DEBUG(MI->dump());
|
||||
}
|
||||
|
||||
killedRegs.insert(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top-Down Scheduling
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Reference in New Issue
Block a user