mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-20 14:29:27 +00:00
Move the PostRA scheduler's fixupKills function for reuse.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198121 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c5443a90d8
commit
8e62b298e1
@ -246,11 +246,11 @@ protected:
|
|||||||
unsigned NumInstrsScheduled;
|
unsigned NumInstrsScheduled;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S,
|
ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S, bool IsPostRA):
|
||||||
bool IsPostRA):
|
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA,
|
||||||
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA, C->LIS), AA(C->AA),
|
/*RemoveKillFlags=*/IsPostRA, C->LIS),
|
||||||
SchedImpl(S), Topo(SUnits, &ExitSU), CurrentTop(), CurrentBottom(),
|
AA(C->AA), SchedImpl(S), Topo(SUnits, &ExitSU), CurrentTop(),
|
||||||
NextClusterPred(NULL), NextClusterSucc(NULL) {
|
CurrentBottom(), NextClusterPred(NULL), NextClusterSucc(NULL) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
NumInstrsScheduled = 0;
|
NumInstrsScheduled = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -88,6 +88,10 @@ namespace llvm {
|
|||||||
/// isPostRA flag indicates vregs cannot be present.
|
/// isPostRA flag indicates vregs cannot be present.
|
||||||
bool IsPostRA;
|
bool IsPostRA;
|
||||||
|
|
||||||
|
/// True if the DAG builder should remove kill flags (in preparation for
|
||||||
|
/// rescheduling).
|
||||||
|
bool RemoveKillFlags;
|
||||||
|
|
||||||
/// The standard DAG builder does not normally include terminators as DAG
|
/// The standard DAG builder does not normally include terminators as DAG
|
||||||
/// nodes because it does not create the necessary dependencies to prevent
|
/// nodes because it does not create the necessary dependencies to prevent
|
||||||
/// reordering. A specialized scheduler can overide
|
/// reordering. A specialized scheduler can overide
|
||||||
@ -145,15 +149,21 @@ namespace llvm {
|
|||||||
DbgValueVector DbgValues;
|
DbgValueVector DbgValues;
|
||||||
MachineInstr *FirstDbgValue;
|
MachineInstr *FirstDbgValue;
|
||||||
|
|
||||||
|
/// Set of live physical registers for updating kill flags.
|
||||||
|
BitVector LiveRegs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ScheduleDAGInstrs(MachineFunction &mf,
|
explicit ScheduleDAGInstrs(MachineFunction &mf,
|
||||||
const MachineLoopInfo &mli,
|
const MachineLoopInfo &mli,
|
||||||
const MachineDominatorTree &mdt,
|
const MachineDominatorTree &mdt,
|
||||||
bool IsPostRAFlag,
|
bool IsPostRAFlag,
|
||||||
|
bool RemoveKillFlags = false,
|
||||||
LiveIntervals *LIS = 0);
|
LiveIntervals *LIS = 0);
|
||||||
|
|
||||||
virtual ~ScheduleDAGInstrs() {}
|
virtual ~ScheduleDAGInstrs() {}
|
||||||
|
|
||||||
|
bool isPostRA() const { return IsPostRA; }
|
||||||
|
|
||||||
/// \brief Expose LiveIntervals for use in DAG mutators and such.
|
/// \brief Expose LiveIntervals for use in DAG mutators and such.
|
||||||
LiveIntervals *getLIS() const { return LIS; }
|
LiveIntervals *getLIS() const { return LIS; }
|
||||||
|
|
||||||
@ -227,12 +237,23 @@ namespace llvm {
|
|||||||
/// Return a label for the region of code covered by the DAG.
|
/// Return a label for the region of code covered by the DAG.
|
||||||
virtual std::string getDAGName() const;
|
virtual std::string getDAGName() const;
|
||||||
|
|
||||||
|
/// \brief Fix register kill flags that scheduling has made invalid.
|
||||||
|
void fixupKills(MachineBasicBlock *MBB);
|
||||||
protected:
|
protected:
|
||||||
void initSUnits();
|
void initSUnits();
|
||||||
void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx);
|
void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx);
|
||||||
void addPhysRegDeps(SUnit *SU, unsigned OperIdx);
|
void addPhysRegDeps(SUnit *SU, unsigned OperIdx);
|
||||||
void addVRegDefDeps(SUnit *SU, unsigned OperIdx);
|
void addVRegDefDeps(SUnit *SU, unsigned OperIdx);
|
||||||
void addVRegUseDeps(SUnit *SU, unsigned OperIdx);
|
void addVRegUseDeps(SUnit *SU, unsigned OperIdx);
|
||||||
|
|
||||||
|
/// \brief PostRA helper for rewriting kill flags.
|
||||||
|
void startBlockForKills(MachineBasicBlock *BB);
|
||||||
|
|
||||||
|
/// \brief Toggle a register operand kill flag.
|
||||||
|
///
|
||||||
|
/// Other adjustments may be made to the instruction if necessary. Return
|
||||||
|
/// true if the operand has been deleted, false if not.
|
||||||
|
bool toggleKillFlag(MachineInstr *MI, MachineOperand &MO);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// newSUnit - Creates a new SUnit and return a ptr to it.
|
/// newSUnit - Creates a new SUnit and return a ptr to it.
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "llvm/CodeGen/MachineDominators.h"
|
#include "llvm/CodeGen/MachineDominators.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
||||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/RegisterClassInfo.h"
|
#include "llvm/CodeGen/RegisterClassInfo.h"
|
||||||
@ -121,9 +120,6 @@ namespace {
|
|||||||
/// AA - AliasAnalysis for making memory reference queries.
|
/// AA - AliasAnalysis for making memory reference queries.
|
||||||
AliasAnalysis *AA;
|
AliasAnalysis *AA;
|
||||||
|
|
||||||
/// LiveRegs - true if the register is live.
|
|
||||||
BitVector LiveRegs;
|
|
||||||
|
|
||||||
/// The schedule. Null SUnit*'s represent noop instructions.
|
/// The schedule. Null SUnit*'s represent noop instructions.
|
||||||
std::vector<SUnit*> Sequence;
|
std::vector<SUnit*> Sequence;
|
||||||
|
|
||||||
@ -174,11 +170,6 @@ namespace {
|
|||||||
///
|
///
|
||||||
void finishBlock();
|
void finishBlock();
|
||||||
|
|
||||||
/// FixupKills - Fix register kill flags that have been made
|
|
||||||
/// invalid due to scheduling
|
|
||||||
///
|
|
||||||
void FixupKills(MachineBasicBlock *MBB);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
|
void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
|
||||||
void ReleaseSuccessors(SUnit *SU);
|
void ReleaseSuccessors(SUnit *SU);
|
||||||
@ -186,11 +177,6 @@ namespace {
|
|||||||
void ListScheduleTopDown();
|
void ListScheduleTopDown();
|
||||||
void StartBlockForKills(MachineBasicBlock *BB);
|
void StartBlockForKills(MachineBasicBlock *BB);
|
||||||
|
|
||||||
// ToggleKillFlag - Toggle a register operand kill flag. Other
|
|
||||||
// adjustments may be made to the instruction if necessary. Return
|
|
||||||
// true if the operand has been deleted, false if not.
|
|
||||||
bool ToggleKillFlag(MachineInstr *MI, MachineOperand &MO);
|
|
||||||
|
|
||||||
void dumpSchedule() const;
|
void dumpSchedule() const;
|
||||||
void emitNoop(unsigned CurCycle);
|
void emitNoop(unsigned CurCycle);
|
||||||
};
|
};
|
||||||
@ -206,9 +192,8 @@ SchedulePostRATDList::SchedulePostRATDList(
|
|||||||
AliasAnalysis *AA, const RegisterClassInfo &RCI,
|
AliasAnalysis *AA, const RegisterClassInfo &RCI,
|
||||||
TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
|
TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
|
||||||
SmallVectorImpl<const TargetRegisterClass*> &CriticalPathRCs)
|
SmallVectorImpl<const TargetRegisterClass*> &CriticalPathRCs)
|
||||||
: ScheduleDAGInstrs(MF, MLI, MDT, /*IsPostRA=*/true), AA(AA),
|
: ScheduleDAGInstrs(MF, MLI, MDT, /*IsPostRA=*/true), AA(AA), EndIndex(0) {
|
||||||
LiveRegs(TRI->getNumRegs()), EndIndex(0)
|
|
||||||
{
|
|
||||||
const TargetMachine &TM = MF.getTarget();
|
const TargetMachine &TM = MF.getTarget();
|
||||||
const InstrItineraryData *InstrItins = TM.getInstrItineraryData();
|
const InstrItineraryData *InstrItins = TM.getInstrItineraryData();
|
||||||
HazardRec =
|
HazardRec =
|
||||||
@ -353,7 +338,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
Scheduler.finishBlock();
|
Scheduler.finishBlock();
|
||||||
|
|
||||||
// Update register kills
|
// Update register kills
|
||||||
Scheduler.FixupKills(MBB);
|
Scheduler.fixupKills(MBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -424,148 +409,6 @@ void SchedulePostRATDList::finishBlock() {
|
|||||||
ScheduleDAGInstrs::finishBlock();
|
ScheduleDAGInstrs::finishBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// StartBlockForKills - Initialize register live-range state for updating kills
|
|
||||||
///
|
|
||||||
void SchedulePostRATDList::StartBlockForKills(MachineBasicBlock *BB) {
|
|
||||||
// Start with no live registers.
|
|
||||||
LiveRegs.reset();
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
// Repeat, for reg and all subregs.
|
|
||||||
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
|
||||||
SubRegs.isValid(); ++SubRegs)
|
|
||||||
LiveRegs.set(*SubRegs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SchedulePostRATDList::ToggleKillFlag(MachineInstr *MI,
|
|
||||||
MachineOperand &MO) {
|
|
||||||
// Setting kill flag...
|
|
||||||
if (!MO.isKill()) {
|
|
||||||
MO.setIsKill(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If MO itself is live, clear the kill flag...
|
|
||||||
if (LiveRegs.test(MO.getReg())) {
|
|
||||||
MO.setIsKill(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any subreg of MO is live, then create an imp-def for that
|
|
||||||
// subreg and keep MO marked as killed.
|
|
||||||
MO.setIsKill(false);
|
|
||||||
bool AllDead = true;
|
|
||||||
const unsigned SuperReg = MO.getReg();
|
|
||||||
MachineInstrBuilder MIB(MF, MI);
|
|
||||||
for (MCSubRegIterator SubRegs(SuperReg, TRI); SubRegs.isValid(); ++SubRegs) {
|
|
||||||
if (LiveRegs.test(*SubRegs)) {
|
|
||||||
MIB.addReg(*SubRegs, RegState::ImplicitDefine);
|
|
||||||
AllDead = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(AllDead)
|
|
||||||
MO.setIsKill(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FixupKills - Fix the register kill flags, they may have been made
|
|
||||||
/// incorrect by instruction reordering.
|
|
||||||
///
|
|
||||||
void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) {
|
|
||||||
DEBUG(dbgs() << "Fixup kills for BB#" << MBB->getNumber() << '\n');
|
|
||||||
|
|
||||||
BitVector killedRegs(TRI->getNumRegs());
|
|
||||||
|
|
||||||
StartBlockForKills(MBB);
|
|
||||||
|
|
||||||
// Examine block from end to start...
|
|
||||||
unsigned Count = MBB->size();
|
|
||||||
for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin();
|
|
||||||
I != E; --Count) {
|
|
||||||
MachineInstr *MI = --I;
|
|
||||||
if (MI->isDebugValue())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Update liveness. Registers that are defed but not used in this
|
|
||||||
// instruction are now dead. Mark register and all subregs as they
|
|
||||||
// are completely defined.
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
|
||||||
MachineOperand &MO = MI->getOperand(i);
|
|
||||||
if (MO.isRegMask())
|
|
||||||
LiveRegs.clearBitsNotInMask(MO.getRegMask());
|
|
||||||
if (!MO.isReg()) continue;
|
|
||||||
unsigned Reg = MO.getReg();
|
|
||||||
if (Reg == 0) continue;
|
|
||||||
if (!MO.isDef()) continue;
|
|
||||||
// Ignore two-addr defs.
|
|
||||||
if (MI->isRegTiedToUseOperand(i)) continue;
|
|
||||||
|
|
||||||
// Repeat for reg and all subregs.
|
|
||||||
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
|
||||||
SubRegs.isValid(); ++SubRegs)
|
|
||||||
LiveRegs.reset(*SubRegs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Examine all used registers and set/clear kill flag. When a
|
|
||||||
// register is used multiple times we only set the kill flag on
|
|
||||||
// the first use. Don't set kill flags on undef operands.
|
|
||||||
killedRegs.reset();
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
|
||||||
MachineOperand &MO = MI->getOperand(i);
|
|
||||||
if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
|
|
||||||
unsigned Reg = MO.getReg();
|
|
||||||
if ((Reg == 0) || MRI.isReserved(Reg)) continue;
|
|
||||||
|
|
||||||
bool kill = false;
|
|
||||||
if (!killedRegs.test(Reg)) {
|
|
||||||
kill = true;
|
|
||||||
// A register is not killed if any subregs are live...
|
|
||||||
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
|
|
||||||
if (LiveRegs.test(*SubRegs)) {
|
|
||||||
kill = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If subreg is not live, then register is killed if it became
|
|
||||||
// live in this instruction
|
|
||||||
if (kill)
|
|
||||||
kill = !LiveRegs.test(Reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MO.isKill() != kill) {
|
|
||||||
DEBUG(dbgs() << "Fixing " << MO << " in ");
|
|
||||||
// Warning: ToggleKillFlag may invalidate MO.
|
|
||||||
ToggleKillFlag(MI, MO);
|
|
||||||
DEBUG(MI->dump());
|
|
||||||
}
|
|
||||||
|
|
||||||
killedRegs.set(Reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark any used register (that is not using undef) and subregs as
|
|
||||||
// now live...
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
|
||||||
MachineOperand &MO = MI->getOperand(i);
|
|
||||||
if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
|
|
||||||
unsigned Reg = MO.getReg();
|
|
||||||
if ((Reg == 0) || MRI.isReserved(Reg)) continue;
|
|
||||||
|
|
||||||
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
|
||||||
SubRegs.isValid(); ++SubRegs)
|
|
||||||
LiveRegs.set(*SubRegs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Top-Down Scheduling
|
// Top-Down Scheduling
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/PseudoSourceValue.h"
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
||||||
@ -48,9 +49,11 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf,
|
|||||||
const MachineLoopInfo &mli,
|
const MachineLoopInfo &mli,
|
||||||
const MachineDominatorTree &mdt,
|
const MachineDominatorTree &mdt,
|
||||||
bool IsPostRAFlag,
|
bool IsPostRAFlag,
|
||||||
|
bool RemoveKillFlags,
|
||||||
LiveIntervals *lis)
|
LiveIntervals *lis)
|
||||||
: ScheduleDAG(mf), MLI(mli), MDT(mdt), MFI(mf.getFrameInfo()), LIS(lis),
|
: ScheduleDAG(mf), MLI(mli), MDT(mdt), MFI(mf.getFrameInfo()), LIS(lis),
|
||||||
IsPostRA(IsPostRAFlag), CanHandleTerminators(false), FirstDbgValue(0) {
|
IsPostRA(IsPostRAFlag), RemoveKillFlags(RemoveKillFlags),
|
||||||
|
CanHandleTerminators(false), FirstDbgValue(0) {
|
||||||
assert((IsPostRA || LIS) && "PreRA scheduling requires LiveIntervals");
|
assert((IsPostRA || LIS) && "PreRA scheduling requires LiveIntervals");
|
||||||
DbgValues.clear();
|
DbgValues.clear();
|
||||||
assert(!(IsPostRA && MRI.getNumVirtRegs()) &&
|
assert(!(IsPostRA && MRI.getNumVirtRegs()) &&
|
||||||
@ -284,8 +287,8 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
|
|||||||
/// this SUnit to following instructions in the same scheduling region that
|
/// this SUnit to following instructions in the same scheduling region that
|
||||||
/// depend the physical register referenced at OperIdx.
|
/// depend the physical register referenced at OperIdx.
|
||||||
void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
|
void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
|
||||||
const MachineInstr *MI = SU->getInstr();
|
MachineInstr *MI = SU->getInstr();
|
||||||
const MachineOperand &MO = MI->getOperand(OperIdx);
|
MachineOperand &MO = MI->getOperand(OperIdx);
|
||||||
|
|
||||||
// Optionally add output and anti dependencies. For anti
|
// Optionally add output and anti dependencies. For anti
|
||||||
// dependencies we use a latency of 0 because for a multi-issue
|
// dependencies we use a latency of 0 because for a multi-issue
|
||||||
@ -323,6 +326,8 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
|
|||||||
// retrieve the existing SUnits list for this register's uses.
|
// retrieve the existing SUnits list for this register's uses.
|
||||||
// Push this SUnit on the use list.
|
// Push this SUnit on the use list.
|
||||||
Uses.insert(PhysRegSUOper(SU, OperIdx, MO.getReg()));
|
Uses.insert(PhysRegSUOper(SU, OperIdx, MO.getReg()));
|
||||||
|
if (RemoveKillFlags)
|
||||||
|
MO.setIsKill(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addPhysRegDataDeps(SU, OperIdx);
|
addPhysRegDataDeps(SU, OperIdx);
|
||||||
@ -1021,6 +1026,145 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
|
|||||||
PendingLoads.clear();
|
PendingLoads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Initialize register live-range state for updating kills.
|
||||||
|
void ScheduleDAGInstrs::startBlockForKills(MachineBasicBlock *BB) {
|
||||||
|
// Start with no live registers.
|
||||||
|
LiveRegs.reset();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// Repeat, for reg and all subregs.
|
||||||
|
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
||||||
|
SubRegs.isValid(); ++SubRegs)
|
||||||
|
LiveRegs.set(*SubRegs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScheduleDAGInstrs::toggleKillFlag(MachineInstr *MI, MachineOperand &MO) {
|
||||||
|
// Setting kill flag...
|
||||||
|
if (!MO.isKill()) {
|
||||||
|
MO.setIsKill(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If MO itself is live, clear the kill flag...
|
||||||
|
if (LiveRegs.test(MO.getReg())) {
|
||||||
|
MO.setIsKill(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any subreg of MO is live, then create an imp-def for that
|
||||||
|
// subreg and keep MO marked as killed.
|
||||||
|
MO.setIsKill(false);
|
||||||
|
bool AllDead = true;
|
||||||
|
const unsigned SuperReg = MO.getReg();
|
||||||
|
MachineInstrBuilder MIB(MF, MI);
|
||||||
|
for (MCSubRegIterator SubRegs(SuperReg, TRI); SubRegs.isValid(); ++SubRegs) {
|
||||||
|
if (LiveRegs.test(*SubRegs)) {
|
||||||
|
MIB.addReg(*SubRegs, RegState::ImplicitDefine);
|
||||||
|
AllDead = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(AllDead)
|
||||||
|
MO.setIsKill(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Reuse the LivePhysRegs utility for this.
|
||||||
|
void ScheduleDAGInstrs::fixupKills(MachineBasicBlock *MBB) {
|
||||||
|
DEBUG(dbgs() << "Fixup kills for BB#" << MBB->getNumber() << '\n');
|
||||||
|
|
||||||
|
LiveRegs.resize(TRI->getNumRegs());
|
||||||
|
BitVector killedRegs(TRI->getNumRegs());
|
||||||
|
|
||||||
|
startBlockForKills(MBB);
|
||||||
|
|
||||||
|
// Examine block from end to start...
|
||||||
|
unsigned Count = MBB->size();
|
||||||
|
for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin();
|
||||||
|
I != E; --Count) {
|
||||||
|
MachineInstr *MI = --I;
|
||||||
|
if (MI->isDebugValue())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update liveness. Registers that are defed but not used in this
|
||||||
|
// instruction are now dead. Mark register and all subregs as they
|
||||||
|
// are completely defined.
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (MO.isRegMask())
|
||||||
|
LiveRegs.clearBitsNotInMask(MO.getRegMask());
|
||||||
|
if (!MO.isReg()) continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (Reg == 0) continue;
|
||||||
|
if (!MO.isDef()) continue;
|
||||||
|
// Ignore two-addr defs.
|
||||||
|
if (MI->isRegTiedToUseOperand(i)) continue;
|
||||||
|
|
||||||
|
// Repeat for reg and all subregs.
|
||||||
|
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
||||||
|
SubRegs.isValid(); ++SubRegs)
|
||||||
|
LiveRegs.reset(*SubRegs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Examine all used registers and set/clear kill flag. When a
|
||||||
|
// register is used multiple times we only set the kill flag on
|
||||||
|
// the first use. Don't set kill flags on undef operands.
|
||||||
|
killedRegs.reset();
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if ((Reg == 0) || MRI.isReserved(Reg)) continue;
|
||||||
|
|
||||||
|
bool kill = false;
|
||||||
|
if (!killedRegs.test(Reg)) {
|
||||||
|
kill = true;
|
||||||
|
// A register is not killed if any subregs are live...
|
||||||
|
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
|
||||||
|
if (LiveRegs.test(*SubRegs)) {
|
||||||
|
kill = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If subreg is not live, then register is killed if it became
|
||||||
|
// live in this instruction
|
||||||
|
if (kill)
|
||||||
|
kill = !LiveRegs.test(Reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MO.isKill() != kill) {
|
||||||
|
DEBUG(dbgs() << "Fixing " << MO << " in ");
|
||||||
|
// Warning: toggleKillFlag may invalidate MO.
|
||||||
|
toggleKillFlag(MI, MO);
|
||||||
|
DEBUG(MI->dump());
|
||||||
|
}
|
||||||
|
|
||||||
|
killedRegs.set(Reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark any used register (that is not using undef) and subregs as
|
||||||
|
// now live...
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if ((Reg == 0) || MRI.isReserved(Reg)) continue;
|
||||||
|
|
||||||
|
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
|
||||||
|
SubRegs.isValid(); ++SubRegs)
|
||||||
|
LiveRegs.set(*SubRegs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
|
void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
|
||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||||
SU->getInstr()->dump();
|
SU->getInstr()->dump();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user