156 lines
5.1 KiB
C
156 lines
5.1 KiB
C
|
//==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- C++ -*-==//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// -------------------------- Post RA scheduling ---------------------------- //
|
||
|
// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
|
||
|
// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
|
||
|
// implementation that looks to optimize decoder grouping and balance the
|
||
|
// usage of processor resources. Scheduler states are saved for the end
|
||
|
// region of each MBB, so that a successor block can learn from it.
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "SystemZHazardRecognizer.h"
|
||
|
#include "llvm/CodeGen/MachineScheduler.h"
|
||
|
#include "llvm/CodeGen/ScheduleDAG.h"
|
||
|
#include <set>
|
||
|
|
||
|
#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
|
||
|
#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
namespace llvm {
|
||
|
|
||
|
/// A MachineSchedStrategy implementation for SystemZ post RA scheduling.
|
||
|
class SystemZPostRASchedStrategy : public MachineSchedStrategy {
|
||
|
|
||
|
const MachineLoopInfo *MLI;
|
||
|
const SystemZInstrInfo *TII;
|
||
|
|
||
|
// A SchedModel is needed before any DAG is built while advancing past
|
||
|
// non-scheduled instructions, so it would not always be possible to call
|
||
|
// DAG->getSchedClass(SU).
|
||
|
TargetSchedModel SchedModel;
|
||
|
|
||
|
/// A candidate during instruction evaluation.
|
||
|
struct Candidate {
|
||
|
SUnit *SU = nullptr;
|
||
|
|
||
|
/// The decoding cost.
|
||
|
int GroupingCost = 0;
|
||
|
|
||
|
/// The processor resources cost.
|
||
|
int ResourcesCost = 0;
|
||
|
|
||
|
Candidate() = default;
|
||
|
Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec);
|
||
|
|
||
|
// Compare two candidates.
|
||
|
bool operator<(const Candidate &other);
|
||
|
|
||
|
// Check if this node is free of cost ("as good as any").
|
||
|
bool noCost() const {
|
||
|
return (GroupingCost <= 0 && !ResourcesCost);
|
||
|
}
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
void dumpCosts() {
|
||
|
if (GroupingCost != 0)
|
||
|
dbgs() << " Grouping cost:" << GroupingCost;
|
||
|
if (ResourcesCost != 0)
|
||
|
dbgs() << " Resource cost:" << ResourcesCost;
|
||
|
}
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
// A sorter for the Available set that makes sure that SUs are considered
|
||
|
// in the best order.
|
||
|
struct SUSorter {
|
||
|
bool operator() (SUnit *lhs, SUnit *rhs) const {
|
||
|
if (lhs->isScheduleHigh && !rhs->isScheduleHigh)
|
||
|
return true;
|
||
|
if (!lhs->isScheduleHigh && rhs->isScheduleHigh)
|
||
|
return false;
|
||
|
|
||
|
if (lhs->getHeight() > rhs->getHeight())
|
||
|
return true;
|
||
|
else if (lhs->getHeight() < rhs->getHeight())
|
||
|
return false;
|
||
|
|
||
|
return (lhs->NodeNum < rhs->NodeNum);
|
||
|
}
|
||
|
};
|
||
|
// A set of SUs with a sorter and dump method.
|
||
|
struct SUSet : std::set<SUnit*, SUSorter> {
|
||
|
#ifndef NDEBUG
|
||
|
void dump(SystemZHazardRecognizer &HazardRec) const;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
/// The set of available SUs to schedule next.
|
||
|
SUSet Available;
|
||
|
|
||
|
/// Current MBB
|
||
|
MachineBasicBlock *MBB;
|
||
|
|
||
|
/// Maintain hazard recognizers for all blocks, so that the scheduler state
|
||
|
/// can be maintained past BB boundaries when appropariate.
|
||
|
typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec;
|
||
|
MBB2HazRec SchedStates;
|
||
|
|
||
|
/// Pointer to the HazardRecognizer that tracks the scheduler state for
|
||
|
/// the current region.
|
||
|
SystemZHazardRecognizer *HazardRec;
|
||
|
|
||
|
/// Update the scheduler state by emitting (non-scheduled) instructions
|
||
|
/// up to, but not including, NextBegin.
|
||
|
void advanceTo(MachineBasicBlock::iterator NextBegin);
|
||
|
|
||
|
public:
|
||
|
SystemZPostRASchedStrategy(const MachineSchedContext *C);
|
||
|
virtual ~SystemZPostRASchedStrategy();
|
||
|
|
||
|
/// Called for a region before scheduling.
|
||
|
void initPolicy(MachineBasicBlock::iterator Begin,
|
||
|
MachineBasicBlock::iterator End,
|
||
|
unsigned NumRegionInstrs) override;
|
||
|
|
||
|
/// PostRA scheduling does not track pressure.
|
||
|
bool shouldTrackPressure() const override { return false; }
|
||
|
|
||
|
// Process scheduling regions top-down so that scheduler states can be
|
||
|
// transferrred over scheduling boundaries.
|
||
|
bool doMBBSchedRegionsTopDown() const override { return true; }
|
||
|
|
||
|
void initialize(ScheduleDAGMI *dag) override;
|
||
|
|
||
|
/// Tell the strategy that MBB is about to be processed.
|
||
|
void enterMBB(MachineBasicBlock *NextMBB) override;
|
||
|
|
||
|
/// Tell the strategy that current MBB is done.
|
||
|
void leaveMBB() override;
|
||
|
|
||
|
/// Pick the next node to schedule, or return NULL.
|
||
|
SUnit *pickNode(bool &IsTopNode) override;
|
||
|
|
||
|
/// ScheduleDAGMI has scheduled an instruction - tell HazardRec
|
||
|
/// about it.
|
||
|
void schedNode(SUnit *SU, bool IsTopNode) override;
|
||
|
|
||
|
/// SU has had all predecessor dependencies resolved. Put it into
|
||
|
/// Available.
|
||
|
void releaseTopNode(SUnit *SU) override;
|
||
|
|
||
|
/// Currently only scheduling top-down, so this method is empty.
|
||
|
void releaseBottomNode(SUnit *SU) override {};
|
||
|
};
|
||
|
|
||
|
} // end namespace llvm
|
||
|
|
||
|
#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
|