MLIR  16.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 
18 namespace mlir {
19 class TypeRange;
20 template <typename ValueRangeT>
21 class ValueTypeRange;
22 class BlockAndValueMapping;
23 
24 /// This class contains a list of basic blocks and a link to the parent
25 /// operation it is attached to.
26 class Region {
27 public:
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.
38  Location getLoc();
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  // Argument Handling
77  //===--------------------------------------------------------------------===//
78 
79  // This is the list of arguments to the block.
82  return empty() ? BlockArgListType() : front().getArguments();
83  }
84 
85  /// Returns the argument types of the first block within the region.
87 
88  using args_iterator = BlockArgListType::iterator;
89  using reverse_args_iterator = BlockArgListType::reverse_iterator;
90  args_iterator args_begin() { return getArguments().begin(); }
91  args_iterator args_end() { return getArguments().end(); }
94 
95  bool args_empty() { return getArguments().empty(); }
96 
97  /// Add one value to the argument list.
99  return front().addArgument(type, loc);
100  }
101 
102  /// Insert one value to the position in the argument list indicated by the
103  /// given iterator. The existing arguments are shifted. The block is expected
104  /// not to have predecessors.
106  return front().insertArgument(it, type, loc);
107  }
108 
109  /// Add one argument to the argument list for each type specified in the list.
110  /// `locs` contains the locations for each of the new arguments, and must be
111  /// of equal size to `types`.
113  ArrayRef<Location> locs);
114 
115  /// Add one value to the argument list at the specified position.
116  BlockArgument insertArgument(unsigned index, Type type, Location loc) {
117  return front().insertArgument(index, type, loc);
118  }
119 
120  /// Erase the argument at 'index' and remove it from the argument list.
121  void eraseArgument(unsigned index) { front().eraseArgument(index); }
122 
123  unsigned getNumArguments() { return getArguments().size(); }
124  BlockArgument getArgument(unsigned i) { return getArguments()[i]; }
125 
126  //===--------------------------------------------------------------------===//
127  // Operation list utilities
128  //===--------------------------------------------------------------------===//
129 
130  /// This class provides iteration over the held operations of blocks directly
131  /// within a region.
132  class OpIterator final
133  : public llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
134  Operation> {
135  public:
136  /// Initialize OpIterator for a region, specify `end` to return the iterator
137  /// to last operation.
138  explicit OpIterator(Region *region, bool end = false);
139 
140  using llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
141  Operation>::operator++;
143  Operation *operator->() const { return &*operation; }
144  Operation &operator*() const { return *operation; }
145 
146  /// Compare this iterator with another.
147  bool operator==(const OpIterator &rhs) const {
148  return operation == rhs.operation;
149  }
150  bool operator!=(const OpIterator &rhs) const { return !(*this == rhs); }
151 
152  private:
153  void skipOverBlocksWithNoOps();
154 
155  /// The region whose operations are being iterated over.
156  Region *region;
157  /// The block of 'region' whose operations are being iterated over.
158  Region::iterator block;
159  /// The current operation within 'block'.
160  Block::iterator operation;
161  };
162 
163  /// This class provides iteration over the held operations of a region for a
164  /// specific operation type.
165  template <typename OpT>
167 
168  /// Return iterators that walk the operations nested directly within this
169  /// region.
170  OpIterator op_begin() { return OpIterator(this); }
171  OpIterator op_end() { return OpIterator(this, /*end=*/true); }
173 
174  /// Return iterators that walk operations of type 'T' nested directly within
175  /// this region.
176  template <typename OpT>
179  }
180  template <typename OpT>
183  }
184  template <typename OpT>
186  auto endIt = op_end();
189  }
190 
191  //===--------------------------------------------------------------------===//
192  // Misc. utilities
193  //===--------------------------------------------------------------------===//
194 
195  /// Return the region containing this region or nullptr if the region is
196  /// attached to a top-level operation.
198 
199  /// Return the parent operation this region is attached to.
200  Operation *getParentOp() { return container; }
201 
202  /// Find the first parent operation of the given type, or nullptr if there is
203  /// no ancestor operation.
204  template <typename ParentT>
205  ParentT getParentOfType() {
206  auto *region = this;
207  do {
208  if (auto parent = dyn_cast_or_null<ParentT>(region->container))
209  return parent;
210  } while ((region = region->getParentRegion()));
211  return ParentT();
212  }
213 
214  /// Return the number of this region in the parent operation.
215  unsigned getRegionNumber();
216 
217  /// Return true if this region is a proper ancestor of the `other` region.
218  bool isProperAncestor(Region *other);
219 
220  /// Return true if this region is ancestor of the `other` region. A region
221  /// is considered as its own ancestor, use `isProperAncestor` to avoid this.
222  bool isAncestor(Region *other) {
223  return this == other || isProperAncestor(other);
224  }
225 
226  /// Clone the internal blocks from this region into dest. Any
227  /// cloned blocks are appended to the back of dest. If the mapper
228  /// contains entries for block arguments, these arguments are not included
229  /// in the respective cloned block.
230  ///
231  /// Calling this method from multiple threads is generally safe if through the
232  /// process of cloning, no new uses of 'Value's from outside the region are
233  /// created. Using the mapper, it is possible to avoid adding uses to outside
234  /// operands by remapping them to 'Value's owned by the caller thread.
235  void cloneInto(Region *dest, BlockAndValueMapping &mapper);
236  /// Clone this region into 'dest' before the given position in 'dest'.
237  void cloneInto(Region *dest, Region::iterator destPos,
238  BlockAndValueMapping &mapper);
239 
240  /// Takes body of another region (that region will have no body after this
241  /// operation completes). The current body of this region is cleared.
242  void takeBody(Region &other) {
244  blocks.clear();
245  blocks.splice(blocks.end(), other.getBlocks());
246  }
247 
248  /// Returns 'block' if 'block' lies in this region, or otherwise finds the
249  /// ancestor of 'block' that lies in this region. Returns nullptr if the
250  /// latter fails.
252 
253  /// Returns 'op' if 'op' lies in this region, or otherwise finds the
254  /// ancestor of 'op' that lies in this region. Returns nullptr if the
255  /// latter fails.
257 
258  /// Drop all operand uses from operations within this region, which is
259  /// an essential step in breaking cyclic dependences between references when
260  /// they are to be deleted.
261  void dropAllReferences();
262 
263  //===--------------------------------------------------------------------===//
264  // Operation Walkers
265  //===--------------------------------------------------------------------===//
266 
267  /// Walk the operations in this region. The callback method is called for each
268  /// nested region, block or operation, depending on the callback provided.
269  /// Regions, blocks and operations at the same nesting level are visited in
270  /// lexicographical order. The walk order for enclosing regions, blocks and
271  /// operations with respect to their nested ones is specified by 'Order'
272  /// (post-order by default). This method is invoked for void-returning
273  /// callbacks. A callback on a block or operation is allowed to erase that
274  /// block or operation only if the walk is in post-order. See non-void method
275  /// for pre-order erasure. See Operation::walk for more details.
276  template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
277  typename RetT = detail::walkResultType<FnT>>
279  for (auto &block : *this)
280  block.walk<Order>(callback);
281  }
282 
283  /// Walk the operations in this region. The callback method is called for each
284  /// nested region, block or operation, depending on the callback provided.
285  /// Regions, blocks and operations at the same nesting level are visited in
286  /// lexicographical order. The walk order for enclosing regions, blocks and
287  /// operations with respect to their nested ones is specified by 'Order'
288  /// (post-order by default). This method is invoked for skippable or
289  /// interruptible callbacks. A callback on a block or operation is allowed to
290  /// erase that block or operation if either:
291  /// * the walk is in post-order,
292  /// * or the walk is in pre-order and the walk is skipped after the erasure.
293  /// See Operation::walk for more details.
294  template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
295  typename RetT = detail::walkResultType<FnT>>
297  walk(FnT &&callback) {
298  for (auto &block : *this)
299  if (block.walk<Order>(callback).wasInterrupted())
300  return WalkResult::interrupt();
301  return WalkResult::advance();
302  }
303 
304  //===--------------------------------------------------------------------===//
305  // CFG view utilities
306  //===--------------------------------------------------------------------===//
307 
308  /// Displays the CFG in a window. This is for use from the debugger and
309  /// depends on Graphviz to generate the graph.
310  /// This function is defined in ViewOpGraph.cpp and only works with that
311  /// target linked.
312  void viewGraph(const Twine &regionName);
313  void viewGraph();
314 
315 private:
316  BlockListType blocks;
317 
318  /// This is the object we are part of.
319  Operation *container = nullptr;
320 };
321 
322 /// This class provides an abstraction over the different types of ranges over
323 /// Regions. In many cases, this prevents the need to explicitly materialize a
324 /// SmallVector/std::vector. This class should be used in places that are not
325 /// suitable for a more derived type (e.g. ArrayRef) or a template range
326 /// parameter.
329  RegionRange,
330  PointerUnion<Region *, const std::unique_ptr<Region> *, Region **>,
331  Region *, Region *, Region *> {
332  /// The type representing the owner of this range. This is either an owning
333  /// list of regions, a list of region unique pointers, or a list of region
334  /// pointers.
335  using OwnerT =
337 
338 public:
339  using RangeBaseT::RangeBaseT;
340 
341  RegionRange(MutableArrayRef<Region> regions = llvm::None);
342 
343  template <typename Arg, typename = std::enable_if_t<std::is_constructible<
345  RegionRange(Arg &&arg)
346  : RegionRange(ArrayRef<std::unique_ptr<Region>>(std::forward<Arg>(arg))) {
347  }
348  template <typename Arg>
350  Arg &&arg,
351  std::enable_if_t<std::is_constructible<ArrayRef<Region *>, Arg>::value>
352  * = nullptr)
353  : RegionRange(ArrayRef<Region *>(std::forward<Arg>(arg))) {}
354  RegionRange(ArrayRef<std::unique_ptr<Region>> regions);
356 
357 private:
358  /// See `llvm::detail::indexed_accessor_range_base` for details.
359  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
360  /// See `llvm::detail::indexed_accessor_range_base` for details.
361  static Region *dereference_iterator(const OwnerT &owner, ptrdiff_t index);
362 
363  /// Allow access to `offset_base` and `dereference_iterator`.
364  friend RangeBaseT;
365 };
366 
367 } // namespace mlir
368 
369 #endif // MLIR_IR_REGION_H
static constexpr const bool value
This class represents an argument of a Block.
Definition: Value.h:296
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType::iterator iterator
Definition: Block.h:129
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:175
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:141
BlockArgListType getArguments()
Definition: Block.h:76
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition: Block.cpp:181
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:64
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:31
This class provides an abstraction over the different types of ranges over Regions.
Definition: Region.h:331
RegionRange(Arg &&arg, std::enable_if_t< std::is_constructible< ArrayRef< Region * >, Arg >::value > *=nullptr)
Definition: Region.h:349
RegionRange(Arg &&arg)
Definition: Region.h:345
RegionRange(MutableArrayRef< Region > regions=llvm::None)
Definition: Region.cpp:260
This class provides iteration over the held operations of blocks directly within a region.
Definition: Region.h:134
Operation & operator*() const
Definition: Region.h:144
OpIterator(Region *region, bool end=false)
Initialize OpIterator for a region, specify end to return the iterator to last operation.
Definition: Region.cpp:226
bool operator==(const OpIterator &rhs) const
Compare this iterator with another.
Definition: Region.h:147
Operation * operator->() const
Definition: Region.h:143
OpIterator & operator++()
Definition: Region.cpp:232
bool operator!=(const OpIterator &rhs) const
Definition: Region.h:150
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
iterator_range< OpIterator > getOps()
Definition: Region.h:172
llvm::iplist< Block > BlockListType
Definition: Region.h:44
std::enable_if_t< std::is_same< RetT, WalkResult >::value, RetT > walk(FnT &&callback)
Walk the operations in this region.
Definition: Region.h:297
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:93
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:105
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition: Region.h:121
BlockArgListType getArguments()
Definition: Region.h:81
op_iterator< OpT > op_begin()
Return iterators that walk operations of type 'T' nested directly within this region.
Definition: Region.h:177
args_iterator args_begin()
Definition: Region.h:90
iterator_range< op_iterator< OpT > > getOps()
Definition: Region.h:185
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
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:170
void dropAllReferences()
Drop all operand uses from operations within this region, which is an essential step in breaking cycl...
Definition: Region.cpp:181
bool isAncestor(Region *other)
Return true if this region is ancestor of the other region.
Definition: Region.h:222
void push_back(Block *block)
Definition: Region.h:61
BlockArgListType::iterator args_iterator
Definition: Region.h:88
BlockArgument insertArgument(unsigned index, Type type, Location loc)
Add one value to the argument list at the specified position.
Definition: Region.h:116
static BlockListType Region::* getSublistAccess(Block *)
getSublistAccess() - Returns pointer to member of region.
Definition: Region.h:71
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition: Region.h:200
op_iterator< OpT > op_end()
Definition: Region.h:181
bool empty()
Definition: Region.h:60
BlockListType::reverse_iterator reverse_iterator
Definition: Region.h:53
iterator end()
Definition: Region.h:56
args_iterator args_end()
Definition: Region.h:91
bool isProperAncestor(Region *other)
Return true if this region is a proper ancestor of the other region.
Definition: Region.cpp:50
Block & back()
Definition: Region.h:64
unsigned getNumArguments()
Definition: Region.h:123
iterator begin()
Definition: Region.h:55
Region()=default
BlockListType & getBlocks()
Definition: Region.h:45
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:124
void cloneInto(Region *dest, BlockAndValueMapping &mapper)
Clone the internal blocks from this region into dest.
Definition: Region.cpp:70
MutableArrayRef< BlockArgument > BlockArgListType
Definition: Region.h:80
MLIRContext * getContext()
Return the context this region is inserted in.
Definition: Region.cpp:24
reverse_args_iterator args_rbegin()
Definition: Region.h:92
OpIterator op_end()
Definition: Region.h:171
void viewGraph()
Block & front()
Definition: Region.h:65
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:242
reverse_iterator rbegin()
Definition: Region.h:57
ParentT getParentOfType()
Find the first parent operation of the given type, or nullptr if there is no ancestor operation.
Definition: Region.h:205
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:95
BlockArgListType::reverse_iterator reverse_args_iterator
Definition: Region.h:89
Block & emplaceBlock()
Definition: Region.h:46
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Region.h:98
bool hasOneBlock()
Return true if this region has exactly one block.
Definition: Region.h:68
std::enable_if_t< std::is_same< RetT, void >::value, RetT > walk(FnT &&callback)
Walk the operations in this region.
Definition: Region.h:278
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
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:131
static WalkResult advance()
Definition: Visitors.h:51
static WalkResult interrupt()
Definition: Visitors.h:50
A utility iterator that filters out operations that are not 'OpT'.
Definition: BlockSupport.h:142
This class provides iteration over the held operations of a block for a specific operation type.
Definition: BlockSupport.h:159
decltype(walk(nullptr, std::declval< FnT >())) walkResultType
Utility to provide the return type of a templated walk method.
Definition: Visitors.h:319
Include the generated interface declarations.
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition: Visitors.h:62