xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/Analysis/DominanceFrontier.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- 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 // This file defines the DominanceFrontier class, which calculate and holds the
100b57cec5SDimitry Andric // dominance frontier for a function.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric // This should be considered deprecated, don't add any more uses of this data
130b57cec5SDimitry Andric // structure.
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H
180b57cec5SDimitry Andric #define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
190b57cec5SDimitry Andric 
205f757f3fSDimitry Andric #include "llvm/ADT/DenseMap.h"
210b57cec5SDimitry Andric #include "llvm/ADT/GraphTraits.h"
225f757f3fSDimitry Andric #include "llvm/ADT/SetVector.h"
230b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
240b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Support/GenericDomTree.h"
270b57cec5SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric #include <utility>
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace llvm {
310b57cec5SDimitry Andric 
32*0fca6ea1SDimitry Andric class BasicBlock;
330b57cec5SDimitry Andric class Function;
340b57cec5SDimitry Andric class raw_ostream;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
370b57cec5SDimitry Andric /// DominanceFrontierBase - Common base class for computing forward and inverse
380b57cec5SDimitry Andric /// dominance frontiers for a function.
390b57cec5SDimitry Andric ///
400b57cec5SDimitry Andric template <class BlockT, bool IsPostDom>
410b57cec5SDimitry Andric class DominanceFrontierBase {
420b57cec5SDimitry Andric public:
435f757f3fSDimitry Andric   // Dom set for a bb. Use SetVector to make iterating dom frontiers of a bb
445f757f3fSDimitry Andric   // deterministic.
455f757f3fSDimitry Andric   using DomSetType = SetVector<BlockT *>;
465f757f3fSDimitry Andric   using DomSetMapType = DenseMap<BlockT *, DomSetType>; // Dom set map
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric protected:
490b57cec5SDimitry Andric   using BlockTraits = GraphTraits<BlockT *>;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   DomSetMapType Frontiers;
520b57cec5SDimitry Andric   // Postdominators can have multiple roots.
530b57cec5SDimitry Andric   SmallVector<BlockT *, IsPostDom ? 4 : 1> Roots;
540b57cec5SDimitry Andric   static constexpr bool IsPostDominators = IsPostDom;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric public:
570b57cec5SDimitry Andric   DominanceFrontierBase() = default;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   /// getRoots - Return the root blocks of the current CFG.  This may include
600b57cec5SDimitry Andric   /// multiple blocks if we are computing post dominators.  For forward
610b57cec5SDimitry Andric   /// dominators, this will always be a single block (the entry node).
620b57cec5SDimitry Andric   const SmallVectorImpl<BlockT *> &getRoots() const { return Roots; }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   BlockT *getRoot() const {
650b57cec5SDimitry Andric     assert(Roots.size() == 1 && "Should always have entry node!");
660b57cec5SDimitry Andric     return Roots[0];
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   /// isPostDominator - Returns true if analysis based of postdoms
700b57cec5SDimitry Andric   bool isPostDominator() const {
710b57cec5SDimitry Andric     return IsPostDominators;
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   void releaseMemory() {
750b57cec5SDimitry Andric     Frontiers.clear();
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // Accessor interface:
790b57cec5SDimitry Andric   using iterator = typename DomSetMapType::iterator;
800b57cec5SDimitry Andric   using const_iterator = typename DomSetMapType::const_iterator;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   iterator begin() { return Frontiers.begin(); }
830b57cec5SDimitry Andric   const_iterator begin() const { return Frontiers.begin(); }
840b57cec5SDimitry Andric   iterator end() { return Frontiers.end(); }
850b57cec5SDimitry Andric   const_iterator end() const { return Frontiers.end(); }
860b57cec5SDimitry Andric   iterator find(BlockT *B) { return Frontiers.find(B); }
870b57cec5SDimitry Andric   const_iterator find(BlockT *B) const { return Frontiers.find(B); }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   iterator addBasicBlock(BlockT *BB, const DomSetType &frontier) {
900b57cec5SDimitry Andric     assert(find(BB) == end() && "Block already in DominanceFrontier!");
910b57cec5SDimitry Andric     return Frontiers.insert(std::make_pair(BB, frontier)).first;
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   /// removeBlock - Remove basic block BB's frontier.
950b57cec5SDimitry Andric   void removeBlock(BlockT *BB);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   void addToFrontier(iterator I, BlockT *Node);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   void removeFromFrontier(iterator I, BlockT *Node);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   /// compareDomSet - Return false if two domsets match. Otherwise
1020b57cec5SDimitry Andric   /// return true;
1030b57cec5SDimitry Andric   bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const;
1040b57cec5SDimitry Andric 
105*0fca6ea1SDimitry Andric   /// compare - Return false if the other dominance frontier base matches
106*0fca6ea1SDimitry Andric   /// this dominance frontier base. Otherwise return true.
1070b57cec5SDimitry Andric   bool compare(DominanceFrontierBase &Other) const;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   /// print - Convert to human readable form
1100b57cec5SDimitry Andric   ///
1110b57cec5SDimitry Andric   void print(raw_ostream &OS) const;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   /// dump - Dump the dominance frontier to dbgs().
1140b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1150b57cec5SDimitry Andric   void dump() const;
1160b57cec5SDimitry Andric #endif
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric //===-------------------------------------
1200b57cec5SDimitry Andric /// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
1210b57cec5SDimitry Andric /// used to compute a forward dominator frontiers.
1220b57cec5SDimitry Andric ///
1230b57cec5SDimitry Andric template <class BlockT>
1240b57cec5SDimitry Andric class ForwardDominanceFrontierBase
1250b57cec5SDimitry Andric     : public DominanceFrontierBase<BlockT, false> {
1260b57cec5SDimitry Andric private:
1270b57cec5SDimitry Andric   using BlockTraits = GraphTraits<BlockT *>;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric public:
1300b57cec5SDimitry Andric   using DomTreeT = DomTreeBase<BlockT>;
1310b57cec5SDimitry Andric   using DomTreeNodeT = DomTreeNodeBase<BlockT>;
1320b57cec5SDimitry Andric   using DomSetType = typename DominanceFrontierBase<BlockT, false>::DomSetType;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   void analyze(DomTreeT &DT) {
1355ffd83dbSDimitry Andric     assert(DT.root_size() == 1 &&
1360b57cec5SDimitry Andric            "Only one entry block for forward domfronts!");
1370b57cec5SDimitry Andric     this->Roots = {DT.getRoot()};
1380b57cec5SDimitry Andric     calculate(DT, DT[this->Roots[0]]);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node);
1420b57cec5SDimitry Andric };
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> {
1450b57cec5SDimitry Andric public:
1460b57cec5SDimitry Andric   using DomTreeT = DomTreeBase<BasicBlock>;
1470b57cec5SDimitry Andric   using DomTreeNodeT = DomTreeNodeBase<BasicBlock>;
1480b57cec5SDimitry Andric   using DomSetType = DominanceFrontierBase<BasicBlock, false>::DomSetType;
1490b57cec5SDimitry Andric   using iterator = DominanceFrontierBase<BasicBlock, false>::iterator;
1500b57cec5SDimitry Andric   using const_iterator =
1510b57cec5SDimitry Andric       DominanceFrontierBase<BasicBlock, false>::const_iterator;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   /// Handle invalidation explicitly.
1540b57cec5SDimitry Andric   bool invalidate(Function &F, const PreservedAnalyses &PA,
1550b57cec5SDimitry Andric                   FunctionAnalysisManager::Invalidator &);
1560b57cec5SDimitry Andric };
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric class DominanceFrontierWrapperPass : public FunctionPass {
1590b57cec5SDimitry Andric   DominanceFrontier DF;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric public:
1620b57cec5SDimitry Andric   static char ID; // Pass ID, replacement for typeid
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   DominanceFrontierWrapperPass();
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   DominanceFrontier &getDominanceFrontier() { return DF; }
1670b57cec5SDimitry Andric   const DominanceFrontier &getDominanceFrontier() const { return DF;  }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   void releaseMemory() override;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   bool runOnFunction(Function &) override;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   void print(raw_ostream &OS, const Module * = nullptr) const override;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   void dump() const;
1780b57cec5SDimitry Andric };
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric extern template class DominanceFrontierBase<BasicBlock, false>;
1810b57cec5SDimitry Andric extern template class DominanceFrontierBase<BasicBlock, true>;
1820b57cec5SDimitry Andric extern template class ForwardDominanceFrontierBase<BasicBlock>;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric /// Analysis pass which computes a \c DominanceFrontier.
1850b57cec5SDimitry Andric class DominanceFrontierAnalysis
1860b57cec5SDimitry Andric     : public AnalysisInfoMixin<DominanceFrontierAnalysis> {
1870b57cec5SDimitry Andric   friend AnalysisInfoMixin<DominanceFrontierAnalysis>;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   static AnalysisKey Key;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric public:
1920b57cec5SDimitry Andric   /// Provide the result type for this analysis pass.
1930b57cec5SDimitry Andric   using Result = DominanceFrontier;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   /// Run the analysis pass over a function and produce a dominator tree.
1960b57cec5SDimitry Andric   DominanceFrontier run(Function &F, FunctionAnalysisManager &AM);
1970b57cec5SDimitry Andric };
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric /// Printer pass for the \c DominanceFrontier.
2000b57cec5SDimitry Andric class DominanceFrontierPrinterPass
2010b57cec5SDimitry Andric     : public PassInfoMixin<DominanceFrontierPrinterPass> {
2020b57cec5SDimitry Andric   raw_ostream &OS;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric public:
2050b57cec5SDimitry Andric   explicit DominanceFrontierPrinterPass(raw_ostream &OS);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
2081db9f3b2SDimitry Andric 
2091db9f3b2SDimitry Andric   static bool isRequired() { return true; }
2100b57cec5SDimitry Andric };
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric } // end namespace llvm
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric #endif // LLVM_ANALYSIS_DOMINANCEFRONTIER_H
215