MLIR  20.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 
25 extern template class llvm::DominatorTreeBase<mlir::Block, false>;
26 extern template class llvm::DominatorTreeBase<mlir::Block, true>;
27 extern template class llvm::DomTreeNodeBase<mlir::Block>;
28 
29 namespace mlir {
30 using DominanceInfoNode = llvm::DomTreeNodeBase<Block>;
31 class Operation;
32 
33 namespace detail {
34 template <bool IsPostDom>
36  using DomTree = llvm::DominatorTreeBase<Block, IsPostDom>;
37 
38 public:
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  void invalidate(Region *region);
51 
52  /// Finds the nearest common dominator block for the two given blocks a
53  /// and b. If no common dominator can be found, this function will return
54  /// nullptr.
55  Block *findNearestCommonDominator(Block *a, Block *b) const;
56 
57  /// Finds the nearest common dominator block for the given range of blocks.
58  /// If no common dominator can be found, this function will return nullptr.
59  template <typename BlockRangeT>
60  Block *findNearestCommonDominator(BlockRangeT &&blocks) const {
61  if (blocks.begin() == blocks.end())
62  return nullptr;
63  Block *dom = *blocks.begin();
64  for (auto it = ++blocks.begin(); it != blocks.end(); ++it) {
65  dom = findNearestCommonDominator(dom, *it);
66  if (!dom)
67  return nullptr;
68  }
69  return dom;
70  }
71 
72  /// Get the root dominance node of the given region. Note that this operation
73  /// is only defined for multi-block regions!
75  auto domInfo = getDominanceInfo(region, /*needsDomTree*/ true).getPointer();
76  assert(domInfo && "Region isn't multiblock");
77  return domInfo->getRootNode();
78  }
79 
80  /// Return the dominance node from the Region containing block A. This only
81  /// works for multi-block regions.
83  return getDomTree(a->getParent()).getNode(a);
84  }
85 
86  /// Return true if the specified block is reachable from the entry
87  /// block of its region.
88  bool isReachableFromEntry(Block *a) const;
89 
90  /// Return true if operations in the specified block are known to obey SSA
91  /// dominance requirements. False if the block is a graph region or unknown.
92  bool hasSSADominance(Block *block) const {
93  return hasSSADominance(block->getParent());
94  }
95  /// Return true if operations in the specified block are known to obey SSA
96  /// dominance requirements. False if the block is a graph region or unknown.
97  bool hasSSADominance(Region *region) const {
98  return getDominanceInfo(region, /*needsDomTree=*/false).getInt();
99  }
100 
101  DomTree &getDomTree(Region *region) const {
102  assert(!region->hasOneBlock() &&
103  "Can't get DomTree for single block regions");
104  return *getDominanceInfo(region, /*needsDomTree=*/true).getPointer();
105  }
106 
107 protected:
109 
110  /// Return the dom tree and "hasSSADominance" bit for the given region. The
111  /// DomTree will be null for single-block regions. This lazily constructs the
112  /// DomTree on demand when needsDomTree=true.
113  llvm::PointerIntPair<DomTree *, 1, bool>
114  getDominanceInfo(Region *region, bool needsDomTree) const;
115 
116  /// Return "true" if the specified block A properly (post)dominates block B.
117  bool properlyDominatesImpl(Block *a, Block *b) const;
118 
119  /// Return "true" if the specified op A properly (post)dominates op B.
120  bool properlyDominatesImpl(Operation *a, Operation *b,
121  bool enclosingOpOk = true) const;
122 
123  /// A mapping of regions to their base dominator tree and a cached
124  /// "hasSSADominance" bit. This map does not contain dominator trees for
125  /// single block CFG regions, but we do want to cache the "hasSSADominance"
126  /// bit for them. We may also not have computed the DomTree yet. In either
127  /// case, the DomTree is just null.
128  ///
131 };
132 
133 extern template class DominanceInfoBase</*IsPostDom=*/true>;
134 extern template class DominanceInfoBase</*IsPostDom=*/false>;
135 } // namespace detail
136 
137 /// A class for computing basic dominance information. Note that this
138 /// class is aware of different types of regions and returns a
139 /// region-kind specific concept of dominance. See RegionKindInterface.
140 class DominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/false> {
141 public:
142  using super::super;
143 
144  /// Return true if operation A properly dominates operation B, i.e. if A and B
145  /// are in the same block and A properly dominates B within the block, or if
146  /// the block that contains A properly dominates the block that contains B. In
147  /// an SSACFG region, Operation A dominates Operation B in the same block if A
148  /// preceeds B. In a Graph region, all operations in a block properly dominate
149  /// all operations in the same block.
150  ///
151  /// The `enclosingOpOk` flag says whether we should return true if the B op
152  /// is enclosed by a region on A.
154  bool enclosingOpOk = true) const {
155  return super::properlyDominatesImpl(a, b, enclosingOpOk);
156  }
157 
158  /// Return true if operation A dominates operation B, i.e. if A and B are the
159  /// same operation or A properly dominates B.
160  bool dominates(Operation *a, Operation *b) const {
161  return a == b || properlyDominates(a, b);
162  }
163 
164  /// Return true if the `a` value properly dominates operation `b`, i.e if the
165  /// operation that defines `a` properlyDominates `b` and the operation that
166  /// defines `a` does not contain `b`.
167  bool properlyDominates(Value a, Operation *b) const;
168 
169  /// Return true if the `a` value dominates operation `b`.
170  bool dominates(Value a, Operation *b) const {
171  return (Operation *)a.getDefiningOp() == b || properlyDominates(a, b);
172  }
173 
174  /// Return true if the specified block A dominates block B, i.e. if block A
175  /// and block B are the same block or block A properly dominates block B.
176  bool dominates(Block *a, Block *b) const {
177  return a == b || properlyDominates(a, b);
178  }
179 
180  /// Return true if the specified block A properly dominates block B, i.e.: if
181  /// block A contains block B, or if the region which contains block A also
182  /// contains block B or some parent of block B and block A dominates that
183  /// block in that kind of region.
184  ///
185  /// In an SSACFG region, block A dominates block B if all control flow paths
186  /// from the entry block to block B flow through block A.
187  ///
188  /// Graph regions have only a single block. To be consistent with "proper
189  /// dominance" of ops, the single block is considered to properly dominate
190  /// itself in a graph region.
191  bool properlyDominates(Block *a, Block *b) const {
192  return super::properlyDominatesImpl(a, b);
193  }
194 };
195 
196 /// A class for computing basic postdominance information.
197 class PostDominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/true> {
198 public:
199  using super::super;
200 
201  /// Return true if operation A properly postdominates operation B.
203  bool enclosingOpOk = true) const {
204  return super::properlyDominatesImpl(a, b, enclosingOpOk);
205  }
206 
207  /// Return true if operation A postdominates operation B.
208  bool postDominates(Operation *a, Operation *b) const {
209  return a == b || properlyPostDominates(a, b);
210  }
211 
212  /// Return true if the specified block A properly postdominates block B.
213  bool properlyPostDominates(Block *a, Block *b) const {
214  return super::properlyDominatesImpl(a, b);
215  }
216 
217  /// Return true if the specified block A postdominates block B.
218  bool postDominates(Block *a, Block *b) const {
219  return a == b || properlyPostDominates(a, b);
220  }
221 };
222 
223 } // namespace mlir
224 
225 namespace llvm {
226 
227 /// DominatorTree GraphTraits specialization so the DominatorTree can be
228 /// iterated by generic graph iterators.
229 template <>
230 struct GraphTraits<mlir::DominanceInfoNode *> {
231  using ChildIteratorType = mlir::DominanceInfoNode::const_iterator;
233 
234  static NodeRef getEntryNode(NodeRef N) { return N; }
235  static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
236  static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
237 };
238 
239 template <>
240 struct GraphTraits<const mlir::DominanceInfoNode *> {
241  using ChildIteratorType = mlir::DominanceInfoNode::const_iterator;
243 
244  static NodeRef getEntryNode(NodeRef N) { return N; }
245  static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
246  static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
247 };
248 
249 } // namespace llvm
250 #endif
Block represents an ordered list of Operations.
Definition: Block.h:33
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition: Block.cpp:29
iterator begin()
Definition: Block.h:143
A class for computing basic dominance information.
Definition: Dominance.h:140
bool dominates(Block *a, Block *b) const
Return true if the specified block A dominates block B, i.e.
Definition: Dominance.h:176
bool dominates(Value a, Operation *b) const
Return true if the a value dominates operation b.
Definition: Dominance.h:170
bool properlyDominates(Operation *a, Operation *b, bool enclosingOpOk=true) const
Return true if operation A properly dominates operation B, i.e.
Definition: Dominance.h:153
bool properlyDominates(Block *a, Block *b) const
Return true if the specified block A properly dominates block B, i.e.
Definition: Dominance.h:191
bool dominates(Operation *a, Operation *b) const
Return true if operation A dominates operation B, i.e.
Definition: Dominance.h:160
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
A class for computing basic postdominance information.
Definition: Dominance.h:197
bool properlyPostDominates(Block *a, Block *b) const
Return true if the specified block A properly postdominates block B.
Definition: Dominance.h:213
bool postDominates(Operation *a, Operation *b) const
Return true if operation A postdominates operation B.
Definition: Dominance.h:208
bool properlyPostDominates(Operation *a, Operation *b, bool enclosingOpOk=true) const
Return true if operation A properly postdominates operation B.
Definition: Dominance.h:202
bool postDominates(Block *a, Block *b) const
Return true if the specified block A postdominates block B.
Definition: Dominance.h:218
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:20
Block * findNearestCommonDominator(BlockRangeT &&blocks) const
Finds the nearest common dominator block for the given range of blocks.
Definition: Dominance.h:60
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:130
bool hasSSADominance(Region *region) const
Return true if operations in the specified block are known to obey SSA dominance requirements.
Definition: Dominance.h:97
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
Definition: Dominance.h:82
DominanceInfoBase(const DominanceInfoBase &)=delete
DominanceInfoBase & operator=(DominanceInfoBase &&)=default
DominanceInfoBase(DominanceInfoBase &&)=default
DominanceInfoBase & operator=(const DominanceInfoBase &)=delete
DominanceInfoBase(Operation *op=nullptr)
Definition: Dominance.h:39
DominanceInfoNode * getRootNode(Region *region)
Get the root dominance node of the given region.
Definition: Dominance.h:74
bool hasSSADominance(Block *block) const
Return true if operations in the specified block are known to obey SSA dominance requirements.
Definition: Dominance.h:92
DomTree & getDomTree(Region *region) const
Definition: Dominance.h:101
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
Include the generated interface declarations.
llvm::DomTreeNodeBase< Block > DominanceInfoNode
Definition: Dominance.h:30
const mlir::DominanceInfoNode * NodeRef
Definition: Dominance.h:242
mlir::DominanceInfoNode::const_iterator ChildIteratorType
Definition: Dominance.h:241
static ChildIteratorType child_end(NodeRef N)
Definition: Dominance.h:246
static ChildIteratorType child_begin(NodeRef N)
Definition: Dominance.h:245
static ChildIteratorType child_end(NodeRef N)
Definition: Dominance.h:236
static ChildIteratorType child_begin(NodeRef N)
Definition: Dominance.h:235
mlir::DominanceInfoNode::const_iterator ChildIteratorType
Definition: Dominance.h:231
static NodeRef getEntryNode(NodeRef N)
Definition: Dominance.h:234