Allow the aggressive anti-dep breaker to process the same region multiple times. This is necessary because new anti-dependencies are exposed when "current" ones are broken.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85166 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Goodwin 2009-10-26 22:31:16 +00:00
parent 06d4033a35
commit e10deca33e
5 changed files with 303 additions and 189 deletions

View File

@ -31,6 +31,10 @@ class AntiDepBreaker {
public: public:
virtual ~AntiDepBreaker(); virtual ~AntiDepBreaker();
/// GetMaxTrials - Return the maximum number of anti-dependence
/// breaking attempts that will be made for a block.
virtual unsigned GetMaxTrials() =0;
/// Start - Initialize anti-dep breaking for a new basic block. /// Start - Initialize anti-dep breaking for a new basic block.
virtual void StartBlock(MachineBasicBlock *BB) =0; virtual void StartBlock(MachineBasicBlock *BB) =0;

View File

@ -22,26 +22,19 @@
#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
using namespace llvm; using namespace llvm;
AggressiveAntiDepBreaker:: static cl::opt<int>
AggressiveAntiDepBreaker(MachineFunction& MFi) : AntiDepTrials("agg-antidep-trials",
AntiDepBreaker(), MF(MFi), cl::desc("Maximum number of anti-dependency breaking passes"),
MRI(MF.getRegInfo()), cl::init(2), cl::Hidden);
TRI(MF.getTarget().getRegisterInfo()),
AllocatableSet(TRI->getAllocatableSet(MF)),
GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0)
{
}
AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { AggressiveAntiDepState::AggressiveAntiDepState(MachineBasicBlock *BB) :
} GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0) {
void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
// Initialize all registers to be in their own group. Initially we // Initialize all registers to be in their own group. Initially we
// assign the register to the same-indexed GroupNode. // assign the register to the same-indexed GroupNode.
for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i) for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i)
@ -50,102 +43,9 @@ void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
// Initialize the indices to indicate that no registers are live. // Initialize the indices to indicate that no registers are live.
std::fill(KillIndices, array_endof(KillIndices), ~0u); std::fill(KillIndices, array_endof(KillIndices), ~0u);
std::fill(DefIndices, array_endof(DefIndices), BB->size()); std::fill(DefIndices, array_endof(DefIndices), BB->size());
bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn());
// Determine the live-out physregs for this block.
if (IsReturnBlock) {
// In a return block, examine the function live-out regs.
for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(),
E = MRI.liveout_end(); I != E; ++I) {
unsigned Reg = *I;
UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
} else {
// In a non-return block, examine the live-in regs of all successors.
for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
SE = BB->succ_end(); SI != SE; ++SI)
for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(),
E = (*SI)->livein_end(); I != E; ++I) {
unsigned Reg = *I;
UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
}
// Mark live-out callee-saved registers. In a return block this is
// all callee-saved registers. In non-return this is any
// callee-saved register that is not saved in the prolog.
const MachineFrameInfo *MFI = MF.getFrameInfo();
BitVector Pristine = MFI->getPristineRegs(BB);
for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {
unsigned Reg = *I;
if (!IsReturnBlock && !Pristine.test(Reg)) continue;
UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
} }
void AggressiveAntiDepBreaker::FinishBlock() { unsigned AggressiveAntiDepState::GetGroup(unsigned Reg)
RegRefs.clear();
}
void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count,
unsigned InsertPosIndex) {
assert(Count < InsertPosIndex && "Instruction index out of expected range!");
DEBUG(errs() << "Observe: ");
DEBUG(MI->dump());
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
// If Reg is current live, then mark that it can't be renamed as
// we don't know the extent of its live-range anymore (now that it
// has been scheduled). If it is not live but was defined in the
// previous schedule region, then set its def index to the most
// conservative location (i.e. the beginning of the previous
// schedule region).
if (IsLive(Reg)) {
DEBUG(if (GetGroup(Reg) != 0)
errs() << " " << TRI->getName(Reg) << "=g" <<
GetGroup(Reg) << "->g0(region live-out)");
UnionGroups(Reg, 0);
} else if ((DefIndices[Reg] < InsertPosIndex) && (DefIndices[Reg] >= Count)) {
DefIndices[Reg] = Count;
}
}
std::set<unsigned> PassthruRegs;
GetPassthruRegs(MI, PassthruRegs);
PrescanInstruction(MI, Count, PassthruRegs);
ScanInstruction(MI, Count);
}
unsigned AggressiveAntiDepBreaker::GetGroup(unsigned Reg)
{ {
unsigned Node = GroupNodeIndices[Reg]; unsigned Node = GroupNodeIndices[Reg];
while (GroupNodes[Node] != Node) while (GroupNodes[Node] != Node)
@ -154,7 +54,7 @@ unsigned AggressiveAntiDepBreaker::GetGroup(unsigned Reg)
return Node; return Node;
} }
void AggressiveAntiDepBreaker::GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs) void AggressiveAntiDepState::GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs)
{ {
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
if (GetGroup(Reg) == Group) if (GetGroup(Reg) == Group)
@ -162,7 +62,7 @@ void AggressiveAntiDepBreaker::GetGroupRegs(unsigned Group, std::vector<unsigned
} }
} }
unsigned AggressiveAntiDepBreaker::UnionGroups(unsigned Reg1, unsigned Reg2) unsigned AggressiveAntiDepState::UnionGroups(unsigned Reg1, unsigned Reg2)
{ {
assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!"); assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!");
assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!"); assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!");
@ -178,7 +78,7 @@ unsigned AggressiveAntiDepBreaker::UnionGroups(unsigned Reg1, unsigned Reg2)
return Parent; return Parent;
} }
unsigned AggressiveAntiDepBreaker::LeaveGroup(unsigned Reg) unsigned AggressiveAntiDepState::LeaveGroup(unsigned Reg)
{ {
// Create a new GroupNode for Reg. Reg's existing GroupNode must // Create a new GroupNode for Reg. Reg's existing GroupNode must
// stay as is because there could be other GroupNodes referring to // stay as is because there could be other GroupNodes referring to
@ -189,13 +89,143 @@ unsigned AggressiveAntiDepBreaker::LeaveGroup(unsigned Reg)
return idx; return idx;
} }
bool AggressiveAntiDepBreaker::IsLive(unsigned Reg) bool AggressiveAntiDepState::IsLive(unsigned Reg)
{ {
// KillIndex must be defined and DefIndex not defined for a register // KillIndex must be defined and DefIndex not defined for a register
// to be live. // to be live.
return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u)); return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u));
} }
AggressiveAntiDepBreaker::
AggressiveAntiDepBreaker(MachineFunction& MFi) :
AntiDepBreaker(), MF(MFi),
MRI(MF.getRegInfo()),
TRI(MF.getTarget().getRegisterInfo()),
AllocatableSet(TRI->getAllocatableSet(MF)),
State(NULL), SavedState(NULL) {
}
AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() {
delete State;
delete SavedState;
}
unsigned AggressiveAntiDepBreaker::GetMaxTrials() {
if (AntiDepTrials <= 0)
return 1;
return AntiDepTrials;
}
void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
assert(State == NULL);
State = new AggressiveAntiDepState(BB);
bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn());
unsigned *KillIndices = State->GetKillIndices();
unsigned *DefIndices = State->GetDefIndices();
// Determine the live-out physregs for this block.
if (IsReturnBlock) {
// In a return block, examine the function live-out regs.
for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(),
E = MRI.liveout_end(); I != E; ++I) {
unsigned Reg = *I;
State->UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
State->UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
} else {
// In a non-return block, examine the live-in regs of all successors.
for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
SE = BB->succ_end(); SI != SE; ++SI)
for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(),
E = (*SI)->livein_end(); I != E; ++I) {
unsigned Reg = *I;
State->UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
State->UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
}
// Mark live-out callee-saved registers. In a return block this is
// all callee-saved registers. In non-return this is any
// callee-saved register that is not saved in the prolog.
const MachineFrameInfo *MFI = MF.getFrameInfo();
BitVector Pristine = MFI->getPristineRegs(BB);
for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {
unsigned Reg = *I;
if (!IsReturnBlock && !Pristine.test(Reg)) continue;
State->UnionGroups(Reg, 0);
KillIndices[Reg] = BB->size();
DefIndices[Reg] = ~0u;
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias;
State->UnionGroups(AliasReg, 0);
KillIndices[AliasReg] = BB->size();
DefIndices[AliasReg] = ~0u;
}
}
}
void AggressiveAntiDepBreaker::FinishBlock() {
delete State;
State = NULL;
delete SavedState;
SavedState = NULL;
}
void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count,
unsigned InsertPosIndex) {
assert(Count < InsertPosIndex && "Instruction index out of expected range!");
DEBUG(errs() << "Observe: ");
DEBUG(MI->dump());
unsigned *DefIndices = State->GetDefIndices();
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
// If Reg is current live, then mark that it can't be renamed as
// we don't know the extent of its live-range anymore (now that it
// has been scheduled). If it is not live but was defined in the
// previous schedule region, then set its def index to the most
// conservative location (i.e. the beginning of the previous
// schedule region).
if (State->IsLive(Reg)) {
DEBUG(if (State->GetGroup(Reg) != 0)
errs() << " " << TRI->getName(Reg) << "=g" <<
State->GetGroup(Reg) << "->g0(region live-out)");
State->UnionGroups(Reg, 0);
} else if ((DefIndices[Reg] < InsertPosIndex) && (DefIndices[Reg] >= Count)) {
DefIndices[Reg] = Count;
}
}
std::set<unsigned> PassthruRegs;
GetPassthruRegs(MI, PassthruRegs);
PrescanInstruction(MI, Count, PassthruRegs);
ScanInstruction(MI, Count);
// We're starting a new schedule region so forget any saved state.
delete SavedState;
SavedState = NULL;
}
bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI, bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI,
MachineOperand& MO) MachineOperand& MO)
{ {
@ -249,6 +279,10 @@ static void AntiDepPathStep(SUnit *SU, std::vector<SDep*>& Edges) {
void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Count, void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Count,
std::set<unsigned>& PassthruRegs) { std::set<unsigned>& PassthruRegs) {
unsigned *DefIndices = State->GetDefIndices();
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&
RegRefs = State->GetRegRefs();
// Scan the register defs for this instruction and update // Scan the register defs for this instruction and update
// live-ranges, groups and RegRefs. // live-ranges, groups and RegRefs.
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
@ -275,23 +309,23 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (Reg == 0) continue; if (Reg == 0) continue;
DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << GetGroup(Reg)); DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << State->GetGroup(Reg));
// If MI's defs have special allocation requirement, don't allow // If MI's defs have special allocation requirement, don't allow
// any def registers to be changed. Also assume all registers // any def registers to be changed. Also assume all registers
// defined in a call must not be changed (ABI). // defined in a call must not be changed (ABI).
if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq()) { if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq()) {
DEBUG(if (GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)");
UnionGroups(Reg, 0); State->UnionGroups(Reg, 0);
} }
// Any aliased that are live at this point are completely or // Any aliased that are live at this point are completely or
// partially defined here, so group those subregisters with Reg. // partially defined here, so group those subregisters with Reg.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
unsigned AliasReg = *Alias; unsigned AliasReg = *Alias;
if (IsLive(AliasReg)) { if (State->IsLive(AliasReg)) {
UnionGroups(Reg, AliasReg); State->UnionGroups(Reg, AliasReg);
DEBUG(errs() << "->g" << GetGroup(Reg) << "(via " << DEBUG(errs() << "->g" << State->GetGroup(Reg) << "(via " <<
TRI->getName(AliasReg) << ")"); TRI->getName(AliasReg) << ")");
} }
} }
@ -300,7 +334,7 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou
const TargetRegisterClass *RC = NULL; const TargetRegisterClass *RC = NULL;
if (i < MI->getDesc().getNumOperands()) if (i < MI->getDesc().getNumOperands())
RC = MI->getDesc().OpInfo[i].getRegClass(TRI); RC = MI->getDesc().OpInfo[i].getRegClass(TRI);
RegisterReference RR = { &MO, RC }; AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
RegRefs.insert(std::make_pair(Reg, RR)); RegRefs.insert(std::make_pair(Reg, RR));
} }
@ -310,6 +344,10 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou
void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI,
unsigned Count) { unsigned Count) {
DEBUG(errs() << "\tUse Groups:"); DEBUG(errs() << "\tUse Groups:");
unsigned *KillIndices = State->GetKillIndices();
unsigned *DefIndices = State->GetDefIndices();
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&
RegRefs = State->GetRegRefs();
// Scan the register uses for this instruction and update // Scan the register uses for this instruction and update
// live-ranges, groups and RegRefs. // live-ranges, groups and RegRefs.
@ -319,29 +357,30 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI,
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (Reg == 0) continue; if (Reg == 0) continue;
DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << GetGroup(Reg)); DEBUG(errs() << " " << TRI->getName(Reg) << "=g" <<
State->GetGroup(Reg));
// It wasn't previously live but now it is, this is a kill. Forget // It wasn't previously live but now it is, this is a kill. Forget
// the previous live-range information and start a new live-range // the previous live-range information and start a new live-range
// for the register. // for the register.
if (!IsLive(Reg)) { if (!State->IsLive(Reg)) {
KillIndices[Reg] = Count; KillIndices[Reg] = Count;
DefIndices[Reg] = ~0u; DefIndices[Reg] = ~0u;
RegRefs.erase(Reg); RegRefs.erase(Reg);
LeaveGroup(Reg); State->LeaveGroup(Reg);
DEBUG(errs() << "->g" << GetGroup(Reg) << "(last-use)"); DEBUG(errs() << "->g" << State->GetGroup(Reg) << "(last-use)");
} }
// Repeat, for subregisters. // Repeat, for subregisters.
for (const unsigned *Subreg = TRI->getSubRegisters(Reg); for (const unsigned *Subreg = TRI->getSubRegisters(Reg);
*Subreg; ++Subreg) { *Subreg; ++Subreg) {
unsigned SubregReg = *Subreg; unsigned SubregReg = *Subreg;
if (!IsLive(SubregReg)) { if (!State->IsLive(SubregReg)) {
KillIndices[SubregReg] = Count; KillIndices[SubregReg] = Count;
DefIndices[SubregReg] = ~0u; DefIndices[SubregReg] = ~0u;
RegRefs.erase(SubregReg); RegRefs.erase(SubregReg);
LeaveGroup(SubregReg); State->LeaveGroup(SubregReg);
DEBUG(errs() << " " << TRI->getName(SubregReg) << "->g" << DEBUG(errs() << " " << TRI->getName(SubregReg) << "->g" <<
GetGroup(SubregReg) << "(last-use)"); State->GetGroup(SubregReg) << "(last-use)");
} }
} }
@ -349,15 +388,15 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI,
// any use registers to be changed. Also assume all registers // any use registers to be changed. Also assume all registers
// used in a call must not be changed (ABI). // used in a call must not be changed (ABI).
if (MI->getDesc().isCall() || MI->getDesc().hasExtraSrcRegAllocReq()) { if (MI->getDesc().isCall() || MI->getDesc().hasExtraSrcRegAllocReq()) {
DEBUG(if (GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)");
UnionGroups(Reg, 0); State->UnionGroups(Reg, 0);
} }
// Note register reference... // Note register reference...
const TargetRegisterClass *RC = NULL; const TargetRegisterClass *RC = NULL;
if (i < MI->getDesc().getNumOperands()) if (i < MI->getDesc().getNumOperands())
RC = MI->getDesc().OpInfo[i].getRegClass(TRI); RC = MI->getDesc().OpInfo[i].getRegClass(TRI);
RegisterReference RR = { &MO, RC }; AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
RegRefs.insert(std::make_pair(Reg, RR)); RegRefs.insert(std::make_pair(Reg, RR));
} }
@ -377,14 +416,14 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI,
if (FirstReg != 0) { if (FirstReg != 0) {
DEBUG(errs() << "=" << TRI->getName(Reg)); DEBUG(errs() << "=" << TRI->getName(Reg));
UnionGroups(FirstReg, Reg); State->UnionGroups(FirstReg, Reg);
} else { } else {
DEBUG(errs() << " " << TRI->getName(Reg)); DEBUG(errs() << " " << TRI->getName(Reg));
FirstReg = Reg; FirstReg = Reg;
} }
} }
DEBUG(errs() << "->g" << GetGroup(FirstReg) << '\n'); DEBUG(errs() << "->g" << State->GetGroup(FirstReg) << '\n');
} }
} }
@ -395,10 +434,12 @@ BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) {
// Check all references that need rewriting for Reg. For each, use // Check all references that need rewriting for Reg. For each, use
// the corresponding register class to narrow the set of registers // the corresponding register class to narrow the set of registers
// that are appropriate for renaming. // that are appropriate for renaming.
std::pair<std::multimap<unsigned, RegisterReference>::iterator, std::pair<std::multimap<unsigned,
std::multimap<unsigned, RegisterReference>::iterator> AggressiveAntiDepState::RegisterReference>::iterator,
Range = RegRefs.equal_range(Reg); std::multimap<unsigned,
for (std::multimap<unsigned, RegisterReference>::iterator AggressiveAntiDepState::RegisterReference>::iterator>
Range = State->GetRegRefs().equal_range(Reg);
for (std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>::iterator
Q = Range.first, QE = Range.second; Q != QE; ++Q) { Q = Range.first, QE = Range.second; Q != QE; ++Q) {
const TargetRegisterClass *RC = Q->second.RC; const TargetRegisterClass *RC = Q->second.RC;
if (RC == NULL) continue; if (RC == NULL) continue;
@ -420,11 +461,16 @@ BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) {
bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
unsigned AntiDepGroupIndex, unsigned AntiDepGroupIndex,
std::map<unsigned, unsigned> &RenameMap) { std::map<unsigned, unsigned> &RenameMap) {
unsigned *KillIndices = State->GetKillIndices();
unsigned *DefIndices = State->GetDefIndices();
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&
RegRefs = State->GetRegRefs();
// Collect all registers in the same group as AntiDepReg. These all // Collect all registers in the same group as AntiDepReg. These all
// need to be renamed together if we are to break the // need to be renamed together if we are to break the
// anti-dependence. // anti-dependence.
std::vector<unsigned> Regs; std::vector<unsigned> Regs;
GetGroupRegs(AntiDepGroupIndex, Regs); State->GetGroupRegs(AntiDepGroupIndex, Regs);
assert(Regs.size() > 0 && "Empty register group!"); assert(Regs.size() > 0 && "Empty register group!");
if (Regs.size() == 0) if (Regs.size() == 0)
return false; return false;
@ -484,7 +530,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
// If Reg is dead and Reg's most recent def is not before // If Reg is dead and Reg's most recent def is not before
// SuperRegs's kill, it's safe to replace SuperReg with // SuperRegs's kill, it's safe to replace SuperReg with
// Reg. We must also check all subregisters of Reg. // Reg. We must also check all subregisters of Reg.
if (IsLive(Reg) || (KillIndices[SuperReg] > DefIndices[Reg])) { if (State->IsLive(Reg) || (KillIndices[SuperReg] > DefIndices[Reg])) {
DEBUG(errs() << "(live)"); DEBUG(errs() << "(live)");
continue; continue;
} else { } else {
@ -492,7 +538,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
for (const unsigned *Subreg = TRI->getSubRegisters(Reg); for (const unsigned *Subreg = TRI->getSubRegisters(Reg);
*Subreg; ++Subreg) { *Subreg; ++Subreg) {
unsigned SubregReg = *Subreg; unsigned SubregReg = *Subreg;
if (IsLive(SubregReg) || (KillIndices[SuperReg] > DefIndices[SubregReg])) { if (State->IsLive(SubregReg) || (KillIndices[SuperReg] > DefIndices[SubregReg])) {
DEBUG(errs() << "(subreg " << TRI->getName(SubregReg) << " live)"); DEBUG(errs() << "(subreg " << TRI->getName(SubregReg) << " live)");
found = true; found = true;
break; break;
@ -518,13 +564,29 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
/// BreakAntiDependencies - Identifiy anti-dependencies within the /// BreakAntiDependencies - Identifiy anti-dependencies within the
/// ScheduleDAG and break them by renaming registers. /// ScheduleDAG and break them by renaming registers.
/// ///
unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUnits, unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(
MachineBasicBlock::iterator& Begin, std::vector<SUnit>& SUnits,
MachineBasicBlock::iterator& End, MachineBasicBlock::iterator& Begin,
unsigned InsertPosIndex) { MachineBasicBlock::iterator& End,
unsigned InsertPosIndex) {
unsigned *KillIndices = State->GetKillIndices();
unsigned *DefIndices = State->GetDefIndices();
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&
RegRefs = State->GetRegRefs();
// The code below assumes that there is at least one instruction, // The code below assumes that there is at least one instruction,
// so just duck out immediately if the block is empty. // so just duck out immediately if the block is empty.
if (SUnits.empty()) return false; if (SUnits.empty()) return false;
// Manage saved state to enable multiple passes...
if (AntiDepTrials > 1) {
if (SavedState == NULL) {
SavedState = new AggressiveAntiDepState(*State);
} else {
delete State;
State = new AggressiveAntiDepState(*SavedState);
}
}
// ...need a map from MI to SUnit. // ...need a map from MI to SUnit.
std::map<MachineInstr *, SUnit *> MISUnitMap; std::map<MachineInstr *, SUnit *> MISUnitMap;
@ -539,7 +601,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn
{ {
DEBUG(errs() << "Available regs:"); DEBUG(errs() << "Available regs:");
for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) {
if (!IsLive(Reg)) if (!State->IsLive(Reg))
DEBUG(errs() << " " << TRI->getName(Reg)); DEBUG(errs() << " " << TRI->getName(Reg));
} }
DEBUG(errs() << '\n'); DEBUG(errs() << '\n');
@ -623,7 +685,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn
if (AntiDepReg == 0) continue; if (AntiDepReg == 0) continue;
// Determine AntiDepReg's register group. // Determine AntiDepReg's register group.
const unsigned GroupIndex = GetGroup(AntiDepReg); const unsigned GroupIndex = State->GetGroup(AntiDepReg);
if (GroupIndex == 0) { if (GroupIndex == 0) {
DEBUG(errs() << " (zero group)\n"); DEBUG(errs() << " (zero group)\n");
continue; continue;
@ -649,10 +711,12 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn
// Update the references to the old register CurrReg to // Update the references to the old register CurrReg to
// refer to the new register NewReg. // refer to the new register NewReg.
std::pair<std::multimap<unsigned, RegisterReference>::iterator, std::pair<std::multimap<unsigned,
std::multimap<unsigned, RegisterReference>::iterator> AggressiveAntiDepState::RegisterReference>::iterator,
std::multimap<unsigned,
AggressiveAntiDepState::RegisterReference>::iterator>
Range = RegRefs.equal_range(CurrReg); Range = RegRefs.equal_range(CurrReg);
for (std::multimap<unsigned, RegisterReference>::iterator for (std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>::iterator
Q = Range.first, QE = Range.second; Q != QE; ++Q) { Q = Range.first, QE = Range.second; Q != QE; ++Q) {
Q->second.Operand->setReg(NewReg); Q->second.Operand->setReg(NewReg);
} }
@ -660,12 +724,12 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn
// We just went back in time and modified history; the // We just went back in time and modified history; the
// liveness information for CurrReg is now inconsistent. Set // liveness information for CurrReg is now inconsistent. Set
// the state as if it were dead. // the state as if it were dead.
UnionGroups(NewReg, 0); State->UnionGroups(NewReg, 0);
RegRefs.erase(NewReg); RegRefs.erase(NewReg);
DefIndices[NewReg] = DefIndices[CurrReg]; DefIndices[NewReg] = DefIndices[CurrReg];
KillIndices[NewReg] = KillIndices[CurrReg]; KillIndices[NewReg] = KillIndices[CurrReg];
UnionGroups(CurrReg, 0); State->UnionGroups(CurrReg, 0);
RegRefs.erase(CurrReg); RegRefs.erase(CurrReg);
DefIndices[CurrReg] = KillIndices[CurrReg]; DefIndices[CurrReg] = KillIndices[CurrReg];
KillIndices[CurrReg] = ~0u; KillIndices[CurrReg] = ~0u;

View File

@ -28,11 +28,12 @@
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
namespace llvm { namespace llvm {
class AggressiveAntiDepBreaker : public AntiDepBreaker { /// Class AggressiveAntiDepState
MachineFunction& MF; /// Contains all the state necessary for anti-dep breaking. We place
MachineRegisterInfo &MRI; /// into a separate class so be can conveniently save/restore it to
const TargetRegisterInfo *TRI; /// enable multi-pass anti-dep breaking.
class AggressiveAntiDepState {
public:
/// RegisterReference - Information about a register reference /// RegisterReference - Information about a register reference
/// within a liverange /// within a liverange
typedef struct { typedef struct {
@ -42,59 +43,43 @@ namespace llvm {
const TargetRegisterClass *RC; const TargetRegisterClass *RC;
} RegisterReference; } RegisterReference;
/// AllocatableSet - The set of allocatable registers. private:
/// We'll be ignoring anti-dependencies on non-allocatable registers,
/// because they may not be safe to break.
const BitVector AllocatableSet;
/// GroupNodes - Implements a disjoint-union data structure to /// GroupNodes - Implements a disjoint-union data structure to
/// form register groups. A node is represented by an index into /// form register groups. A node is represented by an index into
/// the vector. A node can "point to" itself to indicate that it /// the vector. A node can "point to" itself to indicate that it
/// is the parent of a group, or point to another node to indicate /// is the parent of a group, or point to another node to indicate
/// that it is a member of the same group as that node. /// that it is a member of the same group as that node.
std::vector<unsigned> GroupNodes; std::vector<unsigned> GroupNodes;
/// GroupNodeIndices - For each register, the index of the GroupNode /// GroupNodeIndices - For each register, the index of the GroupNode
/// currently representing the group that the register belongs to. /// currently representing the group that the register belongs to.
/// Register 0 is always represented by the 0 group, a group /// Register 0 is always represented by the 0 group, a group
/// composed of registers that are not eligible for anti-aliasing. /// composed of registers that are not eligible for anti-aliasing.
unsigned GroupNodeIndices[TargetRegisterInfo::FirstVirtualRegister]; unsigned GroupNodeIndices[TargetRegisterInfo::FirstVirtualRegister];
/// RegRegs - Map registers to all their references within a live range. /// RegRefs - Map registers to all their references within a live range.
std::multimap<unsigned, RegisterReference> RegRefs; std::multimap<unsigned, RegisterReference> RegRefs;
/// KillIndices - The index of the most recent kill (proceding bottom-up), /// KillIndices - The index of the most recent kill (proceding bottom-up),
/// or ~0u if the register is not live. /// or ~0u if the register is not live.
unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister];
/// DefIndices - The index of the most recent complete def (proceding bottom /// DefIndices - The index of the most recent complete def (proceding bottom
/// up), or ~0u if the register is live. /// up), or ~0u if the register is live.
unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister]; unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister];
public: public:
AggressiveAntiDepBreaker(MachineFunction& MFi); AggressiveAntiDepState(MachineBasicBlock *BB);
~AggressiveAntiDepBreaker();
/// Start - Initialize anti-dep breaking for a new basic block. /// GetKillIndices - Return the kill indices.
void StartBlock(MachineBasicBlock *BB); unsigned *GetKillIndices() { return KillIndices; }
/// BreakAntiDependencies - Identifiy anti-dependencies along the critical path /// GetDefIndices - Return the define indices.
/// of the ScheduleDAG and break them by renaming registers. unsigned *GetDefIndices() { return DefIndices; }
///
unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits,
MachineBasicBlock::iterator& Begin,
MachineBasicBlock::iterator& End,
unsigned InsertPosIndex);
/// Observe - Update liveness information to account for the current /// GetRegRefs - Return the RegRefs map.
/// instruction, which will not be scheduled. std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; }
///
void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex);
/// Finish - Finish anti-dep breaking for a basic block.
void FinishBlock();
private:
// GetGroup - Get the group for a register. The returned value is // GetGroup - Get the group for a register. The returned value is
// the index of the GroupNode representing the group. // the index of the GroupNode representing the group.
unsigned GetGroup(unsigned Reg); unsigned GetGroup(unsigned Reg);
@ -115,7 +100,57 @@ namespace llvm {
/// IsLive - Return true if Reg is live /// IsLive - Return true if Reg is live
bool IsLive(unsigned Reg); bool IsLive(unsigned Reg);
};
/// Class AggressiveAntiDepBreaker
class AggressiveAntiDepBreaker : public AntiDepBreaker {
MachineFunction& MF;
MachineRegisterInfo &MRI;
const TargetRegisterInfo *TRI;
/// AllocatableSet - The set of allocatable registers.
/// We'll be ignoring anti-dependencies on non-allocatable registers,
/// because they may not be safe to break.
const BitVector AllocatableSet;
/// State - The state used to identify and rename anti-dependence
/// registers.
AggressiveAntiDepState *State;
/// SavedState - The state for the start of an anti-dep
/// region. Used to restore the state at the beginning of each
/// pass
AggressiveAntiDepState *SavedState;
public:
AggressiveAntiDepBreaker(MachineFunction& MFi);
~AggressiveAntiDepBreaker();
/// GetMaxTrials - As anti-dependencies are broken, additional
/// dependencies may be exposed, so multiple passes are required.
unsigned GetMaxTrials();
/// Start - Initialize anti-dep breaking for a new basic block.
void StartBlock(MachineBasicBlock *BB);
/// BreakAntiDependencies - Identifiy anti-dependencies along the critical path
/// of the ScheduleDAG and break them by renaming registers.
///
unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits,
MachineBasicBlock::iterator& Begin,
MachineBasicBlock::iterator& End,
unsigned InsertPosIndex);
/// Observe - Update liveness information to account for the current
/// instruction, which will not be scheduled.
///
void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex);
/// Finish - Finish anti-dep breaking for a basic block.
void FinishBlock();
private:
/// IsImplicitDefUse - Return true if MO represents a register /// IsImplicitDefUse - Return true if MO represents a register
/// that is both implicitly used and defined in MI /// that is both implicitly used and defined in MI
bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO); bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO);

View File

@ -64,6 +64,10 @@ namespace llvm {
CriticalAntiDepBreaker(MachineFunction& MFi); CriticalAntiDepBreaker(MachineFunction& MFi);
~CriticalAntiDepBreaker(); ~CriticalAntiDepBreaker();
/// GetMaxTrials - Critical path anti-dependence breaking requires
/// only a single pass
unsigned GetMaxTrials() { return 1; }
/// Start - Initialize anti-dep breaking for a new basic block. /// Start - Initialize anti-dep breaking for a new basic block.
void StartBlock(MachineBasicBlock *BB); void StartBlock(MachineBasicBlock *BB);

View File

@ -40,6 +40,7 @@
#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtarget.h" #include "llvm/Target/TargetSubtarget.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -315,16 +316,20 @@ void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) {
/// Schedule - Schedule the instruction range using list scheduling. /// Schedule - Schedule the instruction range using list scheduling.
/// ///
void SchedulePostRATDList::Schedule() { void SchedulePostRATDList::Schedule() {
DEBUG(errs() << "********** List Scheduling **********\n");
// Build the scheduling graph. // Build the scheduling graph.
BuildSchedGraph(AA); BuildSchedGraph(AA);
if (AntiDepBreak != NULL) { if (AntiDepBreak != NULL) {
unsigned Broken = for (unsigned i = 0, Trials = AntiDepBreak->GetMaxTrials();
AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos, i < Trials; ++i) {
InsertPosIndex); DEBUG(errs() << "********** Break Anti-Deps, Trial " <<
if (Broken > 0) { i << " **********\n");
unsigned Broken =
AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos,
InsertPosIndex);
if (Broken == 0)
break;
// We made changes. Update the dependency graph. // We made changes. Update the dependency graph.
// Theoretically we could update the graph in place: // Theoretically we could update the graph in place:
// When a live range is changed to use a different register, remove // When a live range is changed to use a different register, remove
@ -340,6 +345,8 @@ void SchedulePostRATDList::Schedule() {
} }
} }
DEBUG(errs() << "********** List Scheduling **********\n");
DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
SUnits[su].dumpAll(this)); SUnits[su].dumpAll(this));