xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/RDFLiveness.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10946e70aSDimitry Andric //===- RDFLiveness.h --------------------------------------------*- C++ -*-===//
20946e70aSDimitry Andric //
30946e70aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40946e70aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50946e70aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60946e70aSDimitry Andric //
70946e70aSDimitry Andric //===----------------------------------------------------------------------===//
80946e70aSDimitry Andric //
90946e70aSDimitry Andric // Recalculate the liveness information given a data flow graph.
100946e70aSDimitry Andric // This includes block live-ins and kill flags.
110946e70aSDimitry Andric 
12fe6060f1SDimitry Andric #ifndef LLVM_CODEGEN_RDFLIVENESS_H
13fe6060f1SDimitry Andric #define LLVM_CODEGEN_RDFLIVENESS_H
140946e70aSDimitry Andric 
150946e70aSDimitry Andric #include "RDFGraph.h"
160946e70aSDimitry Andric #include "RDFRegisters.h"
170946e70aSDimitry Andric #include "llvm/ADT/DenseMap.h"
180946e70aSDimitry Andric #include "llvm/MC/LaneBitmask.h"
190946e70aSDimitry Andric #include <map>
200946e70aSDimitry Andric #include <set>
21e8d8bef9SDimitry Andric #include <unordered_map>
22e8d8bef9SDimitry Andric #include <unordered_set>
230946e70aSDimitry Andric #include <utility>
240946e70aSDimitry Andric 
250946e70aSDimitry Andric namespace llvm {
260946e70aSDimitry Andric 
270946e70aSDimitry Andric class MachineBasicBlock;
280946e70aSDimitry Andric class MachineDominanceFrontier;
290946e70aSDimitry Andric class MachineDominatorTree;
300946e70aSDimitry Andric class MachineRegisterInfo;
310946e70aSDimitry Andric class TargetRegisterInfo;
320946e70aSDimitry Andric 
33e8d8bef9SDimitry Andric namespace rdf {
34e8d8bef9SDimitry Andric namespace detail {
35e8d8bef9SDimitry Andric 
36e8d8bef9SDimitry Andric using NodeRef = std::pair<NodeId, LaneBitmask>;
37e8d8bef9SDimitry Andric 
38e8d8bef9SDimitry Andric } // namespace detail
39e8d8bef9SDimitry Andric } // namespace rdf
40e8d8bef9SDimitry Andric } // namespace llvm
41e8d8bef9SDimitry Andric 
42e8d8bef9SDimitry Andric namespace std {
43e8d8bef9SDimitry Andric 
44e8d8bef9SDimitry Andric template <> struct hash<llvm::rdf::detail::NodeRef> {
45e8d8bef9SDimitry Andric   std::size_t operator()(llvm::rdf::detail::NodeRef R) const {
46e8d8bef9SDimitry Andric     return std::hash<llvm::rdf::NodeId>{}(R.first) ^
47e8d8bef9SDimitry Andric            std::hash<llvm::LaneBitmask::Type>{}(R.second.getAsInteger());
48e8d8bef9SDimitry Andric   }
49e8d8bef9SDimitry Andric };
50e8d8bef9SDimitry Andric 
51e8d8bef9SDimitry Andric } // namespace std
52e8d8bef9SDimitry Andric 
53*06c3fb27SDimitry Andric namespace llvm::rdf {
540946e70aSDimitry Andric 
550946e70aSDimitry Andric struct Liveness {
560946e70aSDimitry Andric public:
57*06c3fb27SDimitry Andric   using LiveMapType = RegisterAggrMap<MachineBasicBlock *>;
58e8d8bef9SDimitry Andric   using NodeRef = detail::NodeRef;
59e8d8bef9SDimitry Andric   using NodeRefSet = std::unordered_set<NodeRef>;
60e8d8bef9SDimitry Andric   using RefMap = std::unordered_map<RegisterId, NodeRefSet>;
610946e70aSDimitry Andric 
620946e70aSDimitry Andric   Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g)
630946e70aSDimitry Andric       : DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()),
640946e70aSDimitry Andric         MDF(g.getDF()), LiveMap(g.getPRI()), Empty(), NoRegs(g.getPRI()) {}
650946e70aSDimitry Andric 
660946e70aSDimitry Andric   NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode *> RefA,
67*06c3fb27SDimitry Andric                               bool TopShadows, bool FullChain,
68*06c3fb27SDimitry Andric                               const RegisterAggr &DefRRs);
690946e70aSDimitry Andric 
700946e70aSDimitry Andric   NodeList getAllReachingDefs(NodeAddr<RefNode *> RefA) {
71*06c3fb27SDimitry Andric     return getAllReachingDefs(RefA.Addr->getRegRef(DFG), RefA, false, false,
72*06c3fb27SDimitry Andric                               NoRegs);
730946e70aSDimitry Andric   }
740946e70aSDimitry Andric 
750946e70aSDimitry Andric   NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode *> RefA) {
760946e70aSDimitry Andric     return getAllReachingDefs(RefRR, RefA, false, false, NoRegs);
770946e70aSDimitry Andric   }
780946e70aSDimitry Andric 
790946e70aSDimitry Andric   NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr<DefNode *> DefA,
800946e70aSDimitry Andric                             const RegisterAggr &DefRRs);
810946e70aSDimitry Andric 
820946e70aSDimitry Andric   NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr<DefNode *> DefA) {
830946e70aSDimitry Andric     return getAllReachedUses(RefRR, DefA, NoRegs);
840946e70aSDimitry Andric   }
850946e70aSDimitry Andric 
860946e70aSDimitry Andric   std::pair<NodeSet, bool> getAllReachingDefsRec(RegisterRef RefRR,
87*06c3fb27SDimitry Andric                                                  NodeAddr<RefNode *> RefA,
88*06c3fb27SDimitry Andric                                                  NodeSet &Visited,
89*06c3fb27SDimitry Andric                                                  const NodeSet &Defs);
900946e70aSDimitry Andric 
910946e70aSDimitry Andric   NodeAddr<RefNode *> getNearestAliasedRef(RegisterRef RefRR,
920946e70aSDimitry Andric                                            NodeAddr<InstrNode *> IA);
930946e70aSDimitry Andric 
940946e70aSDimitry Andric   LiveMapType &getLiveMap() { return LiveMap; }
950946e70aSDimitry Andric   const LiveMapType &getLiveMap() const { return LiveMap; }
960946e70aSDimitry Andric 
970946e70aSDimitry Andric   const RefMap &getRealUses(NodeId P) const {
980946e70aSDimitry Andric     auto F = RealUseMap.find(P);
990946e70aSDimitry Andric     return F == RealUseMap.end() ? Empty : F->second;
1000946e70aSDimitry Andric   }
1010946e70aSDimitry Andric 
1020946e70aSDimitry Andric   void computePhiInfo();
1030946e70aSDimitry Andric   void computeLiveIns();
1040946e70aSDimitry Andric   void resetLiveIns();
1050946e70aSDimitry Andric   void resetKills();
1060946e70aSDimitry Andric   void resetKills(MachineBasicBlock *B);
1070946e70aSDimitry Andric 
1080946e70aSDimitry Andric   void trace(bool T) { Trace = T; }
1090946e70aSDimitry Andric 
1100946e70aSDimitry Andric private:
1110946e70aSDimitry Andric   const DataFlowGraph &DFG;
1120946e70aSDimitry Andric   const TargetRegisterInfo &TRI;
1130946e70aSDimitry Andric   const PhysicalRegisterInfo &PRI;
1140946e70aSDimitry Andric   const MachineDominatorTree &MDT;
1150946e70aSDimitry Andric   const MachineDominanceFrontier &MDF;
1160946e70aSDimitry Andric   LiveMapType LiveMap;
1170946e70aSDimitry Andric   const RefMap Empty;
1180946e70aSDimitry Andric   const RegisterAggr NoRegs;
1190946e70aSDimitry Andric   bool Trace = false;
1200946e70aSDimitry Andric 
1210946e70aSDimitry Andric   // Cache of mapping from node ids (for RefNodes) to the containing
1220946e70aSDimitry Andric   // basic blocks. Not computing it each time for each node reduces
1230946e70aSDimitry Andric   // the liveness calculation time by a large fraction.
124e8d8bef9SDimitry Andric   DenseMap<NodeId, MachineBasicBlock *> NBMap;
1250946e70aSDimitry Andric 
1260946e70aSDimitry Andric   // Phi information:
1270946e70aSDimitry Andric   //
1280946e70aSDimitry Andric   // RealUseMap
1290946e70aSDimitry Andric   // map: NodeId -> (map: RegisterId -> NodeRefSet)
1300946e70aSDimitry Andric   //      phi id -> (map: register -> set of reached non-phi uses)
131e8d8bef9SDimitry Andric   DenseMap<NodeId, RefMap> RealUseMap;
1320946e70aSDimitry Andric 
1330946e70aSDimitry Andric   // Inverse iterated dominance frontier.
1340946e70aSDimitry Andric   std::map<MachineBasicBlock *, std::set<MachineBasicBlock *>> IIDF;
1350946e70aSDimitry Andric 
1360946e70aSDimitry Andric   // Live on entry.
1370946e70aSDimitry Andric   std::map<MachineBasicBlock *, RefMap> PhiLON;
1380946e70aSDimitry Andric 
1390946e70aSDimitry Andric   // Phi uses are considered to be located at the end of the block that
1400946e70aSDimitry Andric   // they are associated with. The reaching def of a phi use dominates the
1410946e70aSDimitry Andric   // block that the use corresponds to, but not the block that contains
1420946e70aSDimitry Andric   // the phi itself. To include these uses in the liveness propagation (up
1430946e70aSDimitry Andric   // the dominator tree), create a map: block -> set of uses live on exit.
1440946e70aSDimitry Andric   std::map<MachineBasicBlock *, RefMap> PhiLOX;
1450946e70aSDimitry Andric 
1460946e70aSDimitry Andric   MachineBasicBlock *getBlockWithRef(NodeId RN) const;
1470946e70aSDimitry Andric   void traverse(MachineBasicBlock *B, RefMap &LiveIn);
1480946e70aSDimitry Andric   void emptify(RefMap &M);
1490946e70aSDimitry Andric 
150*06c3fb27SDimitry Andric   std::pair<NodeSet, bool>
151*06c3fb27SDimitry Andric   getAllReachingDefsRecImpl(RegisterRef RefRR, NodeAddr<RefNode *> RefA,
152*06c3fb27SDimitry Andric                             NodeSet &Visited, const NodeSet &Defs,
1530946e70aSDimitry Andric                             unsigned Nest, unsigned MaxNest);
1540946e70aSDimitry Andric };
1550946e70aSDimitry Andric 
1560946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Liveness::RefMap> &P);
1570946e70aSDimitry Andric 
158*06c3fb27SDimitry Andric } // end namespace llvm::rdf
1590946e70aSDimitry Andric 
160fe6060f1SDimitry Andric #endif // LLVM_CODEGEN_RDFLIVENESS_H
161