1 //===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This is the generic implementation of the DominanceFrontier class, which
10 // calculate and holds the dominance frontier for a function for.
12 // This should be considered deprecated, don't add any more uses of this data
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
18 #define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
20 #include "llvm/ADT/GraphTraits.h"
21 #include "llvm/ADT/SmallPtrSet.h"
22 #include "llvm/Analysis/DominanceFrontier.h"
23 #include "llvm/Config/llvm-config.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/GenericDomTree.h"
26 #include "llvm/Support/raw_ostream.h"
34 template <class BlockT
>
35 class DFCalculateWorkObject
{
37 using DomTreeNodeT
= DomTreeNodeBase
<BlockT
>;
39 DFCalculateWorkObject(BlockT
*B
, BlockT
*P
, const DomTreeNodeT
*N
,
40 const DomTreeNodeT
*PN
)
41 : currentBB(B
), parentBB(P
), Node(N
), parentNode(PN
) {}
45 const DomTreeNodeT
*Node
;
46 const DomTreeNodeT
*parentNode
;
49 template <class BlockT
, bool IsPostDom
>
50 void DominanceFrontierBase
<BlockT
, IsPostDom
>::removeBlock(BlockT
*BB
) {
51 assert(find(BB
) != end() && "Block is not in DominanceFrontier!");
52 for (iterator I
= begin(), E
= end(); I
!= E
; ++I
)
57 template <class BlockT
, bool IsPostDom
>
58 void DominanceFrontierBase
<BlockT
, IsPostDom
>::addToFrontier(iterator I
,
60 assert(I
!= end() && "BB is not in DominanceFrontier!");
61 assert(I
->second
.count(Node
) && "Node is not in DominanceFrontier of BB");
62 I
->second
.erase(Node
);
65 template <class BlockT
, bool IsPostDom
>
66 void DominanceFrontierBase
<BlockT
, IsPostDom
>::removeFromFrontier(
67 iterator I
, BlockT
*Node
) {
68 assert(I
!= end() && "BB is not in DominanceFrontier!");
69 assert(I
->second
.count(Node
) && "Node is not in DominanceFrontier of BB");
70 I
->second
.erase(Node
);
73 template <class BlockT
, bool IsPostDom
>
74 bool DominanceFrontierBase
<BlockT
, IsPostDom
>::compareDomSet(
75 DomSetType
&DS1
, const DomSetType
&DS2
) const {
76 std::set
<BlockT
*> tmpSet
;
77 for (BlockT
*BB
: DS2
)
80 for (typename
DomSetType::const_iterator I
= DS1
.begin(), E
= DS1
.end();
84 if (tmpSet
.erase(Node
) == 0)
85 // Node is in DS1 but tnot in DS2.
89 if (!tmpSet
.empty()) {
90 // There are nodes that are in DS2 but not in DS1.
94 // DS1 and DS2 matches.
98 template <class BlockT
, bool IsPostDom
>
99 bool DominanceFrontierBase
<BlockT
, IsPostDom
>::compare(
100 DominanceFrontierBase
<BlockT
, IsPostDom
> &Other
) const {
101 DomSetMapType tmpFrontiers
;
102 for (typename
DomSetMapType::const_iterator I
= Other
.begin(),
105 tmpFrontiers
.insert(std::make_pair(I
->first
, I
->second
));
107 for (typename
DomSetMapType::iterator I
= tmpFrontiers
.begin(),
108 E
= tmpFrontiers
.end();
110 BlockT
*Node
= I
->first
;
111 const_iterator DFI
= find(Node
);
115 if (compareDomSet(I
->second
, DFI
->second
))
119 tmpFrontiers
.erase(Node
);
122 if (!tmpFrontiers
.empty())
128 template <class BlockT
, bool IsPostDom
>
129 void DominanceFrontierBase
<BlockT
, IsPostDom
>::print(raw_ostream
&OS
) const {
130 for (const_iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
131 OS
<< " DomFrontier for BB ";
133 I
->first
->printAsOperand(OS
, false);
135 OS
<< " <<exit node>>";
138 const std::set
<BlockT
*> &BBs
= I
->second
;
140 for (const BlockT
*BB
: BBs
) {
143 BB
->printAsOperand(OS
, false);
145 OS
<< "<<exit node>>";
151 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
152 template <class BlockT
, bool IsPostDom
>
153 void DominanceFrontierBase
<BlockT
, IsPostDom
>::dump() const {
158 template <class BlockT
>
159 const typename ForwardDominanceFrontierBase
<BlockT
>::DomSetType
&
160 ForwardDominanceFrontierBase
<BlockT
>::calculate(const DomTreeT
&DT
,
161 const DomTreeNodeT
*Node
) {
162 BlockT
*BB
= Node
->getBlock();
163 DomSetType
*Result
= nullptr;
165 std::vector
<DFCalculateWorkObject
<BlockT
>> workList
;
166 SmallPtrSet
<BlockT
*, 32> visited
;
168 workList
.push_back(DFCalculateWorkObject
<BlockT
>(BB
, nullptr, Node
, nullptr));
170 DFCalculateWorkObject
<BlockT
> *currentW
= &workList
.back();
171 assert(currentW
&& "Missing work object.");
173 BlockT
*currentBB
= currentW
->currentBB
;
174 BlockT
*parentBB
= currentW
->parentBB
;
175 const DomTreeNodeT
*currentNode
= currentW
->Node
;
176 const DomTreeNodeT
*parentNode
= currentW
->parentNode
;
177 assert(currentBB
&& "Invalid work object. Missing current Basic Block");
178 assert(currentNode
&& "Invalid work object. Missing current Node");
179 DomSetType
&S
= this->Frontiers
[currentBB
];
181 // Visit each block only once.
182 if (visited
.insert(currentBB
).second
) {
183 // Loop over CFG successors to calculate DFlocal[currentNode]
184 for (const auto Succ
: children
<BlockT
*>(currentBB
)) {
185 // Does Node immediately dominate this successor?
186 if (DT
[Succ
]->getIDom() != currentNode
)
191 // At this point, S is DFlocal. Now we union in DFup's of our children...
192 // Loop through and visit the nodes that Node immediately dominates (Node's
193 // children in the IDomTree)
194 bool visitChild
= false;
195 for (typename
DomTreeNodeT::const_iterator NI
= currentNode
->begin(),
196 NE
= currentNode
->end();
198 DomTreeNodeT
*IDominee
= *NI
;
199 BlockT
*childBB
= IDominee
->getBlock();
200 if (visited
.count(childBB
) == 0) {
201 workList
.push_back(DFCalculateWorkObject
<BlockT
>(
202 childBB
, currentBB
, IDominee
, currentNode
));
207 // If all children are visited or there is any child then pop this block
208 // from the workList.
215 typename
DomSetType::const_iterator CDFI
= S
.begin(), CDFE
= S
.end();
216 DomSetType
&parentSet
= this->Frontiers
[parentBB
];
217 for (; CDFI
!= CDFE
; ++CDFI
) {
218 if (!DT
.properlyDominates(parentNode
, DT
[*CDFI
]))
219 parentSet
.insert(*CDFI
);
224 } while (!workList
.empty());
229 } // end namespace llvm
231 #endif // LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H