diff options
Diffstat (limited to 'lib/CodeGen/PostRASchedulerList.cpp')
-rw-r--r-- | lib/CodeGen/PostRASchedulerList.cpp | 115 |
1 files changed, 94 insertions, 21 deletions
diff --git a/lib/CodeGen/PostRASchedulerList.cpp b/lib/CodeGen/PostRASchedulerList.cpp index 5042415c2c..a74d29db8c 100644 --- a/lib/CodeGen/PostRASchedulerList.cpp +++ b/lib/CodeGen/PostRASchedulerList.cpp @@ -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 //===----------------------------------------------------------------------===// |