MLIR 23.0.0git
Dominance.h
Go to the documentation of this file.
1//===- Dominance.h - Dominator analysis for regions -------------*- 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//
9// The DominanceInfo and PostDominanceInfo class provide routines for performimg
10// simple dominance checks, and expose dominator trees for advanced clients.
11// These classes provide fully region-aware functionality, lazily constructing
12// dominator information for any multi-block regions that need it.
13//
14// For more information about the theory behind dominance in graphs algorithms,
15// see: https://en.wikipedia.org/wiki/Dominator_(graph_theory)
16//
17//===----------------------------------------------------------------------===//
18
19#ifndef MLIR_IR_DOMINANCE_H
20#define MLIR_IR_DOMINANCE_H
21
23#include "llvm/Support/GenericDomTree.h"
24
25extern template class llvm::DominatorTreeBase<mlir::Block, false>;
26extern template class llvm::DominatorTreeBase<mlir::Block, true>;
27extern template class llvm::DomTreeNodeBase<mlir::Block>;
28
29namespace mlir {
30using DominanceInfoNode = llvm::DomTreeNodeBase<Block>;
31class Operation;
32
33namespace detail {
34template <bool IsPostDom>
36 using DomTree = llvm::DominatorTreeBase<Block, IsPostDom>;
37
38public:
39 DominanceInfoBase(Operation *op = nullptr) {}
43
46
47 /// Invalidate dominance info. This can be used by clients that make major
48 /// changes to the CFG and don't have a good way to update it.
49 void invalidate();
50
51 /// Invalidate dominance info of the \p region, if \p recursive is true, it
52 /// invalidates the dominance information of child regions.
53 void invalidate(Region *region, bool recursive = true);
54
55 /// Finds the nearest common dominator block for the two given blocks a
56 /// and b. If no common dominator can be found, this function will return
57 /// nullptr.
59
60 /// Finds the nearest common dominator block for the given range of blocks.
61 /// If no common dominator can be found, this function will return nullptr.
62 template <typename BlockRangeT>
63 Block *findNearestCommonDominator(BlockRangeT &&blocks) const {
64 if (blocks.begin() == blocks.end())
65 return nullptr;
66 Block *dom = *blocks.begin();
67 for (auto it = ++blocks.begin(); it != blocks.end(); ++it) {
68 dom = findNearestCommonDominator(dom, *it);
69 if (!dom)
70 return nullptr;
71 }
72 return dom;
73 }
74
75 /// Get the root dominance node of the given region. Note that this operation
76 /// is only defined for multi-block regions!
78 auto domInfo = getDominanceInfo(region, /*needsDomTree*/ true).getPointer();
79 assert(domInfo && "Region isn't multiblock");
80 return domInfo->getRootNode();
81 }
82
83 /// Return the dominance node from the Region containing block A. This only
84 /// works for multi-block regions.
86 return getDomTree(a->getParent()).getNode(a);
87 }
88
89 /// Return true if the specified block is reachable from the entry
90 /// block of its region.
92
93 /// Return true if operations in the specified block are known to obey SSA
94 /// dominance requirements. False if the block is a graph region or unknown.
95 bool hasSSADominance(Block *block) const {
96 return hasSSADominance(block->getParent());
97 }
98 /// Return true if operations in the specified block are known to obey SSA
99 /// dominance requirements. False if the block is a graph region or unknown.
100 bool hasSSADominance(Region *region) const {
101 return getDominanceInfo(region, /*needsDomTree=*/false).getInt();
102 }
103
104 DomTree &getDomTree(Region *region) const {
105 assert(!region->hasOneBlock() &&
106 "Can't get DomTree for single block regions");
107 return *getDominanceInfo(region, /*needsDomTree=*/true).getPointer();
108 }
109
110protected:
112
113 /// Return the dom tree and "hasSSADominance" bit for the given region. The
114 /// DomTree will be null for single-block regions. This lazily constructs the
115 /// DomTree on demand when needsDomTree=true.
116 llvm::PointerIntPair<DomTree *, 1, bool>
117 getDominanceInfo(Region *region, bool needsDomTree) const;
118
119 /// Return "true" if block iterator A properly (post)dominates block iterator
120 /// B. If `enclosingOk` is set, A is considered to (post)dominate B if A
121 /// encloses B.
123 Block::iterator bIt,
124 bool enclosingOk = true) const;
125
126 /// A mapping of regions to their base dominator tree and a cached
127 /// "hasSSADominance" bit. This map does not contain dominator trees for
128 /// single block CFG regions, but we do want to cache the "hasSSADominance"
129 /// bit for them. We may also not have computed the DomTree yet. In either
130 /// case, the DomTree is just null.
131 ///
134};
135
136extern template class DominanceInfoBase</*IsPostDom=*/true>;
137extern template class DominanceInfoBase</*IsPostDom=*/false>;
138} // namespace detail
139
140/// A class for computing basic dominance information. Note that this
141/// class is aware of different types of regions and returns a
142/// region-kind specific concept of dominance. See RegionKindInterface.
143class DominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/false> {
144public:
145 using super::super;
146
147 /// Return true if operation A properly dominates operation B, i.e. if A and B
148 /// are in the same block and A properly dominates B within the block, or if
149 /// the block that contains A properly dominates the block that contains B. In
150 /// an SSACFG region, Operation A dominates Operation B in the same block if A
151 /// preceeds B. In a Graph region, all operations in a block properly dominate
152 /// all operations in the same block.
153 ///
154 /// The `enclosingOpOk` flag says whether we should return true if the B op
155 /// is enclosed by a region on A.
157 bool enclosingOpOk = true) const;
158
159 /// Return true if operation A dominates operation B, i.e. if A and B are the
160 /// same operation or A properly dominates B.
161 bool dominates(Operation *a, Operation *b) const {
162 return a == b || properlyDominates(a, b);
163 }
164
165 /// Return true if the `a` value properly dominates operation `b`, i.e if the
166 /// operation that defines `a` properlyDominates `b` and the operation that
167 /// defines `a` does not contain `b`.
168 bool properlyDominates(Value a, Operation *b) const;
169
170 /// Return true if the `a` value dominates operation `b`.
171 bool dominates(Value a, Operation *b) const {
172 return (Operation *)a.getDefiningOp() == b || properlyDominates(a, b);
173 }
174
175 /// Return true if the specified block A dominates block B, i.e. if block A
176 /// and block B are the same block or block A properly dominates block B.
177 bool dominates(Block *a, Block *b) const {
178 return a == b || properlyDominates(a, b);
179 }
180
181 /// Return true if the specified block A properly dominates block B, i.e.: if
182 /// block A contains block B, or if the region which contains block A also
183 /// contains block B or some parent of block B and block A dominates that
184 /// block in that kind of region.
185 ///
186 /// In an SSACFG region, block A dominates block B if all control flow paths
187 /// from the entry block to block B flow through block A.
188 ///
189 /// Graph regions have only a single block. To be consistent with "proper
190 /// dominance" of ops, the single block is considered to properly dominate
191 /// itself in a graph region.
192 bool properlyDominates(Block *a, Block *b) const;
193
194 bool properlyDominates(Block *aBlock, Block::iterator aIt, Block *bBlock,
195 Block::iterator bIt, bool enclosingOk = true) const {
196 return super::properlyDominatesImpl(aBlock, aIt, bBlock, bIt, enclosingOk);
197 }
198
199 bool dominates(Block *aBlock, Block::iterator aIt, Block *bBlock,
200 Block::iterator bIt, bool enclosingOk = true) const {
201 return (aBlock == bBlock && aIt == bIt) ||
202 super::properlyDominatesImpl(aBlock, aIt, bBlock, bIt, enclosingOk);
203 }
204};
205
206/// A class for computing basic postdominance information.
207class PostDominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/true> {
208public:
209 using super::super;
210
211 /// Return true if operation A properly postdominates operation B.
213 bool enclosingOpOk = true) const;
214
215 /// Return true if operation A postdominates operation B.
217 return a == b || properlyPostDominates(a, b);
218 }
219
220 /// Return true if the specified block A properly postdominates block B.
221 bool properlyPostDominates(Block *a, Block *b) const;
222
223 /// Return true if the specified block A postdominates block B.
224 bool postDominates(Block *a, Block *b) const {
225 return a == b || properlyPostDominates(a, b);
226 }
227
229 Block::iterator bIt,
230 bool enclosingOk = true) const {
231 return super::properlyDominatesImpl(aBlock, aIt, bBlock, bIt, enclosingOk);
232 }
233
234 bool postDominates(Block *aBlock, Block::iterator aIt, Block *bBlock,
235 Block::iterator bIt, bool enclosingOk = true) const {
236 return (aBlock == bBlock && aIt == bIt) ||
237 super::properlyDominatesImpl(aBlock, aIt, bBlock, bIt, enclosingOk);
238 }
239};
240
241} // namespace mlir
242
243namespace llvm {
244
245/// DominatorTree GraphTraits specialization so the DominatorTree can be
246/// iterated by generic graph iterators.
247template <>
248struct GraphTraits<mlir::DominanceInfoNode *> {
249 using ChildIteratorType = mlir::DominanceInfoNode::const_iterator;
251
252 static NodeRef getEntryNode(NodeRef N) { return N; }
253 static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
254 static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
255};
256
257template <>
258struct GraphTraits<const mlir::DominanceInfoNode *> {
259 using ChildIteratorType = mlir::DominanceInfoNode::const_iterator;
261
262 static NodeRef getEntryNode(NodeRef N) { return N; }
263 static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
264 static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
265};
266
267} // namespace llvm
268#endif
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
Block represents an ordered list of Operations.
Definition Block.h:33
OpListType::iterator iterator
Definition Block.h:150
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
iterator begin()
Definition Block.h:153
A class for computing basic dominance information.
Definition Dominance.h:143
bool dominates(Block *a, Block *b) const
Return true if the specified block A dominates block B, i.e.
Definition Dominance.h:177
bool properlyDominates(Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt, bool enclosingOk=true) const
Definition Dominance.h:194
bool dominates(Value a, Operation *b) const
Return true if the a value dominates operation b.
Definition Dominance.h:171
bool properlyDominates(Operation *a, Operation *b, bool enclosingOpOk=true) const
Return true if operation A properly dominates operation B, i.e.
bool dominates(Operation *a, Operation *b) const
Return true if operation A dominates operation B, i.e.
Definition Dominance.h:161
bool dominates(Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt, bool enclosingOk=true) const
Definition Dominance.h:199
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
A class for computing basic postdominance information.
Definition Dominance.h:207
bool properlyPostDominates(Operation *a, Operation *b, bool enclosingOpOk=true) const
Return true if operation A properly postdominates operation B.
bool postDominates(Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt, bool enclosingOk=true) const
Definition Dominance.h:234
bool properlyPostDominates(Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt, bool enclosingOk=true) const
Definition Dominance.h:228
bool postDominates(Operation *a, Operation *b) const
Return true if operation A postdominates operation B.
Definition Dominance.h:216
bool postDominates(Block *a, Block *b) const
Return true if the specified block A postdominates block B.
Definition Dominance.h:224
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
bool hasOneBlock()
Return true if this region has exactly one block.
Definition Region.h:68
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
llvm::PointerIntPair< DomTree *, 1, bool > getDominanceInfo(Region *region, bool needsDomTree) const
Return the dom tree and "hasSSADominance" bit for the given region.
Definition Dominance.cpp:62
DominanceInfoBase & operator=(const DominanceInfoBase &)=delete
DenseMap< Region *, llvm::PointerIntPair< DomTree *, 1, bool > > dominanceInfos
A mapping of regions to their base dominator tree and a cached "hasSSADominance" bit.
Definition Dominance.h:133
DominanceInfoBase< IsPostDom > super
Definition Dominance.h:111
DominanceInfoNode * getRootNode(Region *region)
Get the root dominance node of the given region.
Definition Dominance.h:77
bool hasSSADominance(Region *region) const
Return true if operations in the specified block are known to obey SSA dominance requirements.
Definition Dominance.h:100
DominanceInfoBase(const DominanceInfoBase &)=delete
DominanceInfoBase & operator=(DominanceInfoBase &&)=default
DomTree & getDomTree(Region *region) const
Definition Dominance.h:104
DominanceInfoBase(DominanceInfoBase &&)=default
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
Definition Dominance.h:85
bool isReachableFromEntry(Block *a) const
Return true if the specified block is reachable from the entry block of its region.
Block * findNearestCommonDominator(BlockRangeT &&blocks) const
Finds the nearest common dominator block for the given range of blocks.
Definition Dominance.h:63
DominanceInfoBase(Operation *op=nullptr)
Definition Dominance.h:39
bool properlyDominatesImpl(Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt, bool enclosingOk=true) const
Return "true" if block iterator A properly (post)dominates block iterator B.
Block * findNearestCommonDominator(Block *a, Block *b) const
Finds the nearest common dominator block for the two given blocks a and b.
bool hasSSADominance(Block *block) const
Return true if operations in the specified block are known to obey SSA dominance requirements.
Definition Dominance.h:95
void invalidate()
Invalidate dominance info.
Definition Dominance.cpp:37
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
AttrTypeReplacer.
Include the generated interface declarations.
llvm::DomTreeNodeBase< Block > DominanceInfoNode
Definition Dominance.h:30
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
mlir::DominanceInfoNode::const_iterator ChildIteratorType
Definition Dominance.h:259
static ChildIteratorType child_end(NodeRef N)
Definition Dominance.h:264
static ChildIteratorType child_begin(NodeRef N)
Definition Dominance.h:263
static ChildIteratorType child_end(NodeRef N)
Definition Dominance.h:254
static ChildIteratorType child_begin(NodeRef N)
Definition Dominance.h:253
mlir::DominanceInfoNode::const_iterator ChildIteratorType
Definition Dominance.h:249