blob: fcd21339ef1f5390d1dd8982469c835479a27316 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Compute iterated dominance frontiers using a linear time algorithm.
10///
11/// The algorithm used here is based on:
12///
13/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
14/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
15/// Programming Languages
16/// POPL '95. ACM, New York, NY, 62-73.
17///
18/// It has been modified to not explicitly use the DJ graph data structure and
19/// to directly compute pruned SSA using per-variable liveness information.
20//
21//===----------------------------------------------------------------------===//
22
23#ifndef LLVM_SUPPORT_GENERIC_IDF_H
24#define LLVM_SUPPORT_GENERIC_IDF_H
25
26#include "llvm/ADT/DenseMap.h"
27#include "llvm/ADT/SmallPtrSet.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/Support/GenericDomTree.h"
30#include <queue>
31
32namespace llvm {
33
34namespace IDFCalculatorDetail {
35
36/// Generic utility class used for getting the children of a basic block.
37/// May be specialized if, for example, one wouldn't like to return nullpointer
38/// successors.
39template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy {
40 using NodeRef = typename GraphTraits<NodeTy>::NodeRef;
41 using ChildrenTy = SmallVector<NodeRef, 8>;
42
43 ChildrenTy get(const NodeRef &N);
44};
45
46} // end of namespace IDFCalculatorDetail
47
48/// Determine the iterated dominance frontier, given a set of defining
49/// blocks, and optionally, a set of live-in blocks.
50///
51/// In turn, the results can be used to place phi nodes.
52///
53/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
54/// pruned using the live-in set.
55/// By default, liveness is not used to prune the IDF computation.
56/// The template parameters should be of a CFG block type.
57template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
58public:
59 using OrderedNodeTy =
60 typename std::conditional<IsPostDom, Inverse<NodeTy *>, NodeTy *>::type;
61 using ChildrenGetterTy =
62 IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
63
64 IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT) : DT(DT) {}
65
66 IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT,
67 const ChildrenGetterTy &C)
68 : DT(DT), ChildrenGetter(C) {}
69
70 /// Give the IDF calculator the set of blocks in which the value is
71 /// defined. This is equivalent to the set of starting blocks it should be
72 /// calculating the IDF for (though later gets pruned based on liveness).
73 ///
74 /// Note: This set *must* live for the entire lifetime of the IDF calculator.
75 void setDefiningBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
76 DefBlocks = &Blocks;
77 }
78
79 /// Give the IDF calculator the set of blocks in which the value is
80 /// live on entry to the block. This is used to prune the IDF calculation to
81 /// not include blocks where any phi insertion would be dead.
82 ///
83 /// Note: This set *must* live for the entire lifetime of the IDF calculator.
84 void setLiveInBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
85 LiveInBlocks = &Blocks;
86 useLiveIn = true;
87 }
88
89 /// Reset the live-in block set to be empty, and tell the IDF
90 /// calculator to not use liveness anymore.
91 void resetLiveInBlocks() {
92 LiveInBlocks = nullptr;
93 useLiveIn = false;
94 }
95
96 /// Calculate iterated dominance frontiers
97 ///
98 /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
99 /// the file-level comment. It performs DF->IDF pruning using the live-in
100 /// set, to avoid computing the IDF for blocks where an inserted PHI node
101 /// would be dead.
102 void calculate(SmallVectorImpl<NodeTy *> &IDFBlocks);
103
104private:
105 DominatorTreeBase<NodeTy, IsPostDom> &DT;
106 ChildrenGetterTy ChildrenGetter;
107 bool useLiveIn = false;
108 const SmallPtrSetImpl<NodeTy *> *LiveInBlocks;
109 const SmallPtrSetImpl<NodeTy *> *DefBlocks;
110};
111
112//===----------------------------------------------------------------------===//
113// Implementation.
114//===----------------------------------------------------------------------===//
115
116namespace IDFCalculatorDetail {
117
118template <class NodeTy, bool IsPostDom>
119typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
120ChildrenGetterTy<NodeTy, IsPostDom>::get(
121 const ChildrenGetterTy<NodeTy, IsPostDom>::NodeRef &N) {
122 using OrderedNodeTy =
123 typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
124
125 auto Children = children<OrderedNodeTy>(N);
126 return {Children.begin(), Children.end()};
127}
128
129} // end of namespace IDFCalculatorDetail
130
131template <class NodeTy, bool IsPostDom>
132void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
133 SmallVectorImpl<NodeTy *> &PHIBlocks) {
134 // Use a priority queue keyed on dominator tree level so that inserted nodes
135 // are handled from the bottom of the dominator tree upwards. We also augment
136 // the level with a DFS number to ensure that the blocks are ordered in a
137 // deterministic way.
138 using DomTreeNodePair =
139 std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>;
140 using IDFPriorityQueue =
141 std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
142 less_second>;
143
144 IDFPriorityQueue PQ;
145
146 DT.updateDFSNumbers();
147
148 for (NodeTy *BB : *DefBlocks) {
149 if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB))
150 PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
151 }
152
153 SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
154 SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
155 SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
156
157 while (!PQ.empty()) {
158 DomTreeNodePair RootPair = PQ.top();
159 PQ.pop();
160 DomTreeNodeBase<NodeTy> *Root = RootPair.first;
161 unsigned RootLevel = RootPair.second.first;
162
163 // Walk all dominator tree children of Root, inspecting their CFG edges with
164 // targets elsewhere on the dominator tree. Only targets whose level is at
165 // most Root's level are added to the iterated dominance frontier of the
166 // definition set.
167
168 Worklist.clear();
169 Worklist.push_back(Root);
170 VisitedWorklist.insert(Root);
171
172 while (!Worklist.empty()) {
173 DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
174 NodeTy *BB = Node->getBlock();
175 // Succ is the successor in the direction we are calculating IDF, so it is
176 // successor for IDF, and predecessor for Reverse IDF.
177 auto DoWork = [&](NodeTy *Succ) {
178 DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ);
179
180 const unsigned SuccLevel = SuccNode->getLevel();
181 if (SuccLevel > RootLevel)
182 return;
183
184 if (!VisitedPQ.insert(SuccNode).second)
185 return;
186
187 NodeTy *SuccBB = SuccNode->getBlock();
188 if (useLiveIn && !LiveInBlocks->count(SuccBB))
189 return;
190
191 PHIBlocks.emplace_back(SuccBB);
192 if (!DefBlocks->count(SuccBB))
193 PQ.push(std::make_pair(
194 SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
195 };
196
197 for (auto Succ : ChildrenGetter.get(BB))
198 DoWork(Succ);
199
200 for (auto DomChild : *Node) {
201 if (VisitedWorklist.insert(DomChild).second)
202 Worklist.push_back(DomChild);
203 }
204 }
205 }
206}
207
208} // end of namespace llvm
209
210#endif