#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
+#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
/// Observe - Update liveness information to account for the current
/// instruction, which will not be scheduled.
///
- void Observe(MachineInstr *MI);
+ void Observe(MachineInstr *MI, unsigned Count);
/// FinishBlock - Clean up register live-range state.
///
if (MI->getDesc().isTerminator() || MI->isLabel())
return true;
+ // Don't attempt to schedule around any instruction that modifies
+ // a stack-oriented pointer, as it's unlikely to be profitable. This
+ // saves compile time, because it doesn't require every single
+ // stack slot reference to depend on the instruction that does the
+ // modification.
+ const TargetLowering &TLI = *MF.getTarget().getTargetLowering();
+ if (MI->modifiesRegister(TLI.getStackPointerRegisterToSaveRestore()))
+ return true;
+
return false;
}
// Schedule each sequence of instructions not interrupted by a label
// or anything else that effectively needs to shut down scheduling.
MachineBasicBlock::iterator Current = MBB->end();
+ unsigned Count = MBB->size(), CurrentCount = Count;
for (MachineBasicBlock::iterator I = Current; I != MBB->begin(); ) {
MachineInstr *MI = prior(I);
if (isSchedulingBoundary(MI, Fn)) {
- if (I != Current) {
- Scheduler.Run(0, MBB, I, Current);
- Scheduler.EmitSchedule();
- }
- Scheduler.Observe(MI);
+ Scheduler.Run(MBB, I, Current, CurrentCount);
+ Scheduler.EmitSchedule();
Current = MI;
+ CurrentCount = Count - 1;
+ Scheduler.Observe(MI, CurrentCount);
}
I = MI;
+ --Count;
}
- Scheduler.Run(0, MBB, MBB->begin(), Current);
+ assert(Count == 0 && "Instruction count mismatch!");
+ assert((MBB->begin() == Current || CurrentCount != 0) &&
+ "Instruction count mismatch!");
+ Scheduler.Run(MBB, MBB->begin(), Current, CurrentCount);
Scheduler.EmitSchedule();
// Clean up register live-range state.
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)
+ 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;
/// Observe - Update liveness information to account for the current
/// instruction, which will not be scheduled.
///
-void SchedulePostRATDList::Observe(MachineInstr *MI) {
+void SchedulePostRATDList::Observe(MachineInstr *MI, unsigned Count) {
+ assert(Count < InsertPosIndex && "Instruction index out of expected range!");
+
+ // Any register which was defined within the previous scheduling region
+ // may have been rescheduled and its lifetime may overlap with registers
+ // in ways not reflected in our current liveness state. For each such
+ // register, adjust the liveness state to be conservatively correct.
+ for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg)
+ if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) {
+ assert(KillIndices[Reg] == ~0u && "Clobbered register is live!");
+ // Mark this register to be non-renamable.
+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
+ // Move the def index to the end of the previous region, to reflect
+ // that the def could theoretically have been scheduled at the end.
+ DefIndices[Reg] = InsertPosIndex;
+ }
+
PrescanInstruction(MI);
- ScanInstruction(MI, 0);
+ ScanInstruction(MI, Count);
}
/// FinishBlock - Clean up register live-range state.
DefIndices[Reg] = Count;
KillIndices[Reg] = ~0u;
+ assert(((KillIndices[Reg] == ~0u) !=
+ (DefIndices[Reg] == ~0u)) &&
+ "Kill and Def maps aren't consistent for Reg!");
Classes[Reg] = 0;
RegRefs.erase(Reg);
// Repeat, for all subregs.
if (KillIndices[Reg] == ~0u) {
KillIndices[Reg] = Count;
DefIndices[Reg] = ~0u;
+ assert(((KillIndices[Reg] == ~0u) !=
+ (DefIndices[Reg] == ~0u)) &&
+ "Kill and Def maps aren't consistent for Reg!");
}
// Repeat, for all aliases.
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
// instructions from the bottom up, tracking information about liveness
// as we go to help determine which registers are available.
bool Changed = false;
- unsigned Count = SUnits.size() - 1;
- for (MachineBasicBlock::iterator I = End, E = Begin;
+ unsigned Count = InsertPosIndex - 1;
+ for (MachineBasicBlock::iterator I = InsertPos, E = Begin;
I != E; --Count) {
MachineInstr *MI = --I;
Classes[NewReg] = Classes[AntiDepReg];
DefIndices[NewReg] = DefIndices[AntiDepReg];
KillIndices[NewReg] = KillIndices[AntiDepReg];
+ assert(((KillIndices[NewReg] == ~0u) !=
+ (DefIndices[NewReg] == ~0u)) &&
+ "Kill and Def maps aren't consistent for NewReg!");
Classes[AntiDepReg] = 0;
DefIndices[AntiDepReg] = KillIndices[AntiDepReg];
KillIndices[AntiDepReg] = ~0u;
+ assert(((KillIndices[AntiDepReg] == ~0u) !=
+ (DefIndices[AntiDepReg] == ~0u)) &&
+ "Kill and Def maps aren't consistent for AntiDepReg!");
RegRefs.erase(AntiDepReg);
Changed = true;
ScanInstruction(MI, Count);
}
- assert(Count == ~0u && "Count mismatch!");
return Changed;
}