blob: c0228540b7a2fe6893e8dfc42f2c58b5db59c866 [file] [log] [blame]
//===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the class GCNIterativeScheduler, which uses an iterative
/// approach to find a best schedule for GCN architecture. It basically makes
/// use of various lightweight schedules, scores them, chooses best one based on
/// their scores, and finally implements the chosen one.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
#define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
#include "GCNRegPressure.h"
#include "llvm/CodeGen/MachineScheduler.h"
namespace llvm {
class MachineInstr;
class SUnit;
class raw_ostream;
class GCNIterativeScheduler : public ScheduleDAGMILive {
using BaseClass = ScheduleDAGMILive;
public:
enum StrategyKind {
SCHEDULE_MINREGONLY,
SCHEDULE_MINREGFORCED,
SCHEDULE_LEGACYMAXOCCUPANCY,
SCHEDULE_ILP
};
GCNIterativeScheduler(MachineSchedContext *C,
StrategyKind S);
void schedule() override;
void enterRegion(MachineBasicBlock *BB,
MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
unsigned RegionInstrs) override;
void finalizeSchedule() override;
protected:
using ScheduleRef = ArrayRef<const SUnit *>;
struct TentativeSchedule {
std::vector<MachineInstr *> Schedule;
GCNRegPressure MaxPressure;
};
struct Region {
// Fields except for BestSchedule are supposed to reflect current IR state
// `const` fields are to emphasize they shouldn't change for any schedule.
MachineBasicBlock::iterator Begin;
// End is either a boundary instruction or end of basic block
const MachineBasicBlock::iterator End;
const unsigned NumRegionInstrs;
GCNRegPressure MaxPressure;
// best schedule for the region so far (not scheduled yet)
std::unique_ptr<TentativeSchedule> BestSchedule;
};
SpecificBumpPtrAllocator<Region> Alloc;
std::vector<Region*> Regions;
MachineSchedContext *Context;
const StrategyKind Strategy;
mutable GCNUpwardRPTracker UPTracker;
class BuildDAG;
class OverrideLegacyStrategy;
template <typename Range>
GCNRegPressure getSchedulePressure(const Region &R,
Range &&Schedule) const;
GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End) const;
GCNRegPressure getRegionPressure(const Region &R) const {
return getRegionPressure(R.Begin, R.End);
}
void setBestSchedule(Region &R,
ScheduleRef Schedule,
const GCNRegPressure &MaxRP = GCNRegPressure());
void scheduleBest(Region &R);
std::vector<MachineInstr*> detachSchedule(ScheduleRef Schedule) const;
void sortRegionsByPressure(unsigned TargetOcc);
template <typename Range>
void scheduleRegion(Region &R, Range &&Schedule,
const GCNRegPressure &MaxRP = GCNRegPressure());
unsigned tryMaximizeOccupancy(unsigned TargetOcc =
std::numeric_limits<unsigned>::max());
void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true);
void scheduleMinReg(bool force = false);
void scheduleILP(bool TryMaximizeOccupancy = true);
void printRegions(raw_ostream &OS) const;
void printSchedResult(raw_ostream &OS,
const Region *R,
const GCNRegPressure &RP) const;
void printSchedRP(raw_ostream &OS,
const GCNRegPressure &Before,
const GCNRegPressure &After) const;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H