xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/ScheduleDFS.h (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
10b57cec5SDimitry Andric //===- ScheduleDFS.h - ILP metric for ScheduleDAGInstrs ---------*- 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 //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Definition of an ILP metric for machine level instruction scheduling.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CODEGEN_SCHEDULEDFS_H
140b57cec5SDimitry Andric #define LLVM_CODEGEN_SCHEDULEDFS_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
180b57cec5SDimitry Andric #include <cassert>
190b57cec5SDimitry Andric #include <cstdint>
200b57cec5SDimitry Andric #include <vector>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace llvm {
230b57cec5SDimitry Andric 
24*5ffd83dbSDimitry Andric template <typename T> class ArrayRef;
250b57cec5SDimitry Andric class raw_ostream;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric /// Represent the ILP of the subDAG rooted at a DAG node.
280b57cec5SDimitry Andric ///
290b57cec5SDimitry Andric /// ILPValues summarize the DAG subtree rooted at each node. ILPValues are
300b57cec5SDimitry Andric /// valid for all nodes regardless of their subtree membership.
310b57cec5SDimitry Andric ///
320b57cec5SDimitry Andric /// When computed using bottom-up DFS, this metric assumes that the DAG is a
330b57cec5SDimitry Andric /// forest of trees with roots at the bottom of the schedule branching upward.
340b57cec5SDimitry Andric struct ILPValue {
350b57cec5SDimitry Andric   unsigned InstrCount;
360b57cec5SDimitry Andric   /// Length may either correspond to depth or height, depending on direction,
370b57cec5SDimitry Andric   /// and cycles or nodes depending on context.
380b57cec5SDimitry Andric   unsigned Length;
390b57cec5SDimitry Andric 
ILPValueILPValue400b57cec5SDimitry Andric   ILPValue(unsigned count, unsigned length):
410b57cec5SDimitry Andric     InstrCount(count), Length(length) {}
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // Order by the ILP metric's value.
440b57cec5SDimitry Andric   bool operator<(ILPValue RHS) const {
450b57cec5SDimitry Andric     return (uint64_t)InstrCount * RHS.Length
460b57cec5SDimitry Andric       < (uint64_t)Length * RHS.InstrCount;
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric   bool operator>(ILPValue RHS) const {
490b57cec5SDimitry Andric     return RHS < *this;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   bool operator<=(ILPValue RHS) const {
520b57cec5SDimitry Andric     return (uint64_t)InstrCount * RHS.Length
530b57cec5SDimitry Andric       <= (uint64_t)Length * RHS.InstrCount;
540b57cec5SDimitry Andric   }
550b57cec5SDimitry Andric   bool operator>=(ILPValue RHS) const {
560b57cec5SDimitry Andric     return RHS <= *this;
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   void print(raw_ostream &OS) const;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   void dump() const;
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric /// Compute the values of each DAG node for various metrics during DFS.
650b57cec5SDimitry Andric class SchedDFSResult {
660b57cec5SDimitry Andric   friend class SchedDFSImpl;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   static const unsigned InvalidSubtreeID = ~0u;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   /// Per-SUnit data computed during DFS for various metrics.
710b57cec5SDimitry Andric   ///
720b57cec5SDimitry Andric   /// A node's SubtreeID is set to itself when it is visited to indicate that it
730b57cec5SDimitry Andric   /// is the root of a subtree. Later it is set to its parent to indicate an
740b57cec5SDimitry Andric   /// interior node. Finally, it is set to a representative subtree ID during
750b57cec5SDimitry Andric   /// finalization.
760b57cec5SDimitry Andric   struct NodeData {
770b57cec5SDimitry Andric     unsigned InstrCount = 0;
780b57cec5SDimitry Andric     unsigned SubtreeID = InvalidSubtreeID;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric     NodeData() = default;
810b57cec5SDimitry Andric   };
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   /// Per-Subtree data computed during DFS.
840b57cec5SDimitry Andric   struct TreeData {
850b57cec5SDimitry Andric     unsigned ParentTreeID = InvalidSubtreeID;
860b57cec5SDimitry Andric     unsigned SubInstrCount = 0;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     TreeData() = default;
890b57cec5SDimitry Andric   };
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Record a connection between subtrees and the connection level.
920b57cec5SDimitry Andric   struct Connection {
930b57cec5SDimitry Andric     unsigned TreeID;
940b57cec5SDimitry Andric     unsigned Level;
950b57cec5SDimitry Andric 
ConnectionConnection960b57cec5SDimitry Andric     Connection(unsigned tree, unsigned level): TreeID(tree), Level(level) {}
970b57cec5SDimitry Andric   };
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   bool IsBottomUp;
1000b57cec5SDimitry Andric   unsigned SubtreeLimit;
1010b57cec5SDimitry Andric   /// DFS results for each SUnit in this DAG.
1020b57cec5SDimitry Andric   std::vector<NodeData> DFSNodeData;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   // Store per-tree data indexed on tree ID,
1050b57cec5SDimitry Andric   SmallVector<TreeData, 16> DFSTreeData;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   // For each subtree discovered during DFS, record its connections to other
1080b57cec5SDimitry Andric   // subtrees.
1090b57cec5SDimitry Andric   std::vector<SmallVector<Connection, 4>> SubtreeConnections;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// Cache the current connection level of each subtree.
1120b57cec5SDimitry Andric   /// This mutable array is updated during scheduling.
1130b57cec5SDimitry Andric   std::vector<unsigned> SubtreeConnectLevels;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric public:
SchedDFSResult(bool IsBU,unsigned lim)1160b57cec5SDimitry Andric   SchedDFSResult(bool IsBU, unsigned lim)
1170b57cec5SDimitry Andric     : IsBottomUp(IsBU), SubtreeLimit(lim) {}
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   /// Get the node cutoff before subtrees are considered significant.
getSubtreeLimit()1200b57cec5SDimitry Andric   unsigned getSubtreeLimit() const { return SubtreeLimit; }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   /// Return true if this DFSResult is uninitialized.
1230b57cec5SDimitry Andric   ///
1240b57cec5SDimitry Andric   /// resize() initializes DFSResult, while compute() populates it.
empty()1250b57cec5SDimitry Andric   bool empty() const { return DFSNodeData.empty(); }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   /// Clear the results.
clear()1280b57cec5SDimitry Andric   void clear() {
1290b57cec5SDimitry Andric     DFSNodeData.clear();
1300b57cec5SDimitry Andric     DFSTreeData.clear();
1310b57cec5SDimitry Andric     SubtreeConnections.clear();
1320b57cec5SDimitry Andric     SubtreeConnectLevels.clear();
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   /// Initialize the result data with the size of the DAG.
resize(unsigned NumSUnits)1360b57cec5SDimitry Andric   void resize(unsigned NumSUnits) {
1370b57cec5SDimitry Andric     DFSNodeData.resize(NumSUnits);
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   /// Compute various metrics for the DAG with given roots.
1410b57cec5SDimitry Andric   void compute(ArrayRef<SUnit> SUnits);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   /// Get the number of instructions in the given subtree and its
1440b57cec5SDimitry Andric   /// children.
getNumInstrs(const SUnit * SU)1450b57cec5SDimitry Andric   unsigned getNumInstrs(const SUnit *SU) const {
1460b57cec5SDimitry Andric     return DFSNodeData[SU->NodeNum].InstrCount;
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   /// Get the number of instructions in the given subtree not including
1500b57cec5SDimitry Andric   /// children.
getNumSubInstrs(unsigned SubtreeID)1510b57cec5SDimitry Andric   unsigned getNumSubInstrs(unsigned SubtreeID) const {
1520b57cec5SDimitry Andric     return DFSTreeData[SubtreeID].SubInstrCount;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   /// Get the ILP value for a DAG node.
1560b57cec5SDimitry Andric   ///
1570b57cec5SDimitry Andric   /// A leaf node has an ILP of 1/1.
getILP(const SUnit * SU)1580b57cec5SDimitry Andric   ILPValue getILP(const SUnit *SU) const {
1590b57cec5SDimitry Andric     return ILPValue(DFSNodeData[SU->NodeNum].InstrCount, 1 + SU->getDepth());
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   /// The number of subtrees detected in this DAG.
getNumSubtrees()1630b57cec5SDimitry Andric   unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   /// Get the ID of the subtree the given DAG node belongs to.
1660b57cec5SDimitry Andric   ///
1670b57cec5SDimitry Andric   /// For convenience, if DFSResults have not been computed yet, give everything
1680b57cec5SDimitry Andric   /// tree ID 0.
getSubtreeID(const SUnit * SU)1690b57cec5SDimitry Andric   unsigned getSubtreeID(const SUnit *SU) const {
1700b57cec5SDimitry Andric     if (empty())
1710b57cec5SDimitry Andric       return 0;
1720b57cec5SDimitry Andric     assert(SU->NodeNum < DFSNodeData.size() &&  "New Node");
1730b57cec5SDimitry Andric     return DFSNodeData[SU->NodeNum].SubtreeID;
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   /// Get the connection level of a subtree.
1770b57cec5SDimitry Andric   ///
1780b57cec5SDimitry Andric   /// For bottom-up trees, the connection level is the latency depth (in cycles)
1790b57cec5SDimitry Andric   /// of the deepest connection to another subtree.
getSubtreeLevel(unsigned SubtreeID)1800b57cec5SDimitry Andric   unsigned getSubtreeLevel(unsigned SubtreeID) const {
1810b57cec5SDimitry Andric     return SubtreeConnectLevels[SubtreeID];
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   /// Scheduler callback to update SubtreeConnectLevels when a tree is
1850b57cec5SDimitry Andric   /// initially scheduled.
1860b57cec5SDimitry Andric   void scheduleTree(unsigned SubtreeID);
1870b57cec5SDimitry Andric };
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric } // end namespace llvm
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric #endif // LLVM_CODEGEN_SCHEDULEDFS_H
194