123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- /// Compute iterated dominance frontiers using a linear time algorithm.
- ///
- /// The algorithm used here is based on:
- ///
- /// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
- /// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
- /// Programming Languages
- /// POPL '95. ACM, New York, NY, 62-73.
- ///
- /// It has been modified to not explicitly use the DJ graph data structure and
- /// to directly compute pruned SSA using per-variable liveness information.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
- #define LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/Support/GenericDomTree.h"
- #include <queue>
- namespace llvm {
- namespace IDFCalculatorDetail {
- /// Generic utility class used for getting the children of a basic block.
- /// May be specialized if, for example, one wouldn't like to return nullpointer
- /// successors.
- template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy {
- using NodeRef = typename GraphTraits<NodeTy *>::NodeRef;
- using ChildrenTy = SmallVector<NodeRef, 8>;
- ChildrenTy get(const NodeRef &N);
- };
- } // end of namespace IDFCalculatorDetail
- /// Determine the iterated dominance frontier, given a set of defining
- /// blocks, and optionally, a set of live-in blocks.
- ///
- /// In turn, the results can be used to place phi nodes.
- ///
- /// This algorithm is a linear time computation of Iterated Dominance Frontiers,
- /// pruned using the live-in set.
- /// By default, liveness is not used to prune the IDF computation.
- /// The template parameters should be of a CFG block type.
- template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
- public:
- using OrderedNodeTy =
- std::conditional_t<IsPostDom, Inverse<NodeTy *>, NodeTy *>;
- using ChildrenGetterTy =
- IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
- IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT) : DT(DT) {}
- IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT,
- const ChildrenGetterTy &C)
- : DT(DT), ChildrenGetter(C) {}
- /// Give the IDF calculator the set of blocks in which the value is
- /// defined. This is equivalent to the set of starting blocks it should be
- /// calculating the IDF for (though later gets pruned based on liveness).
- ///
- /// Note: This set *must* live for the entire lifetime of the IDF calculator.
- void setDefiningBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
- DefBlocks = &Blocks;
- }
- /// Give the IDF calculator the set of blocks in which the value is
- /// live on entry to the block. This is used to prune the IDF calculation to
- /// not include blocks where any phi insertion would be dead.
- ///
- /// Note: This set *must* live for the entire lifetime of the IDF calculator.
- void setLiveInBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
- LiveInBlocks = &Blocks;
- useLiveIn = true;
- }
- /// Reset the live-in block set to be empty, and tell the IDF
- /// calculator to not use liveness anymore.
- void resetLiveInBlocks() {
- LiveInBlocks = nullptr;
- useLiveIn = false;
- }
- /// Calculate iterated dominance frontiers
- ///
- /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
- /// the file-level comment. It performs DF->IDF pruning using the live-in
- /// set, to avoid computing the IDF for blocks where an inserted PHI node
- /// would be dead.
- void calculate(SmallVectorImpl<NodeTy *> &IDFBlocks);
- private:
- DominatorTreeBase<NodeTy, IsPostDom> &DT;
- ChildrenGetterTy ChildrenGetter;
- bool useLiveIn = false;
- const SmallPtrSetImpl<NodeTy *> *LiveInBlocks;
- const SmallPtrSetImpl<NodeTy *> *DefBlocks;
- };
- //===----------------------------------------------------------------------===//
- // Implementation.
- //===----------------------------------------------------------------------===//
- namespace IDFCalculatorDetail {
- template <class NodeTy, bool IsPostDom>
- typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
- ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) {
- using OrderedNodeTy =
- typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
- auto Children = children<OrderedNodeTy>(N);
- return {Children.begin(), Children.end()};
- }
- } // end of namespace IDFCalculatorDetail
- template <class NodeTy, bool IsPostDom>
- void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
- SmallVectorImpl<NodeTy *> &IDFBlocks) {
- // Use a priority queue keyed on dominator tree level so that inserted nodes
- // are handled from the bottom of the dominator tree upwards. We also augment
- // the level with a DFS number to ensure that the blocks are ordered in a
- // deterministic way.
- using DomTreeNodePair =
- std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>;
- using IDFPriorityQueue =
- std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
- less_second>;
- IDFPriorityQueue PQ;
- DT.updateDFSNumbers();
- SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
- SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
- SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
- for (NodeTy *BB : *DefBlocks)
- if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
- PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
- VisitedWorklist.insert(Node);
- }
- while (!PQ.empty()) {
- DomTreeNodePair RootPair = PQ.top();
- PQ.pop();
- DomTreeNodeBase<NodeTy> *Root = RootPair.first;
- unsigned RootLevel = RootPair.second.first;
- // Walk all dominator tree children of Root, inspecting their CFG edges with
- // targets elsewhere on the dominator tree. Only targets whose level is at
- // most Root's level are added to the iterated dominance frontier of the
- // definition set.
- assert(Worklist.empty());
- Worklist.push_back(Root);
- while (!Worklist.empty()) {
- DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
- NodeTy *BB = Node->getBlock();
- // Succ is the successor in the direction we are calculating IDF, so it is
- // successor for IDF, and predecessor for Reverse IDF.
- auto DoWork = [&](NodeTy *Succ) {
- DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ);
- const unsigned SuccLevel = SuccNode->getLevel();
- if (SuccLevel > RootLevel)
- return;
- if (!VisitedPQ.insert(SuccNode).second)
- return;
- NodeTy *SuccBB = SuccNode->getBlock();
- if (useLiveIn && !LiveInBlocks->count(SuccBB))
- return;
- IDFBlocks.emplace_back(SuccBB);
- if (!DefBlocks->count(SuccBB))
- PQ.push(std::make_pair(
- SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
- };
- for (auto Succ : ChildrenGetter.get(BB))
- DoWork(Succ);
- for (auto DomChild : *Node) {
- if (VisitedWorklist.insert(DomChild).second)
- Worklist.push_back(DomChild);
- }
- }
- }
- }
- } // end of namespace llvm
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|