forked from OSchip/llvm-project
misched: Target-independent support for MacroFusion.
Uses the infrastructure from r167742 to support clustering instructure that the target processor can "fuse". e.g. cmp+jmp. Next step: target hook implementations with test cases, and enable. llvm-svn: 167744
This commit is contained in:
parent
f8326b6052
commit
263280248a
|
@ -634,6 +634,13 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Can this target fuse the given instructions if they are scheduled
|
||||
/// adjacent.
|
||||
virtual bool shouldScheduleAdjacent(MachineInstr* First,
|
||||
MachineInstr *Second) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ReverseBranchCondition - Reverses the branch condition of the specified
|
||||
/// condition list, returning false on success and true if it cannot be
|
||||
/// reversed.
|
||||
|
|
|
@ -62,6 +62,10 @@ static cl::opt<unsigned> ILPWindow("ilp-window", cl::Hidden,
|
|||
static cl::opt<bool> EnableLoadCluster("misched-cluster", cl::Hidden,
|
||||
cl::desc("Enable load clustering."));
|
||||
|
||||
// Experimental heuristics
|
||||
static cl::opt<bool> EnableMacroFusion("misched-fusion", cl::Hidden,
|
||||
cl::desc("Enable scheduling for macro fusion."));
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Machine Instruction Scheduling Pass and Registry
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -308,11 +312,13 @@ void ReadyQueue::dump() {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool ScheduleDAGMI::addEdge(SUnit *SuccSU, const SDep &PredDep) {
|
||||
// Do not use WillCreateCycle, it assumes SD scheduling.
|
||||
// If Pred is reachable from Succ, then the edge creates a cycle.
|
||||
if (Topo.IsReachable(PredDep.getSUnit(), SuccSU))
|
||||
return false;
|
||||
Topo.AddPred(SuccSU, PredDep.getSUnit());
|
||||
if (SuccSU != &ExitSU) {
|
||||
// Do not use WillCreateCycle, it assumes SD scheduling.
|
||||
// If Pred is reachable from Succ, then the edge creates a cycle.
|
||||
if (Topo.IsReachable(PredDep.getSUnit(), SuccSU))
|
||||
return false;
|
||||
Topo.AddPred(SuccSU, PredDep.getSUnit());
|
||||
}
|
||||
SuccSU->addPred(PredDep, /*Required=*/!PredDep.isArtificial());
|
||||
// Return true regardless of whether a new edge needed to be inserted.
|
||||
return true;
|
||||
|
@ -687,6 +693,10 @@ void ScheduleDAGMI::dumpSchedule() const {
|
|||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// LoadClusterMutation - DAG post-processing to cluster loads.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
/// \brief Post-process the DAG to create cluster edges between neighboring
|
||||
/// loads.
|
||||
|
@ -800,6 +810,50 @@ void LoadClusterMutation::apply(ScheduleDAGMI *DAG) {
|
|||
clusterNeighboringLoads(StoreChainDependents[Idx], DAG);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MacroFusion - DAG post-processing to encourage fusion of macro ops.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
/// \brief Post-process the DAG to create cluster edges between instructions
|
||||
/// that may be fused by the processor into a single operation.
|
||||
class MacroFusion : public ScheduleDAGMutation {
|
||||
const TargetInstrInfo *TII;
|
||||
public:
|
||||
MacroFusion(const TargetInstrInfo *tii): TII(tii) {}
|
||||
|
||||
virtual void apply(ScheduleDAGMI *DAG);
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
/// \brief Callback from DAG postProcessing to create cluster edges to encourage
|
||||
/// fused operations.
|
||||
void MacroFusion::apply(ScheduleDAGMI *DAG) {
|
||||
// For now, assume targets can only fuse with the branch.
|
||||
MachineInstr *Branch = DAG->ExitSU.getInstr();
|
||||
if (!Branch)
|
||||
return;
|
||||
|
||||
for (unsigned Idx = DAG->SUnits.size(); Idx > 0;) {
|
||||
SUnit *SU = &DAG->SUnits[--Idx];
|
||||
if (!TII->shouldScheduleAdjacent(SU->getInstr(), Branch))
|
||||
continue;
|
||||
|
||||
// Create a single weak edge from SU to ExitSU. The only effect is to cause
|
||||
// bottom-up scheduling to heavily prioritize the clustered SU. There is no
|
||||
// need to copy predecessor edges from ExitSU to SU, since top-down
|
||||
// scheduling cannot prioritize ExitSU anyway. To defer top-down scheduling
|
||||
// of SU, we could create an artificial edge from the deepest root, but it
|
||||
// hasn't been needed yet.
|
||||
bool Success = DAG->addEdge(&DAG->ExitSU, SDep(SU, SDep::Cluster));
|
||||
(void)Success;
|
||||
assert(Success && "No DAG nodes should be reachable from ExitSU");
|
||||
|
||||
DEBUG(dbgs() << "Macro Fuse SU(" << SU->NodeNum << ")\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConvergingScheduler - Implementation of the standard MachineSchedStrategy.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1986,6 +2040,8 @@ static ScheduleDAGInstrs *createConvergingSched(MachineSchedContext *C) {
|
|||
// Register DAG post-processors.
|
||||
if (EnableLoadCluster)
|
||||
DAG->addMutation(new LoadClusterMutation(DAG->TII, DAG->TRI));
|
||||
if (EnableMacroFusion)
|
||||
DAG->addMutation(new MacroFusion(DAG->TII));
|
||||
return DAG;
|
||||
}
|
||||
static MachineSchedRegistry
|
||||
|
|
Loading…
Reference in New Issue