Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/Block.h
Line
Count
Source (jump to first uncovered line)
1
//===- Block.h - MLIR Block 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 Block class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef MLIR_IR_BLOCK_H
14
#define MLIR_IR_BLOCK_H
15
16
#include "mlir/IR/BlockSupport.h"
17
#include "mlir/IR/Visitors.h"
18
19
namespace mlir {
20
class TypeRange;
21
template <typename ValueRangeT> class ValueTypeRange;
22
23
/// `Block` represents an ordered list of `Operation`s.
24
class Block : public IRObjectWithUseList<BlockOperand>,
25
              public llvm::ilist_node_with_parent<Block, Region> {
26
public:
27
0
  explicit Block() {}
28
  ~Block();
29
30
0
  void clear() {
31
0
    // Drop all references from within this block.
32
0
    dropAllReferences();
33
0
34
0
    // Clear operations in the reverse order so that uses are destroyed
35
0
    // before their defs.
36
0
    while (!empty())
37
0
      operations.pop_back();
38
0
  }
39
40
  /// Provide a 'getParent' method for ilist_node_with_parent methods.
41
  /// We mark it as a const function because ilist_node_with_parent specifically
42
  /// requires a 'getParent() const' method. Once ilist_node removes this
43
  /// constraint, we should drop the const to fit the rest of the MLIR const
44
  /// model.
45
  Region *getParent() const;
46
47
  /// Returns the closest surrounding operation that contains this block.
48
  Operation *getParentOp();
49
50
  /// Return if this block is the entry block in the parent region.
51
  bool isEntryBlock();
52
53
  /// Insert this block (which must not already be in a region) right before
54
  /// the specified block.
55
  void insertBefore(Block *block);
56
57
  /// Unlink this block from its current region and insert it right before the
58
  /// specific block.
59
  void moveBefore(Block *block);
60
61
  /// Unlink this Block from its parent region and delete it.
62
  void erase();
63
64
  //===--------------------------------------------------------------------===//
65
  // Block argument management
66
  //===--------------------------------------------------------------------===//
67
68
  // This is the list of arguments to the block.
69
  using BlockArgListType = MutableArrayRef<BlockArgument>;
70
71
0
  BlockArgListType getArguments() { return arguments; }
72
73
  /// Return a range containing the types of the arguments for this block.
74
  ValueTypeRange<BlockArgListType> getArgumentTypes();
75
76
  using args_iterator = BlockArgListType::iterator;
77
  using reverse_args_iterator = BlockArgListType::reverse_iterator;
78
0
  args_iterator args_begin() { return getArguments().begin(); }
79
0
  args_iterator args_end() { return getArguments().end(); }
80
0
  reverse_args_iterator args_rbegin() { return getArguments().rbegin(); }
81
0
  reverse_args_iterator args_rend() { return getArguments().rend(); }
82
83
0
  bool args_empty() { return arguments.empty(); }
84
85
  /// Add one value to the argument list.
86
  BlockArgument addArgument(Type type);
87
88
  /// Insert one value to the position in the argument list indicated by the
89
  /// given iterator. The existing arguments are shifted. The block is expected
90
  /// not to have predecessors.
91
  BlockArgument insertArgument(args_iterator it, Type type);
92
93
  /// Add one argument to the argument list for each type specified in the list.
94
  iterator_range<args_iterator> addArguments(TypeRange types);
95
96
  /// Add one value to the argument list at the specified position.
97
  BlockArgument insertArgument(unsigned index, Type type);
98
99
  /// Erase the argument at 'index' and remove it from the argument list.
100
  void eraseArgument(unsigned index);
101
102
0
  unsigned getNumArguments() { return arguments.size(); }
103
0
  BlockArgument getArgument(unsigned i) { return arguments[i]; }
104
105
  //===--------------------------------------------------------------------===//
106
  // Operation list management
107
  //===--------------------------------------------------------------------===//
108
109
  /// This is the list of operations in the block.
110
  using OpListType = llvm::iplist<Operation>;
111
0
  OpListType &getOperations() { return operations; }
112
113
  // Iteration over the operations in the block.
114
  using iterator = OpListType::iterator;
115
  using reverse_iterator = OpListType::reverse_iterator;
116
117
0
  iterator begin() { return operations.begin(); }
118
0
  iterator end() { return operations.end(); }
119
0
  reverse_iterator rbegin() { return operations.rbegin(); }
120
0
  reverse_iterator rend() { return operations.rend(); }
121
122
0
  bool empty() { return operations.empty(); }
123
0
  void push_back(Operation *op) { operations.push_back(op); }
124
0
  void push_front(Operation *op) { operations.push_front(op); }
125
126
0
  Operation &back() { return operations.back(); }
127
0
  Operation &front() { return operations.front(); }
128
129
  /// Returns 'op' if 'op' lies in this block, or otherwise finds the
130
  /// ancestor operation of 'op' that lies in this block. Returns nullptr if
131
  /// the latter fails.
132
  /// TODO: This is very specific functionality that should live somewhere else,
133
  /// probably in Dominance.cpp.
134
  Operation *findAncestorOpInBlock(Operation &op);
135
136
  /// This drops all operand uses from operations within this block, which is
137
  /// an essential step in breaking cyclic dependences between references when
138
  /// they are to be deleted.
139
  void dropAllReferences();
140
141
  /// This drops all uses of values defined in this block or in the blocks of
142
  /// nested regions wherever the uses are located.
143
  void dropAllDefinedValueUses();
144
145
  /// Returns true if the ordering of the child operations is valid, false
146
  /// otherwise.
147
  bool isOpOrderValid();
148
149
  /// Invalidates the current ordering of operations.
150
  void invalidateOpOrder();
151
152
  /// Verifies the current ordering of child operations matches the
153
  /// validOpOrder flag. Returns false if the order is valid, true otherwise.
154
  bool verifyOpOrder();
155
156
  /// Recomputes the ordering of child operations within the block.
157
  void recomputeOpOrder();
158
159
  /// This class provides iteration over the held operations of a block for a
160
  /// specific operation type.
161
  template <typename OpT>
162
  using op_iterator = detail::op_iterator<OpT, iterator>;
163
164
  /// Return an iterator range over the operations within this block that are of
165
  /// 'OpT'.
166
  template <typename OpT> iterator_range<op_iterator<OpT>> getOps() {
167
    auto endIt = end();
168
    return {detail::op_filter_iterator<OpT, iterator>(begin(), endIt),
169
            detail::op_filter_iterator<OpT, iterator>(endIt, endIt)};
170
  }
171
  template <typename OpT> op_iterator<OpT> op_begin() {
172
    return detail::op_filter_iterator<OpT, iterator>(begin(), end());
173
  }
174
  template <typename OpT> op_iterator<OpT> op_end() {
175
    return detail::op_filter_iterator<OpT, iterator>(end(), end());
176
  }
177
178
  /// Return an iterator range over the operation within this block excluding
179
  /// the terminator operation at the end.
180
0
  iterator_range<iterator> without_terminator() {
181
0
    if (begin() == end())
182
0
      return {begin(), end()};
183
0
    auto endIt = --end();
184
0
    return {begin(), endIt};
185
0
  }
186
187
  //===--------------------------------------------------------------------===//
188
  // Terminator management
189
  //===--------------------------------------------------------------------===//
190
191
  /// Get the terminator operation of this block. This function asserts that
192
  /// the block has a valid terminator operation.
193
  Operation *getTerminator();
194
195
  //===--------------------------------------------------------------------===//
196
  // Predecessors and successors.
197
  //===--------------------------------------------------------------------===//
198
199
  // Predecessor iteration.
200
  using pred_iterator = PredecessorIterator;
201
0
  pred_iterator pred_begin() {
202
0
    return pred_iterator((BlockOperand *)getFirstUse());
203
0
  }
204
0
  pred_iterator pred_end() { return pred_iterator(nullptr); }
205
0
  iterator_range<pred_iterator> getPredecessors() {
206
0
    return {pred_begin(), pred_end()};
207
0
  }
208
209
  /// Return true if this block has no predecessors.
210
  bool hasNoPredecessors();
211
212
  /// If this block has exactly one predecessor, return it.  Otherwise, return
213
  /// null.
214
  ///
215
  /// Note that if a block has duplicate predecessors from a single block (e.g.
216
  /// if you have a conditional branch with the same block as the true/false
217
  /// destinations) is not considered to be a single predecessor.
218
  Block *getSinglePredecessor();
219
220
  /// If this block has a unique predecessor, i.e., all incoming edges originate
221
  /// from one block, return it. Otherwise, return null.
222
  Block *getUniquePredecessor();
223
224
  // Indexed successor access.
225
  unsigned getNumSuccessors();
226
  Block *getSuccessor(unsigned i);
227
228
  // Successor iteration.
229
  using succ_iterator = SuccessorRange::iterator;
230
0
  succ_iterator succ_begin() { return getSuccessors().begin(); }
231
0
  succ_iterator succ_end() { return getSuccessors().end(); }
232
0
  SuccessorRange getSuccessors() { return SuccessorRange(this); }
233
234
  //===--------------------------------------------------------------------===//
235
  // Operation Walkers
236
  //===--------------------------------------------------------------------===//
237
238
  /// Walk the operations in this block in postorder, calling the callback for
239
  /// each operation.
240
  /// See Operation::walk for more details.
241
  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
242
0
  RetT walk(FnT &&callback) {
243
0
    return walk(begin(), end(), std::forward<FnT>(callback));
244
0
  }
Unexecuted instantiation: Ops.cpp:_ZN4mlir5Block4walkIRZL6verifyNS_18GenericAtomicRMWOpEE4$_24NS_10WalkResultEEET0_OT_
Unexecuted instantiation: Region.cpp:_ZN4mlir5Block4walkIRZNS_6Region9cloneIntoEPS2_N4llvm14ilist_iteratorINS4_12ilist_detail12node_optionsIS0_Lb1ELb0EvEELb0ELb0EEERNS_20BlockAndValueMappingEE3$_0vEET0_OT_
245
246
  /// Walk the operations in the specified [begin, end) range of this block in
247
  /// postorder, calling the callback for each operation. This method is invoked
248
  /// for void return callbacks.
249
  /// See Operation::walk for more details.
250
  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
251
  typename std::enable_if<std::is_same<RetT, void>::value, RetT>::type
252
0
  walk(Block::iterator begin, Block::iterator end, FnT &&callback) {
253
0
    for (auto &op : llvm::make_early_inc_range(llvm::make_range(begin, end)))
254
0
      detail::walkOperations(&op, callback);
255
0
  }
256
257
  /// Walk the operations in the specified [begin, end) range of this block in
258
  /// postorder, calling the callback for each operation. This method is invoked
259
  /// for interruptible callbacks.
260
  /// See Operation::walk for more details.
261
  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
262
  typename std::enable_if<std::is_same<RetT, WalkResult>::value, RetT>::type
263
0
  walk(Block::iterator begin, Block::iterator end, FnT &&callback) {
264
0
    for (auto &op : llvm::make_early_inc_range(llvm::make_range(begin, end)))
265
0
      if (detail::walkOperations(&op, callback).wasInterrupted())
266
0
        return WalkResult::interrupt();
267
0
    return WalkResult::advance();
268
0
  }
269
270
  //===--------------------------------------------------------------------===//
271
  // Other
272
  //===--------------------------------------------------------------------===//
273
274
  /// Split the block into two blocks before the specified operation or
275
  /// iterator.
276
  ///
277
  /// Note that all operations BEFORE the specified iterator stay as part of
278
  /// the original basic block, and the rest of the operations in the original
279
  /// block are moved to the new block, including the old terminator.  The
280
  /// original block is left without a terminator.
281
  ///
282
  /// The newly formed Block is returned, and the specified iterator is
283
  /// invalidated.
284
  Block *splitBlock(iterator splitBefore);
285
0
  Block *splitBlock(Operation *splitBeforeOp) {
286
0
    return splitBlock(iterator(splitBeforeOp));
287
0
  }
288
289
  /// Returns pointer to member of operation list.
290
0
  static OpListType Block::*getSublistAccess(Operation *) {
291
0
    return &Block::operations;
292
0
  }
293
294
  void print(raw_ostream &os);
295
  void print(raw_ostream &os, AsmState &state);
296
  void dump();
297
298
  /// Print out the name of the block without printing its body.
299
  /// NOTE: The printType argument is ignored.  We keep it for compatibility
300
  /// with LLVM dominator machinery that expects it to exist.
301
  void printAsOperand(raw_ostream &os, bool printType = true);
302
  void printAsOperand(raw_ostream &os, AsmState &state);
303
304
private:
305
  /// Pair of the parent object that owns this block and a bit that signifies if
306
  /// the operations within this block have a valid ordering.
307
  llvm::PointerIntPair<Region *, /*IntBits=*/1, bool> parentValidOpOrderPair;
308
309
  /// This is the list of operations in the block.
310
  OpListType operations;
311
312
  /// This is the list of arguments to the block.
313
  std::vector<BlockArgument> arguments;
314
315
  Block(Block &) = delete;
316
  void operator=(Block &) = delete;
317
318
  friend struct llvm::ilist_traits<Block>;
319
};
320
} // end namespace mlir
321
322
#endif // MLIR_IR_BLOCK_H