Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/Region.h
Line
Count
Source (jump to first uncovered line)
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 BlockAndValueMapping;
20
21
/// This class contains a list of basic blocks and a link to the parent
22
/// operation it is attached to.
23
class Region {
24
public:
25
0
  Region() = default;
26
  explicit Region(Operation *container);
27
  ~Region();
28
29
  /// Return the context this region is inserted in.  The region must have a
30
  /// valid parent container.
31
  MLIRContext *getContext();
32
33
  /// Return a location for this region. This is the location attached to the
34
  /// parent container. The region must have a valid parent container.
35
  Location getLoc();
36
37
  //===--------------------------------------------------------------------===//
38
  // Block list management
39
  //===--------------------------------------------------------------------===//
40
41
  using BlockListType = llvm::iplist<Block>;
42
0
  BlockListType &getBlocks() { return blocks; }
43
44
  // Iteration over the blocks in the region.
45
  using iterator = BlockListType::iterator;
46
  using reverse_iterator = BlockListType::reverse_iterator;
47
48
0
  iterator begin() { return blocks.begin(); }
49
0
  iterator end() { return blocks.end(); }
50
0
  reverse_iterator rbegin() { return blocks.rbegin(); }
51
0
  reverse_iterator rend() { return blocks.rend(); }
52
53
0
  bool empty() { return blocks.empty(); }
54
0
  void push_back(Block *block) { blocks.push_back(block); }
55
0
  void push_front(Block *block) { blocks.push_front(block); }
56
57
0
  Block &back() { return blocks.back(); }
58
0
  Block &front() { return blocks.front(); }
59
60
  /// getSublistAccess() - Returns pointer to member of region.
61
0
  static BlockListType Region::*getSublistAccess(Block *) {
62
0
    return &Region::blocks;
63
0
  }
64
65
  //===--------------------------------------------------------------------===//
66
  // Operation list utilities
67
  //===--------------------------------------------------------------------===//
68
69
  /// This class provides iteration over the held operations of blocks directly
70
  /// within a region.
71
  class OpIterator final
72
      : public llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
73
                                          Operation> {
74
  public:
75
    /// Initialize OpIterator for a region, specify `end` to return the iterator
76
    /// to last operation.
77
    explicit OpIterator(Region *region, bool end = false);
78
79
    using llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
80
                                     Operation>::operator++;
81
    OpIterator &operator++();
82
0
    Operation *operator->() const { return &*operation; }
83
0
    Operation &operator*() const { return *operation; }
84
85
    /// Compare this iterator with another.
86
0
    bool operator==(const OpIterator &rhs) const {
87
0
      return operation == rhs.operation;
88
0
    }
89
0
    bool operator!=(const OpIterator &rhs) const { return !(*this == rhs); }
90
91
  private:
92
    void skipOverBlocksWithNoOps();
93
94
    /// The region whose operations are being iterated over.
95
    Region *region;
96
    /// The block of 'region' whose operations are being iterated over.
97
    Region::iterator block;
98
    /// The current operation within 'block'.
99
    Block::iterator operation;
100
  };
101
102
  /// This class provides iteration over the held operations of a region for a
103
  /// specific operation type.
104
  template <typename OpT>
105
  using op_iterator = detail::op_iterator<OpT, OpIterator>;
106
107
  /// Return iterators that walk the operations nested directly within this
108
  /// region.
109
0
  OpIterator op_begin() { return OpIterator(this); }
110
0
  OpIterator op_end() { return OpIterator(this, /*end=*/true); }
111
0
  iterator_range<OpIterator> getOps() { return {op_begin(), op_end()}; }
112
113
  /// Return iterators that walk operations of type 'T' nested directly within
114
  /// this region.
115
  template <typename OpT> op_iterator<OpT> op_begin() {
116
    return detail::op_filter_iterator<OpT, OpIterator>(op_begin(), op_end());
117
  }
118
  template <typename OpT> op_iterator<OpT> op_end() {
119
    return detail::op_filter_iterator<OpT, OpIterator>(op_end(), op_end());
120
  }
121
  template <typename OpT> iterator_range<op_iterator<OpT>> getOps() {
122
    auto endIt = op_end();
123
    return {detail::op_filter_iterator<OpT, OpIterator>(op_begin(), endIt),
124
            detail::op_filter_iterator<OpT, OpIterator>(endIt, endIt)};
125
  }
126
127
  //===--------------------------------------------------------------------===//
128
  // Misc. utilities
129
  //===--------------------------------------------------------------------===//
130
131
  /// Return the region containing this region or nullptr if the region is
132
  /// attached to a top-level operation.
133
  Region *getParentRegion();
134
135
  /// Return the parent operation this region is attached to.
136
  Operation *getParentOp();
137
138
  /// Find the first parent operation of the given type, or nullptr if there is
139
  /// no ancestor operation.
140
  template <typename ParentT> ParentT getParentOfType() {
141
    auto *region = this;
142
    do {
143
      if (auto parent = dyn_cast_or_null<ParentT>(region->container))
144
        return parent;
145
    } while ((region = region->getParentRegion()));
146
    return ParentT();
147
  }
148
149
  /// Return the number of this region in the parent operation.
150
  unsigned getRegionNumber();
151
152
  /// Return true if this region is a proper ancestor of the `other` region.
153
  bool isProperAncestor(Region *other);
154
155
  /// Return true if this region is ancestor of the `other` region.  A region
156
  /// is considered as its own ancestor, use `isProperAncestor` to avoid this.
157
0
  bool isAncestor(Region *other) {
158
0
    return this == other || isProperAncestor(other);
159
0
  }
160
161
  /// Clone the internal blocks from this region into dest. Any
162
  /// cloned blocks are appended to the back of dest. If the mapper
163
  /// contains entries for block arguments, these arguments are not included
164
  /// in the respective cloned block.
165
  void cloneInto(Region *dest, BlockAndValueMapping &mapper);
166
  /// Clone this region into 'dest' before the given position in 'dest'.
167
  void cloneInto(Region *dest, Region::iterator destPos,
168
                 BlockAndValueMapping &mapper);
169
170
  /// Takes body of another region (that region will have no body after this
171
  /// operation completes).  The current body of this region is cleared.
172
0
  void takeBody(Region &other) {
173
0
    blocks.clear();
174
0
    blocks.splice(blocks.end(), other.getBlocks());
175
0
  }
176
177
  /// Check that this does not use any value defined outside it.
178
  /// Emit errors if `noteLoc` is provided; this location is used to point
179
  /// to the operation containing the region, the actual error is reported at
180
  /// the operation with an offending use.
181
  bool isIsolatedFromAbove(Optional<Location> noteLoc = llvm::None);
182
183
  /// Returns 'block' if 'block' lies in this region, or otherwise finds the
184
  /// ancestor of 'block' that lies in this region. Returns nullptr if the
185
  /// latter fails.
186
  Block *findAncestorBlockInRegion(Block &block);
187
188
  /// Drop all operand uses from operations within this region, which is
189
  /// an essential step in breaking cyclic dependences between references when
190
  /// they are to be deleted.
191
  void dropAllReferences();
192
193
  //===--------------------------------------------------------------------===//
194
  // Operation Walkers
195
  //===--------------------------------------------------------------------===//
196
197
  /// Walk the operations in this region in postorder, calling the callback for
198
  /// each operation. This method is invoked for void-returning callbacks.
199
  /// See Operation::walk for more details.
200
  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
201
  typename std::enable_if<std::is_same<RetT, void>::value, RetT>::type
202
  walk(FnT &&callback) {
203
    for (auto &block : *this)
204
      block.walk(callback);
205
  }
206
207
  /// Walk the operations in this region in postorder, calling the callback for
208
  /// each operation. This method is invoked for interruptible callbacks.
209
  /// See Operation::walk for more details.
210
  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
211
  typename std::enable_if<std::is_same<RetT, WalkResult>::value, RetT>::type
212
0
  walk(FnT &&callback) {
213
0
    for (auto &block : *this)
214
0
      if (block.walk(callback).wasInterrupted())
215
0
        return WalkResult::interrupt();
216
0
    return WalkResult::advance();
217
0
  }
218
219
  //===--------------------------------------------------------------------===//
220
  // CFG view utilities
221
  //===--------------------------------------------------------------------===//
222
223
  /// Displays the CFG in a window. This is for use from the debugger and
224
  /// depends on Graphviz to generate the graph.
225
  /// This function is defined in ViewRegionGraph and only works with that
226
  /// target linked.
227
  void viewGraph(const Twine &regionName);
228
  void viewGraph();
229
230
private:
231
  BlockListType blocks;
232
233
  /// This is the object we are part of.
234
  Operation *container = nullptr;
235
};
236
237
/// This class provides an abstraction over the different types of ranges over
238
/// Regions. In many cases, this prevents the need to explicitly materialize a
239
/// SmallVector/std::vector. This class should be used in places that are not
240
/// suitable for a more derived type (e.g. ArrayRef) or a template range
241
/// parameter.
242
class RegionRange
243
    : public llvm::detail::indexed_accessor_range_base<
