1//===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the class GCNIterativeScheduler, which uses an iterative
11/// approach to find a best schedule for GCN architecture. It basically makes
12/// use of various lightweight schedules, scores them, chooses best one based on
13/// their scores, and finally implements the chosen one.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
18#define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
19
20#include "GCNRegPressure.h"
21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/CodeGen/MachineBasicBlock.h"
23#include "llvm/CodeGen/MachineScheduler.h"
24#include "llvm/Support/Allocator.h"
25#include <limits>
26#include <memory>
27#include <vector>
28
29namespace llvm {
30
31class MachineInstr;
32class SUnit;
33class raw_ostream;
34
35class GCNIterativeScheduler : public ScheduleDAGMILive {
36  using BaseClass = ScheduleDAGMILive;
37
38public:
39  enum StrategyKind {
40    SCHEDULE_MINREGONLY,
41    SCHEDULE_MINREGFORCED,
42    SCHEDULE_LEGACYMAXOCCUPANCY,
43    SCHEDULE_ILP
44  };
45
46  GCNIterativeScheduler(MachineSchedContext *C,
47                        StrategyKind S);
48
49  void schedule() override;
50
51  void enterRegion(MachineBasicBlock *BB,
52                   MachineBasicBlock::iterator Begin,
53                   MachineBasicBlock::iterator End,
54                   unsigned RegionInstrs) override;
55
56  void finalizeSchedule() override;
57
58protected:
59  using ScheduleRef = ArrayRef<const SUnit *>;
60
61  struct TentativeSchedule {
62    std::vector<MachineInstr *> Schedule;
63    GCNRegPressure MaxPressure;
64  };
65
66  struct Region {
67    // Fields except for BestSchedule are supposed to reflect current IR state
68    // `const` fields are to emphasize they shouldn't change for any schedule.
69    MachineBasicBlock::iterator Begin;
70    // End is either a boundary instruction or end of basic block
71    const MachineBasicBlock::iterator End;
72    const unsigned NumRegionInstrs;
73    GCNRegPressure MaxPressure;
74
75    // best schedule for the region so far (not scheduled yet)
76    std::unique_ptr<TentativeSchedule> BestSchedule;
77  };
78
79  SpecificBumpPtrAllocator<Region> Alloc;
80  std::vector<Region*> Regions;
81
82  MachineSchedContext *Context;
83  const StrategyKind Strategy;
84  mutable GCNUpwardRPTracker UPTracker;
85
86  class BuildDAG;
87  class OverrideLegacyStrategy;
88
89  template <typename Range>
90  GCNRegPressure getSchedulePressure(const Region &R,
91                                     Range &&Schedule) const;
92
93  GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin,
94                                   MachineBasicBlock::iterator End) const;
95
96  GCNRegPressure getRegionPressure(const Region &R) const {
97    return getRegionPressure(R.Begin, R.End);
98  }
99
100  void setBestSchedule(Region &R,
101                       ScheduleRef Schedule,
102                       const GCNRegPressure &MaxRP = GCNRegPressure());
103
104  void scheduleBest(Region &R);
105
106  std::vector<MachineInstr*> detachSchedule(ScheduleRef Schedule) const;
107
108  void sortRegionsByPressure(unsigned TargetOcc);
109
110  template <typename Range>
111  void scheduleRegion(Region &R, Range &&Schedule,
112                      const GCNRegPressure &MaxRP = GCNRegPressure());
113
114  unsigned tryMaximizeOccupancy(unsigned TargetOcc =
115                                std::numeric_limits<unsigned>::max());
116
117  void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true);
118  void scheduleMinReg(bool force = false);
119  void scheduleILP(bool TryMaximizeOccupancy = true);
120
121  void printRegions(raw_ostream &OS) const;
122  void printSchedResult(raw_ostream &OS,
123                        const Region *R,
124                        const GCNRegPressure &RP) const;
125  void printSchedRP(raw_ostream &OS,
126                    const GCNRegPressure &Before,
127                    const GCNRegPressure &After) const;
128};
129
130} // end namespace llvm
131
132#endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
133