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:
David Goodwin
2009-08-25 17:03:05 +00:00
parent 379a087cc7
commit 88a589c4b3
4 changed files with 203 additions and 21 deletions

View File

@ -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
//===----------------------------------------------------------------------===//