//==- 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