Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- 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_GENERICITERATEDDOMINANCEFRONTIER_H
24
#define LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_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
 
32
namespace llvm {
33
 
34
namespace 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.
39
template <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.
57
template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
58
public:
59
  using OrderedNodeTy =
60
      std::conditional_t<IsPostDom, Inverse<NodeTy *>, NodeTy *>;
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
 
104
private:
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
 
116
namespace IDFCalculatorDetail {
117
 
118
template <class NodeTy, bool IsPostDom>
119
typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
120
ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) {
121
  using OrderedNodeTy =
122
      typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
123
 
124
  auto Children = children<OrderedNodeTy>(N);
125
  return {Children.begin(), Children.end()};
126
}
127
 
128
} // end of namespace IDFCalculatorDetail
129
 
130
template <class NodeTy, bool IsPostDom>
131
void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
132
    SmallVectorImpl<NodeTy *> &IDFBlocks) {
133
  // Use a priority queue keyed on dominator tree level so that inserted nodes
134
  // are handled from the bottom of the dominator tree upwards. We also augment
135
  // the level with a DFS number to ensure that the blocks are ordered in a
136
  // deterministic way.
137
  using DomTreeNodePair =
138
      std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>;
139
  using IDFPriorityQueue =
140
      std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
141
                          less_second>;
142
 
143
  IDFPriorityQueue PQ;
144
 
145
  DT.updateDFSNumbers();
146
 
147
  SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
148
  SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
149
  SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
150
 
151
  for (NodeTy *BB : *DefBlocks)
152
    if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
153
      PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
154
      VisitedWorklist.insert(Node);
155
    }
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
    assert(Worklist.empty());
169
    Worklist.push_back(Root);
170
 
171
    while (!Worklist.empty()) {
172
      DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
173
      NodeTy *BB = Node->getBlock();
174
      // Succ is the successor in the direction we are calculating IDF, so it is
175
      // successor for IDF, and predecessor for Reverse IDF.
176
      auto DoWork = [&](NodeTy *Succ) {
177
        DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ);
178
 
179
        const unsigned SuccLevel = SuccNode->getLevel();
180
        if (SuccLevel > RootLevel)
181
          return;
182
 
183
        if (!VisitedPQ.insert(SuccNode).second)
184
          return;
185
 
186
        NodeTy *SuccBB = SuccNode->getBlock();
187
        if (useLiveIn && !LiveInBlocks->count(SuccBB))
188
          return;
189
 
190
        IDFBlocks.emplace_back(SuccBB);
191
        if (!DefBlocks->count(SuccBB))
192
          PQ.push(std::make_pair(
193
              SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
194
      };
195
 
196
      for (auto *Succ : ChildrenGetter.get(BB))
197
        DoWork(Succ);
198
 
199
      for (auto DomChild : *Node) {
200
        if (VisitedWorklist.insert(DomChild).second)
201
          Worklist.push_back(DomChild);
202
      }
203
    }
204
  }
205
}
206
 
207
} // end of namespace llvm
208
 
209
#endif