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