Skip to content

Commit 0c83424

Browse files
committed
Move GenericScheduler and PostGenericScheduler into a header.
These were not exposed previously because I didn't want out-of-tree targets to be too dependent on their internals. They can be reused for a very wide variety of processors with casual scheduling needs without exposing the classes by instead using hooks defined in MachineSchedPolicy (we can add more if needed). When targets are more aggressively tuned or want to provide custom heuristics, they can define their own MachineSchedStrategy. I tend to think this is better once you start customizing heuristics because you can copy over only what you need. I don't think that layering heuristics generally works well. However, Arch64 targets now want to reuse the Generic scheduling logic but also provide extensions. I don't see much harm in exposing the Generic scheduling classes with a major caveat: these scheduling strategies may change in the future without validating performance on less mainstream processors. If you want to be immune from changes, just define your own MachineSchedStrategy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210166 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e5d8481 commit 0c83424

File tree

2 files changed

+226
-229
lines changed

2 files changed

+226
-229
lines changed

include/llvm/CodeGen/MachineScheduler.h

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,217 @@ class SchedBoundary {
739739
#endif
740740
};
741741

742+
/// Base class for GenericScheduler. This class maintains information about
743+
/// scheduling candidates based on TargetSchedModel making it easy to implement
744+
/// heuristics for either preRA or postRA scheduling.
745+
class GenericSchedulerBase : public MachineSchedStrategy {
746+
public:
747+
/// Represent the type of SchedCandidate found within a single queue.
748+
/// pickNodeBidirectional depends on these listed by decreasing priority.
749+
enum CandReason {
750+
NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax,
751+
ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
752+
TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
753+
754+
#ifndef NDEBUG
755+
static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
756+
#endif
757+
758+
/// Policy for scheduling the next instruction in the candidate's zone.
759+
struct CandPolicy {
760+
bool ReduceLatency;
761+
unsigned ReduceResIdx;
762+
unsigned DemandResIdx;
763+
764+
CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {}
765+
};
766+
767+
/// Status of an instruction's critical resource consumption.
768+
struct SchedResourceDelta {
769+
// Count critical resources in the scheduled region required by SU.
770+
unsigned CritResources;
771+
772+
// Count critical resources from another region consumed by SU.
773+
unsigned DemandedResources;
774+
775+
SchedResourceDelta(): CritResources(0), DemandedResources(0) {}
776+
777+
bool operator==(const SchedResourceDelta &RHS) const {
778+
return CritResources == RHS.CritResources
779+
&& DemandedResources == RHS.DemandedResources;
780+
}
781+
bool operator!=(const SchedResourceDelta &RHS) const {
782+
return !operator==(RHS);
783+
}
784+
};
785+
786+
/// Store the state used by GenericScheduler heuristics, required for the
787+
/// lifetime of one invocation of pickNode().
788+
struct SchedCandidate {
789+
CandPolicy Policy;
790+
791+
// The best SUnit candidate.
792+
SUnit *SU;
793+
794+
// The reason for this candidate.
795+
CandReason Reason;
796+
797+
// Set of reasons that apply to multiple candidates.
798+
uint32_t RepeatReasonSet;
799+
800+
// Register pressure values for the best candidate.
801+
RegPressureDelta RPDelta;
802+
803+
// Critical resource consumption of the best candidate.
804+
SchedResourceDelta ResDelta;
805+
806+
SchedCandidate(const CandPolicy &policy)
807+
: Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {}
808+
809+
bool isValid() const { return SU; }
810+
811+
// Copy the status of another candidate without changing policy.
812+
void setBest(SchedCandidate &Best) {
813+
assert(Best.Reason != NoCand && "uninitialized Sched candidate");
814+
SU = Best.SU;
815+
Reason = Best.Reason;
816+
RPDelta = Best.RPDelta;
817+
ResDelta = Best.ResDelta;
818+
}
819+
820+
bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); }
821+
void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); }
822+
823+
void initResourceDelta(const ScheduleDAGMI *DAG,
824+
const TargetSchedModel *SchedModel);
825+
};
826+
827+
protected:
828+
const MachineSchedContext *Context;
829+
const TargetSchedModel *SchedModel;
830+
const TargetRegisterInfo *TRI;
831+
832+
SchedRemainder Rem;
833+
protected:
834+
GenericSchedulerBase(const MachineSchedContext *C):
835+
Context(C), SchedModel(nullptr), TRI(nullptr) {}
836+
837+
void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
838+
SchedBoundary *OtherZone);
839+
840+
#ifndef NDEBUG
841+
void traceCandidate(const SchedCandidate &Cand);
842+
#endif
843+
};
844+
845+
/// GenericScheduler shrinks the unscheduled zone using heuristics to balance
846+
/// the schedule.
847+
class GenericScheduler : public GenericSchedulerBase {
848+
ScheduleDAGMILive *DAG;
849+
850+
// State of the top and bottom scheduled instruction boundaries.
851+
SchedBoundary Top;
852+
SchedBoundary Bot;
853+
854+
MachineSchedPolicy RegionPolicy;
855+
public:
856+
GenericScheduler(const MachineSchedContext *C):
857+
GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"),
858+
Bot(SchedBoundary::BotQID, "BotQ") {}
859+
860+
void initPolicy(MachineBasicBlock::iterator Begin,
861+
MachineBasicBlock::iterator End,
862+
unsigned NumRegionInstrs) override;
863+
864+
bool shouldTrackPressure() const override {
865+
return RegionPolicy.ShouldTrackPressure;
866+
}
867+
868+
void initialize(ScheduleDAGMI *dag) override;
869+
870+
SUnit *pickNode(bool &IsTopNode) override;
871+
872+
void schedNode(SUnit *SU, bool IsTopNode) override;
873+
874+
void releaseTopNode(SUnit *SU) override {
875+
Top.releaseTopNode(SU);
876+
}
877+
878+
void releaseBottomNode(SUnit *SU) override {
879+
Bot.releaseBottomNode(SU);
880+
}
881+
882+
void registerRoots() override;
883+
884+
protected:
885+
void checkAcyclicLatency();
886+
887+
void tryCandidate(SchedCandidate &Cand,
888+
SchedCandidate &TryCand,
889+
SchedBoundary &Zone,
890+
const RegPressureTracker &RPTracker,
891+
RegPressureTracker &TempTracker);
892+
893+
SUnit *pickNodeBidirectional(bool &IsTopNode);
894+
895+
void pickNodeFromQueue(SchedBoundary &Zone,
896+
const RegPressureTracker &RPTracker,
897+
SchedCandidate &Candidate);
898+
899+
void reschedulePhysRegCopies(SUnit *SU, bool isTop);
900+
};
901+
902+
/// PostGenericScheduler - Interface to the scheduling algorithm used by
903+
/// ScheduleDAGMI.
904+
///
905+
/// Callbacks from ScheduleDAGMI:
906+
/// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ...
907+
class PostGenericScheduler : public GenericSchedulerBase {
908+
ScheduleDAGMI *DAG;
909+
SchedBoundary Top;
910+
SmallVector<SUnit*, 8> BotRoots;
911+
public:
912+
PostGenericScheduler(const MachineSchedContext *C):
913+
GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {}
914+
915+
virtual ~PostGenericScheduler() {}
916+
917+
void initPolicy(MachineBasicBlock::iterator Begin,
918+
MachineBasicBlock::iterator End,
919+
unsigned NumRegionInstrs) override {
920+
/* no configurable policy */
921+
};
922+
923+
/// PostRA scheduling does not track pressure.
924+
bool shouldTrackPressure() const override { return false; }
925+
926+
void initialize(ScheduleDAGMI *Dag) override;
927+
928+
void registerRoots() override;
929+
930+
SUnit *pickNode(bool &IsTopNode) override;
931+
932+
void scheduleTree(unsigned SubtreeID) override {
933+
llvm_unreachable("PostRA scheduler does not support subtree analysis.");
934+
}
935+
936+
void schedNode(SUnit *SU, bool IsTopNode) override;
937+
938+
void releaseTopNode(SUnit *SU) override {
939+
Top.releaseTopNode(SU);
940+
}
941+
942+
// Only called for roots.
943+
void releaseBottomNode(SUnit *SU) override {
944+
BotRoots.push_back(SU);
945+
}
946+
947+
protected:
948+
void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
949+
950+
void pickNodeFromQueue(SchedCandidate &Cand);
951+
};
952+
742953
} // namespace llvm
743954

744955
#endif

0 commit comments

Comments
 (0)