MLIR 23.0.0git
Region.h
Go to the documentation of this file.
1//===- Region.h - MLIR Region Class -----------------------------*- 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// This file defines the Region class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_IR_REGION_H
14#define MLIR_IR_REGION_H
15
16#include "mlir/IR/Block.h"
17
18namespace mlir {
19class TypeRange;
20template <typename ValueRangeT>
21class ValueTypeRange;
22class IRMapping;
23
24/// This class contains a list of basic blocks and a link to the parent
25/// operation it is attached to.
26class Region {
27public:
28 Region() = default;
29 explicit Region(Operation *container);
30 ~Region();
31
32 /// Return the context this region is inserted in. The region must have a
33 /// valid parent container.
35
36 /// Return a location for this region. This is the location attached to the
37 /// parent container. The region must have a valid parent container.
39
40 //===--------------------------------------------------------------------===//
41 // Block list management
42 //===--------------------------------------------------------------------===//
43
44 using BlockListType = llvm::iplist<Block>;
45 BlockListType &getBlocks() { return blocks; }
47 push_back(new Block);
48 return back();
49 }
50
51 // Iteration over the blocks in the region.
52 using iterator = BlockListType::iterator;
53 using reverse_iterator = BlockListType::reverse_iterator;
54
55 iterator begin() { return blocks.begin(); }
56 iterator end() { return blocks.end(); }
57 reverse_iterator rbegin() { return blocks.rbegin(); }
58 reverse_iterator rend() { return blocks.rend(); }
59
60 bool empty() { return blocks.empty(); }
61 void push_back(Block *block) { blocks.push_back(block); }
62 void push_front(Block *block) { blocks.push_front(block); }
63
64 Block &back() { return blocks.back(); }
65 Block &front() { return blocks.front(); }
66
67 /// Return true if this region has exactly one block.
68 bool hasOneBlock() { return !empty() && std::next(begin()) == end(); }
69
70 /// getSublistAccess() - Returns pointer to member of region.
72 return &Region::blocks;
73 }
74
75 //===--------------------------------------------------------------------===//
76 // Block numbering
77 //===--------------------------------------------------------------------===//
78
79 /// One past the largest block ID handed out in this region; block IDs lie in
80 /// [0, getMaxBlockID()). See Block::getBlockID().
81 unsigned getMaxBlockID() const { return nextBlockID; }
82
83 /// The block-ID epoch, part of the generic number-indexed graph contract
84 /// (LoopInfo, DominatorTree) for detecting stale IDs. MLIR never renumbers a
85 /// region's blocks, so this is a fixed 0. See Block::getBlockID().
86 unsigned getBlockIDEpoch() const { return 0; }
87
88 //===--------------------------------------------------------------------===//
89 // Argument Handling
90 //===--------------------------------------------------------------------===//
91
92 // This is the list of arguments to the block.
97
98 /// Returns the argument types of the first block within the region.
100
101 using args_iterator = BlockArgListType::iterator;
102 using reverse_args_iterator = BlockArgListType::reverse_iterator;
103 args_iterator args_begin() { return getArguments().begin(); }
104 args_iterator args_end() { return getArguments().end(); }
107
108 bool args_empty() { return getArguments().empty(); }
109
110 /// Add one value to the argument list.
112 return front().addArgument(type, loc);
113 }
114
115 /// Insert one value to the position in the argument list indicated by the
116 /// given iterator. The existing arguments are shifted. The block is expected
117 /// not to have predecessors.
119 return front().insertArgument(it, type, loc);
120 }
121
122 /// Add one argument to the argument list for each type specified in the list.
123 /// `locs` contains the locations for each of the new arguments, and must be
124 /// of equal size to `types`.
126 ArrayRef<Location> locs);
127
128 /// Add one value to the argument list at the specified position.
130 return front().insertArgument(index, type, loc);
131 }
132
133 /// Erase the argument at 'index' and remove it from the argument list.
135
136 unsigned getNumArguments() { return getArguments().size(); }
137 BlockArgument getArgument(unsigned i) { return getArguments()[i]; }
138
139 //===--------------------------------------------------------------------===//
140 // Operation list utilities
141 //===--------------------------------------------------------------------===//
142
143 /// This class provides iteration over the held operations of blocks directly
144 /// within a region.
145 class OpIterator final
146 : public llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
147 Operation> {
148 public:
149 /// Initialize OpIterator for a region, specify `end` to return the iterator
150 /// to last operation.
151 explicit OpIterator(Region *region, bool end = false);
152
153 using llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
154 Operation>::operator++;
156 Operation *operator->() const { return &*operation; }
157 Operation &operator*() const { return *operation; }
158
159 /// Compare this iterator with another.
160 bool operator==(const OpIterator &rhs) const {
161 return operation == rhs.operation;
162 }
163 bool operator!=(const OpIterator &rhs) const { return !(*this == rhs); }
164
165 private:
166 void skipOverBlocksWithNoOps();
167
168 /// The region whose operations are being iterated over.
169 Region *region;
170 /// The block of 'region' whose operations are being iterated over.
171 Region::iterator block;
172 /// The current operation within 'block'.
173 Block::iterator operation;
174 };
175
176 /// This class provides iteration over the held operations of a region for a
177 /// specific operation type.
178 template <typename OpT>
180
181 /// Return iterators that walk the operations nested directly within this
182 /// region.
183 OpIterator op_begin() { return OpIterator(this); }
184 OpIterator op_end() { return OpIterator(this, /*end=*/true); }
186
187 /// Return iterators that walk operations of type 'T' nested directly within
188 /// this region.
189 template <typename OpT>
193 template <typename OpT>
197 template <typename OpT>
203
204 //===--------------------------------------------------------------------===//
205 // Misc. utilities
206 //===--------------------------------------------------------------------===//
207
208 /// Return the region containing this region or nullptr if the region is
209 /// attached to a top-level operation.
211
212 /// Return the parent operation this region is attached to.
213 Operation *getParentOp() { return container; }
214
215 /// Find the first parent operation of the given type, or nullptr if there is
216 /// no ancestor operation.
217 template <typename ParentT>
218 ParentT getParentOfType() {
219 auto *region = this;
220 do {
221 if (auto parent = dyn_cast_or_null<ParentT>(region->container))
222 return parent;
223 } while ((region = region->getParentRegion()));
224 return ParentT();
225 }
226 template <typename... ParentT>
227 std::enable_if_t<(sizeof...(ParentT) > 1), Operation *> getParentOfType() {
228 auto *region = this;
229 do {
230 if (!region->container)
231 return nullptr;
232 if (isa<ParentT...>(region->container))
233 return region->container;
234 } while ((region = region->getParentRegion()));
235 return nullptr;
236 }
237
238 /// Return the number of this region in the parent operation.
239 unsigned getRegionNumber();
240
241 /// Return true if this region is a proper ancestor of the `other` region.
242 bool isProperAncestor(Region *other);
243
244 /// Return true if this region is ancestor of the `other` region. A region
245 /// is considered as its own ancestor, use `isProperAncestor` to avoid this.
246 bool isAncestor(Region *other) {
247 return this == other || isProperAncestor(other);
248 }
249
250 /// Clone the internal blocks from this region into dest. Any
251 /// cloned blocks are appended to the back of dest. If the mapper
252 /// contains entries for block arguments, these arguments are not included
253 /// in the respective cloned block.
254 ///
255 /// Calling this method from multiple threads is generally safe if through the
256 /// process of cloning, no new uses of 'Value's from outside the region are
257 /// created. Using the mapper, it is possible to avoid adding uses to outside
258 /// operands by remapping them to 'Value's owned by the caller thread.
259 void cloneInto(Region *dest, IRMapping &mapper);
260 /// Clone this region into 'dest' before the given position in 'dest'.
261 void cloneInto(Region *dest, Region::iterator destPos, IRMapping &mapper);
262
263 /// Takes body of another region (that region will have no body after this
264 /// operation completes). The current body of this region is cleared.
265 void takeBody(Region &other) {
267 blocks.clear();
268 blocks.splice(blocks.end(), other.getBlocks());
269 }
270
271 /// Returns 'block' if 'block' lies in this region, or otherwise finds the
272 /// ancestor of 'block' that lies in this region. Returns nullptr if the
273 /// latter fails.
275
276 /// Returns 'op' if 'op' lies in this region, or otherwise finds the
277 /// ancestor of 'op' that lies in this region. Returns nullptr if the
278 /// latter fails.
280
281 /// Drop all operand uses from operations within this region, which is
282 /// an essential step in breaking cyclic dependences between references when
283 /// they are to be deleted.
284 void dropAllReferences();
285
286 //===--------------------------------------------------------------------===//
287 // Walkers
288 //===--------------------------------------------------------------------===//
289
290 /// Walk all nested operations, blocks or regions (including this region),
291 /// depending on the type of callback.
292 ///
293 /// The order in which operations, blocks or regions at the same nesting
294 /// level are visited (e.g., lexicographical or reverse lexicographical order)
295 /// is determined by `Iterator`. The walk order for enclosing operations,
296 /// blocks or regions with respect to their nested ones is specified by
297 /// `Order` (post-order by default).
298 ///
299 /// A callback on a operation or block is allowed to erase that operation or
300 /// block if either:
301 /// * the walk is in post-order, or
302 /// * the walk is in pre-order and the walk is skipped after the erasure.
303 ///
304 /// See Operation::walk for more details.
305 template <WalkOrder Order = WalkOrder::PostOrder,
306 typename Iterator = ForwardIterator, typename FnT,
307 typename ArgT = detail::first_argument<FnT>,
308 typename RetT = detail::walkResultType<FnT>>
309 RetT walk(FnT &&callback) {
310 if constexpr (std::is_same<ArgT, Region *>::value &&
311 Order == WalkOrder::PreOrder) {
312 // Pre-order walk on regions: invoke the callback on this region.
313 if constexpr (std::is_same<RetT, void>::value) {
314 callback(this);
315 } else {
316 RetT result = callback(this);
317 if (result.wasSkipped())
318 return WalkResult::advance();
319 if (result.wasInterrupted())
320 return WalkResult::interrupt();
321 }
322 }
323
324 // Walk nested operations, blocks or regions.
325 for (auto &block : *this) {
326 if constexpr (std::is_same<RetT, void>::value) {
327 block.walk<Order, Iterator>(callback);
328 } else {
329 if (block.walk<Order, Iterator>(callback).wasInterrupted())
330 return WalkResult::interrupt();
331 }
332 }
333
334 if constexpr (std::is_same<ArgT, Region *>::value &&
335 Order == WalkOrder::PostOrder) {
336 // Post-order walk on regions: invoke the callback on this block.
337 return callback(this);
338 }
339 if constexpr (!std::is_same<RetT, void>::value)
340 return WalkResult::advance();
341 }
342
343 //===--------------------------------------------------------------------===//
344 // CFG view utilities
345 //===--------------------------------------------------------------------===//
346
347 /// Displays the CFG in a window. This is for use from the debugger and
348 /// depends on Graphviz to generate the graph.
349 /// This function is defined in ViewOpGraph.cpp and only works with that
350 /// target linked.
351 void viewGraph(const Twine &regionName);
352 void viewGraph();
353
354private:
355 BlockListType blocks;
356
357 /// This is the object we are part of.
358 Operation *container = nullptr;
359
360 /// Next block ID to hand out. See Block::getBlockID().
361 unsigned nextBlockID = 0;
362
363 friend struct llvm::ilist_traits<Block>;
364};
365
366/// This class provides an abstraction over the different types of ranges over
367/// Regions. In many cases, this prevents the need to explicitly materialize a
368/// SmallVector/std::vector. This class should be used in places that are not
369/// suitable for a more derived type (e.g. ArrayRef) or a template range
370/// parameter.
373 RegionRange,
374 PointerUnion<Region *, const std::unique_ptr<Region> *, Region **>,
375 Region *, Region *, Region *> {
376 /// The type representing the owner of this range. This is either an owning
377 /// list of regions, a list of region unique pointers, or a list of region
378 /// pointers.
379 using OwnerT =
381
382public:
383 using RangeBaseT::RangeBaseT;
384
386
387 template <typename Arg, typename = std::enable_if_t<std::is_constructible<
389 RegionRange(Arg &&arg LLVM_LIFETIME_BOUND)
390 : RegionRange(ArrayRef<std::unique_ptr<Region>>(std::forward<Arg>(arg))) {
391 }
392 template <typename Arg>
394 Arg &&arg LLVM_LIFETIME_BOUND,
395 std::enable_if_t<std::is_constructible<ArrayRef<Region *>, Arg>::value>
396 * = nullptr)
397 : RegionRange(ArrayRef<Region *>(std::forward<Arg>(arg))) {}
398 RegionRange(ArrayRef<std::unique_ptr<Region>> regions);
400
401private:
402 /// See `llvm::detail::indexed_accessor_range_base` for details.
403 static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
404 /// See `llvm::detail::indexed_accessor_range_base` for details.
405 static Region *dereference_iterator(const OwnerT &owner, ptrdiff_t index);
406
407 /// Allow access to `offset_base` and `dereference_iterator`.
408 friend RangeBaseT;
409};
410
411llvm::raw_ostream &operator<<(llvm::raw_ostream &os, Region &region);
412
413} // namespace mlir
414
415#endif // MLIR_IR_REGION_H
This class represents an argument of a Block.
Definition Value.h:306
Block represents an ordered list of Operations.
Definition Block.h:33
OpListType::iterator iterator
Definition Block.h:164
BlockArgument insertArgument(args_iterator it, Type type, Location loc)
Insert one value to the position in the argument list indicated by the given iterator.
Definition Block.cpp:192
Operation & front()
Definition Block.h:177
Operation & back()
Definition Block.h:176
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
BlockArgListType getArguments()
Definition Block.h:111
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition Block.cpp:198
This is a utility class for mapping one set of IR entities to another.
Definition IRMapping.h:26
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
RegionRange(Arg &&arg LLVM_LIFETIME_BOUND)
Definition Region.h:389
RegionRange(Arg &&arg LLVM_LIFETIME_BOUND, std::enable_if_t< std::is_constructible< ArrayRef< Region * >, Arg >::value > *=nullptr)
Definition Region.h:393
RegionRange(MutableArrayRef< Region > regions={})
Definition Region.cpp:282
This class provides iteration over the held operations of blocks directly within a region.
Definition Region.h:147
OpIterator(Region *region, bool end=false)
Initialize OpIterator for a region, specify end to return the iterator to last operation.
Definition Region.cpp:233
bool operator==(const OpIterator &rhs) const
Compare this iterator with another.
Definition Region.h:160
Operation & operator*() const
Definition Region.h:157
OpIterator & operator++()
Definition Region.cpp:239
Operation * operator->() const
Definition Region.h:156
bool operator!=(const OpIterator &rhs) const
Definition Region.h:163
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
unsigned getMaxBlockID() const
One past the largest block ID handed out in this region; block IDs lie in [0, getMaxBlockID()).
Definition Region.h:81
llvm::iplist< Block > BlockListType
Definition Region.h:44
Block & front()
Definition Region.h:65
Region * getParentRegion()
Return the region containing this region or nullptr if the region is attached to a top-level operatio...
Definition Region.cpp:45
reverse_args_iterator args_rend()
Definition Region.h:106
BlockArgument insertArgument(args_iterator it, Type type, Location loc)
Insert one value to the position in the argument list indicated by the given iterator.
Definition Region.h:118
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition Region.h:134
BlockArgListType getArguments()
Definition Region.h:94
args_iterator args_begin()
Definition Region.h:103
iterator_range< op_iterator< OpT > > getOps()
Definition Region.h:198
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
Definition Region.cpp:41
reverse_iterator rend()
Definition Region.h:58
detail::op_iterator< OpT, OpIterator > op_iterator
This class provides iteration over the held operations of a region for a specific operation type.
Definition Region.h:179
Operation * findAncestorOpInRegion(Operation &op)
Returns 'op' if 'op' lies in this region, or otherwise finds the ancestor of 'op' that lies in this r...
Definition Region.cpp:168
unsigned getRegionNumber()
Return the number of this region in the parent operation.
Definition Region.cpp:62
OpIterator op_begin()
Return iterators that walk the operations nested directly within this region.
Definition Region.h:183
void dropAllReferences()
Drop all operand uses from operations within this region, which is an essential step in breaking cycl...
Definition Region.cpp:181
Block & emplaceBlock()
Definition Region.h:46
bool isAncestor(Region *other)
Return true if this region is ancestor of the other region.
Definition Region.h:246
void push_back(Block *block)
Definition Region.h:61
BlockArgListType::iterator args_iterator
Definition Region.h:101
iterator_range< OpIterator > getOps()
Definition Region.h:185
BlockArgument insertArgument(unsigned index, Type type, Location loc)
Add one value to the argument list at the specified position.
Definition Region.h:129
static BlockListType Region::* getSublistAccess(Block *)
getSublistAccess() - Returns pointer to member of region.
Definition Region.h:71
op_iterator< OpT > op_begin()
Return iterators that walk operations of type 'T' nested directly within this region.
Definition Region.h:190
Block & back()
Definition Region.h:64
bool empty()
Definition Region.h:60
BlockListType::reverse_iterator reverse_iterator
Definition Region.h:53
void cloneInto(Region *dest, IRMapping &mapper)
Clone the internal blocks from this region into dest.
Definition Region.cpp:70
iterator end()
Definition Region.h:56
args_iterator args_end()
Definition Region.h:104
bool isProperAncestor(Region *other)
Return true if this region is a proper ancestor of the other region.
Definition Region.cpp:50
unsigned getNumArguments()
Definition Region.h:136
iterator begin()
Definition Region.h:55
Region()=default
Location getLoc()
Return a location for this region.
Definition Region.cpp:31
ValueTypeRange< BlockArgListType > getArgumentTypes()
Returns the argument types of the first block within the region.
Definition Region.cpp:36
BlockArgument getArgument(unsigned i)
Definition Region.h:137
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition Region.h:213
MutableArrayRef< BlockArgument > BlockArgListType
Definition Region.h:93
MLIRContext * getContext()
Return the context this region is inserted in.
Definition Region.cpp:24
BlockListType & getBlocks()
Definition Region.h:45
reverse_args_iterator args_rbegin()
Definition Region.h:105
OpIterator op_end()
Definition Region.h:184
BlockListType::iterator iterator
Definition Region.h:52
void push_front(Block *block)
Definition Region.h:62
void takeBody(Region &other)
Takes body of another region (that region will have no body after this operation completes).
Definition Region.h:265
reverse_iterator rbegin()
Definition Region.h:57
op_iterator< OpT > op_end()
Definition Region.h:194
ParentT getParentOfType()
Find the first parent operation of the given type, or nullptr if there is no ancestor operation.
Definition Region.h:218
Block * findAncestorBlockInRegion(Block &block)
Returns 'block' if 'block' lies in this region, or otherwise finds the ancestor of 'block' that lies ...
Definition Region.cpp:154
bool args_empty()
Definition Region.h:108
std::enable_if_t<(sizeof...(ParentT) > 1), Operation * > getParentOfType()
Definition Region.h:227
BlockArgListType::reverse_iterator reverse_args_iterator
Definition Region.h:102
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Region.h:111
bool hasOneBlock()
Return true if this region has exactly one block.
Definition Region.h:68
RetT walk(FnT &&callback)
Walk all nested operations, blocks or regions (including this region), depending on the type of callb...
Definition Region.h:309
unsigned getBlockIDEpoch() const
The block-ID epoch, part of the generic number-indexed graph contract (LoopInfo, DominatorTree) for d...
Definition Region.h:86
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:40
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class implements iteration on the types of a given range of values.
Definition TypeRange.h:147
static WalkResult advance()
Definition WalkResult.h:47
static WalkResult interrupt()
Definition WalkResult.h:46
A utility iterator that filters out operations that are not 'OpT'.
This class provides iteration over the held operations of a block for a specific operation type.
decltype(first_argument_type(std::declval< T >())) first_argument
Type definition of the first argument to the given callable 'T'.
Definition Visitors.h:90
decltype(walk(nullptr, std::declval< FnT >())) walkResultType
Utility to provide the return type of a templated walk method.
Definition Visitors.h:433
Include the generated interface declarations.
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition Visitors.h:28
This iterator enumerates the elements in "forward" order.
Definition Visitors.h:31