xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNIterativeScheduler.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric ///
9*5ffd83dbSDimitry Andric /// \file
10*5ffd83dbSDimitry Andric /// This file defines the class GCNIterativeScheduler, which uses an iterative
11*5ffd83dbSDimitry Andric /// approach to find a best schedule for GCN architecture. It basically makes
12*5ffd83dbSDimitry Andric /// use of various lightweight schedules, scores them, chooses best one based on
13*5ffd83dbSDimitry Andric /// their scores, and finally implements the chosen one.
14*5ffd83dbSDimitry Andric ///
15*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
180b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "GCNRegPressure.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace llvm {
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric class MachineInstr;
260b57cec5SDimitry Andric class SUnit;
270b57cec5SDimitry Andric class raw_ostream;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class GCNIterativeScheduler : public ScheduleDAGMILive {
300b57cec5SDimitry Andric   using BaseClass = ScheduleDAGMILive;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric public:
330b57cec5SDimitry Andric   enum StrategyKind {
340b57cec5SDimitry Andric     SCHEDULE_MINREGONLY,
350b57cec5SDimitry Andric     SCHEDULE_MINREGFORCED,
360b57cec5SDimitry Andric     SCHEDULE_LEGACYMAXOCCUPANCY,
370b57cec5SDimitry Andric     SCHEDULE_ILP
380b57cec5SDimitry Andric   };
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   GCNIterativeScheduler(MachineSchedContext *C,
410b57cec5SDimitry Andric                         StrategyKind S);
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   void schedule() override;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   void enterRegion(MachineBasicBlock *BB,
460b57cec5SDimitry Andric                    MachineBasicBlock::iterator Begin,
470b57cec5SDimitry Andric                    MachineBasicBlock::iterator End,
480b57cec5SDimitry Andric                    unsigned RegionInstrs) override;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   void finalizeSchedule() override;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric protected:
530b57cec5SDimitry Andric   using ScheduleRef = ArrayRef<const SUnit *>;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   struct TentativeSchedule {
560b57cec5SDimitry Andric     std::vector<MachineInstr *> Schedule;
570b57cec5SDimitry Andric     GCNRegPressure MaxPressure;
580b57cec5SDimitry Andric   };
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   struct Region {
610b57cec5SDimitry Andric     // Fields except for BestSchedule are supposed to reflect current IR state
620b57cec5SDimitry Andric     // `const` fields are to emphasize they shouldn't change for any schedule.
630b57cec5SDimitry Andric     MachineBasicBlock::iterator Begin;
640b57cec5SDimitry Andric     // End is either a boundary instruction or end of basic block
650b57cec5SDimitry Andric     const MachineBasicBlock::iterator End;
660b57cec5SDimitry Andric     const unsigned NumRegionInstrs;
670b57cec5SDimitry Andric     GCNRegPressure MaxPressure;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     // best schedule for the region so far (not scheduled yet)
700b57cec5SDimitry Andric     std::unique_ptr<TentativeSchedule> BestSchedule;
710b57cec5SDimitry Andric   };
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   SpecificBumpPtrAllocator<Region> Alloc;
740b57cec5SDimitry Andric   std::vector<Region*> Regions;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   MachineSchedContext *Context;
770b57cec5SDimitry Andric   const StrategyKind Strategy;
780b57cec5SDimitry Andric   mutable GCNUpwardRPTracker UPTracker;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   class BuildDAG;
810b57cec5SDimitry Andric   class OverrideLegacyStrategy;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   template <typename Range>
840b57cec5SDimitry Andric   GCNRegPressure getSchedulePressure(const Region &R,
850b57cec5SDimitry Andric                                      Range &&Schedule) const;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin,
880b57cec5SDimitry Andric                                    MachineBasicBlock::iterator End) const;
890b57cec5SDimitry Andric 
getRegionPressure(const Region & R)900b57cec5SDimitry Andric   GCNRegPressure getRegionPressure(const Region &R) const {
910b57cec5SDimitry Andric     return getRegionPressure(R.Begin, R.End);
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   void setBestSchedule(Region &R,
950b57cec5SDimitry Andric                        ScheduleRef Schedule,
960b57cec5SDimitry Andric                        const GCNRegPressure &MaxRP = GCNRegPressure());
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   void scheduleBest(Region &R);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   std::vector<MachineInstr*> detachSchedule(ScheduleRef Schedule) const;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   void sortRegionsByPressure(unsigned TargetOcc);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   template <typename Range>
1050b57cec5SDimitry Andric   void scheduleRegion(Region &R, Range &&Schedule,
1060b57cec5SDimitry Andric                       const GCNRegPressure &MaxRP = GCNRegPressure());
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   unsigned tryMaximizeOccupancy(unsigned TargetOcc =
1090b57cec5SDimitry Andric                                 std::numeric_limits<unsigned>::max());
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true);
1120b57cec5SDimitry Andric   void scheduleMinReg(bool force = false);
1130b57cec5SDimitry Andric   void scheduleILP(bool TryMaximizeOccupancy = true);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   void printRegions(raw_ostream &OS) const;
1160b57cec5SDimitry Andric   void printSchedResult(raw_ostream &OS,
1170b57cec5SDimitry Andric                         const Region *R,
1180b57cec5SDimitry Andric                         const GCNRegPressure &RP) const;
1190b57cec5SDimitry Andric   void printSchedRP(raw_ostream &OS,
1200b57cec5SDimitry Andric                     const GCNRegPressure &Before,
1210b57cec5SDimitry Andric                     const GCNRegPressure &After) const;
1220b57cec5SDimitry Andric };
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric } // end namespace llvm
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H
127