244
          RegionRange, PointerUnion<Region *, const std::unique_ptr<Region> *>,
245
          Region *, Region *, Region *> {
246
  /// The type representing the owner of this range. This is either a list of
247
  /// values, operands, or results.
248
  using OwnerT = PointerUnion<Region *, const std::unique_ptr<Region> *>;
249
250
public:
251
  using RangeBaseT::RangeBaseT;
252
253
  RegionRange(MutableArrayRef<Region> regions = llvm::None);
254
255
  template <typename Arg,
256
            typename = typename std::enable_if_t<std::is_constructible<
257
                ArrayRef<std::unique_ptr<Region>>, Arg>::value>>
258
  RegionRange(Arg &&arg)
259
0
      : RegionRange(ArrayRef<std::unique_ptr<Region>>(std::forward<Arg>(arg))) {
260
0
  }
261
  RegionRange(ArrayRef<std::unique_ptr<Region>> regions);
262
263
private:
264
  /// See `llvm::detail::indexed_accessor_range_base` for details.
265
  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
266
  /// See `llvm::detail::indexed_accessor_range_base` for details.
267
  static Region *dereference_iterator(const OwnerT &owner, ptrdiff_t index);
268
269
  /// Allow access to `offset_base` and `dereference_iterator`.
270
  friend RangeBaseT;
271
};
272
273
} // end namespace mlir
274
275
#endif // MLIR_IR_REGION_H