MLIR  20.0.0git
Block.h
Go to the documentation of this file.
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 #include "llvm/ADT/SmallPtrSet.h"
20 
21 namespace llvm {
22 class BitVector;
23 class raw_ostream;
24 } // namespace llvm
25 
26 namespace mlir {
27 class TypeRange;
28 template <typename ValueRangeT>
29 class ValueTypeRange;
30 
31 /// `Block` represents an ordered list of `Operation`s.
32 class alignas(8) Block : public IRObjectWithUseList<BlockOperand>,
33  public llvm::ilist_node_with_parent<Block, Region> {
34 public:
35  explicit Block() = default;
36  ~Block();
37 
38  void clear() {
39  // Drop all references from within this block.
41 
42  // Clear operations in the reverse order so that uses are destroyed
43  // before their defs.
44  while (!empty())
45  operations.pop_back();
46  }
47 
48  /// Provide a 'getParent' method for ilist_node_with_parent methods.
49  /// We mark it as a const function because ilist_node_with_parent specifically
50  /// requires a 'getParent() const' method. Once ilist_node removes this
51  /// constraint, we should drop the const to fit the rest of the MLIR const
52  /// model.
53  Region *getParent() const;
54 
55  /// Returns the closest surrounding operation that contains this block.
57 
58  /// Return if this block is the entry block in the parent region.
59  bool isEntryBlock();
60 
61  /// Insert this block (which must not already be in a region) right before
62  /// the specified block.
63  void insertBefore(Block *block);
64 
65  /// Insert this block (which must not already be in a region) right after
66  /// the specified block.
67  void insertAfter(Block *block);
68 
69  /// Unlink this block from its current region and insert it right before the
70  /// specific block.
71  void moveBefore(Block *block);
72 
73  /// Unlink this block from its current region and insert it right before the
74  /// block that the given iterator points to in the region region.
75  void moveBefore(Region *region, llvm::iplist<Block>::iterator iterator);
76 
77  /// Unlink this Block from its parent region and delete it.
78  void erase();
79 
80  //===--------------------------------------------------------------------===//
81  // Block argument management
82  //===--------------------------------------------------------------------===//
83 
84  // This is the list of arguments to the block.
86 
87  BlockArgListType getArguments() { return arguments; }
88 
89  /// Return a range containing the types of the arguments for this block.
91 
92  using args_iterator = BlockArgListType::iterator;
93  using reverse_args_iterator = BlockArgListType::reverse_iterator;
94  args_iterator args_begin() { return getArguments().begin(); }
95  args_iterator args_end() { return getArguments().end(); }
98 
99  bool args_empty() { return arguments.empty(); }
100 
101  /// Add one value to the argument list.
103 
104  /// Insert one value to the position in the argument list indicated by the
105  /// given iterator. The existing arguments are shifted. The block is expected
106  /// not to have predecessors.
108 
109  /// Add one argument to the argument list for each type specified in the list.
110  /// `locs` is required to have the same number of elements as `types`.
112  ArrayRef<Location> locs);
113 
114  /// Add one value to the argument list at the specified position.
115  BlockArgument insertArgument(unsigned index, Type type, Location loc);
116 
117  /// Erase the argument at 'index' and remove it from the argument list.
118  void eraseArgument(unsigned index);
119  /// Erases 'num' arguments from the index 'start'.
120  void eraseArguments(unsigned start, unsigned num);
121  /// Erases the arguments that have their corresponding bit set in
122  /// `eraseIndices` and removes them from the argument list.
123  void eraseArguments(const BitVector &eraseIndices);
124  /// Erases arguments using the given predicate. If the predicate returns true,
125  /// that argument is erased.
126  void eraseArguments(function_ref<bool(BlockArgument)> shouldEraseFn);
127 
128  unsigned getNumArguments() { return arguments.size(); }
129  BlockArgument getArgument(unsigned i) { return arguments[i]; }
130 
131  //===--------------------------------------------------------------------===//
132  // Operation list management
133  //===--------------------------------------------------------------------===//
134 
135  /// This is the list of operations in the block.
136  using OpListType = llvm::iplist<Operation>;
137  OpListType &getOperations() { return operations; }
138 
139  // Iteration over the operations in the block.
140  using iterator = OpListType::iterator;
141  using reverse_iterator = OpListType::reverse_iterator;
142 
143  iterator begin() { return operations.begin(); }
144  iterator end() { return operations.end(); }
145  reverse_iterator rbegin() { return operations.rbegin(); }
146  reverse_iterator rend() { return operations.rend(); }
147 
148  bool empty() { return operations.empty(); }
149  void push_back(Operation *op) { operations.push_back(op); }
150  void push_front(Operation *op) { operations.push_front(op); }
151 
152  Operation &back() { return operations.back(); }
153  Operation &front() { return operations.front(); }
154 
155  /// Returns 'op' if 'op' lies in this block, or otherwise finds the
156  /// ancestor operation of 'op' that lies in this block. Returns nullptr if
157  /// the latter fails.
158  /// TODO: This is very specific functionality that should live somewhere else,
159  /// probably in Dominance.cpp.
161 
162  /// This drops all operand uses from operations within this block, which is
163  /// an essential step in breaking cyclic dependences between references when
164  /// they are to be deleted.
165  void dropAllReferences();
166 
167  /// This drops all uses of values defined in this block or in the blocks of
168  /// nested regions wherever the uses are located.
170 
171  /// Returns true if the ordering of the child operations is valid, false
172  /// otherwise.
173  bool isOpOrderValid();
174 
175  /// Invalidates the current ordering of operations.
176  void invalidateOpOrder();
177 
178  /// Verifies the current ordering of child operations matches the
179  /// validOpOrder flag. Returns false if the order is valid, true otherwise.
180  bool verifyOpOrder();
181 
182  /// Recomputes the ordering of child operations within the block.
183  void recomputeOpOrder();
184 
185  /// This class provides iteration over the held operations of a block for a
186  /// specific operation type.
187  template <typename OpT>
189 
190  /// Return an iterator range over the operations within this block that are of
191  /// 'OpT'.
192  template <typename OpT>
194  auto endIt = end();
197  }
198  template <typename OpT>
201  }
202  template <typename OpT>
205  }
206 
207  /// Return an iterator range over the operation within this block excluding
208  /// the terminator operation at the end.
210  if (begin() == end())
211  return {begin(), end()};
212  auto endIt = --end();
213  return {begin(), endIt};
214  }
215 
216  //===--------------------------------------------------------------------===//
217  // Terminator management
218  //===--------------------------------------------------------------------===//
219 
220  /// Get the terminator operation of this block. This function asserts that
221  /// the block might have a valid terminator operation.
223 
224  /// Check whether this block might have a terminator.
225  bool mightHaveTerminator();
226 
227  //===--------------------------------------------------------------------===//
228  // Predecessors and successors.
229  //===--------------------------------------------------------------------===//
230 
231  // Predecessor iteration.
235  }
236  pred_iterator pred_end() { return pred_iterator(nullptr); }
238  return {pred_begin(), pred_end()};
239  }
240 
241  /// Return true if this block has no predecessors.
242  bool hasNoPredecessors() { return pred_begin() == pred_end(); }
243 
244  /// Returns true if this blocks has no successors.
245  bool hasNoSuccessors() { return succ_begin() == succ_end(); }
246 
247  /// If this block has exactly one predecessor, return it. Otherwise, return
248  /// null.
249  ///
250  /// Note that if a block has duplicate predecessors from a single block (e.g.
251  /// if you have a conditional branch with the same block as the true/false
252  /// destinations) is not considered to be a single predecessor.
254 
255  /// If this block has a unique predecessor, i.e., all incoming edges originate
256  /// from one block, return it. Otherwise, return null.
258 
259  // Indexed successor access.
260  unsigned getNumSuccessors();
261  Block *getSuccessor(unsigned i);
262 
263  // Successor iteration.
264  using succ_iterator = SuccessorRange::iterator;
265  succ_iterator succ_begin() { return getSuccessors().begin(); }
266  succ_iterator succ_end() { return getSuccessors().end(); }
268 
269  /// Return "true" if there is a path from this block to the given block
270  /// (according to the successors relationship). Both blocks must be in the
271  /// same region. Paths that contain a block from `except` do not count.
272  /// This function returns "false" if `other` is in `except`.
273  ///
274  /// Note: This function performs a block graph traversal and its complexity
275  /// linear in the number of blocks in the parent region.
276  ///
277  /// Note: Reachability is a necessary but insufficient condition for
278  /// dominance. Do not use this function in places where you need to check for
279  /// dominance.
280  bool isReachable(Block *other, SmallPtrSet<Block *, 16> &&except = {});
281 
282  //===--------------------------------------------------------------------===//
283  // Walkers
284  //===--------------------------------------------------------------------===//
285 
286  /// Walk all nested operations, blocks (including this block) or regions,
287  /// depending on the type of callback.
288  ///
289  /// The order in which operations, blocks or regions at the same nesting
290  /// level are visited (e.g., lexicographical or reverse lexicographical order)
291  /// is determined by `Iterator`. The walk order for enclosing operations,
292  /// blocks or regions with respect to their nested ones is specified by
293  /// `Order` (post-order by default).
294  ///
295  /// A callback on a operation or block is allowed to erase that operation or
296  /// block if either:
297  /// * the walk is in post-order, or
298  /// * the walk is in pre-order and the walk is skipped after the erasure.
299  ///
300  /// See Operation::walk for more details.
301  template <WalkOrder Order = WalkOrder::PostOrder,
302  typename Iterator = ForwardIterator, typename FnT,
303  typename ArgT = detail::first_argument<FnT>,
304  typename RetT = detail::walkResultType<FnT>>
305  RetT walk(FnT &&callback) {
306  if constexpr (std::is_same<ArgT, Block *>::value &&
307  Order == WalkOrder::PreOrder) {
308  // Pre-order walk on blocks: invoke the callback on this block.
309  if constexpr (std::is_same<RetT, void>::value) {
310  callback(this);
311  } else {
312  RetT result = callback(this);
313  if (result.wasSkipped())
314  return WalkResult::advance();
315  if (result.wasInterrupted())
316  return WalkResult::interrupt();
317  }
318  }
319 
320  // Walk nested operations, blocks or regions.
321  if constexpr (std::is_same<RetT, void>::value) {
322  walk<Order, Iterator>(begin(), end(), std::forward<FnT>(callback));
323  } else {
324  if (walk<Order, Iterator>(begin(), end(), std::forward<FnT>(callback))
325  .wasInterrupted())
326  return WalkResult::interrupt();
327  }
328 
329  if constexpr (std::is_same<ArgT, Block *>::value &&
330  Order == WalkOrder::PostOrder) {
331  // Post-order walk on blocks: invoke the callback on this block.
332  return callback(this);
333  }
334  if constexpr (!std::is_same<RetT, void>::value)
335  return WalkResult::advance();
336  }
337 
338  /// Walk all nested operations, blocks (excluding this block) or regions,
339  /// depending on the type of callback, in the specified [begin, end) range of
340  /// this block.
341  ///
342  /// The order in which operations, blocks or regions at the same nesting
343  /// level are visited (e.g., lexicographical or reverse lexicographical order)
344  /// is determined by `Iterator`. The walk order for enclosing operations,
345  /// blocks or regions with respect to their nested ones is specified by
346  /// `Order` (post-order by default).
347  ///
348  /// A callback on a operation or block is allowed to erase that operation or
349  /// block if either:
350  /// * the walk is in post-order, or
351  /// * the walk is in pre-order and the walk is skipped after the erasure.
352  ///
353  /// See Operation::walk for more details.
354  template <WalkOrder Order = WalkOrder::PostOrder,
355  typename Iterator = ForwardIterator, typename FnT,
356  typename RetT = detail::walkResultType<FnT>>
357  RetT walk(Block::iterator begin, Block::iterator end, FnT &&callback) {
358  for (auto &op : llvm::make_early_inc_range(llvm::make_range(begin, end))) {
359  if constexpr (std::is_same<RetT, WalkResult>::value) {
360  if (detail::walk<Order, Iterator>(&op, callback).wasInterrupted())
361  return WalkResult::interrupt();
362  } else {
363  detail::walk<Order, Iterator>(&op, callback);
364  }
365  }
366  if constexpr (std::is_same<RetT, WalkResult>::value)
367  return WalkResult::advance();
368  }
369 
370  //===--------------------------------------------------------------------===//
371  // Other
372  //===--------------------------------------------------------------------===//
373 
374  /// Split the block into two blocks before the specified operation or
375  /// iterator.
376  ///
377  /// Note that all operations BEFORE the specified iterator stay as part of
378  /// the original basic block, and the rest of the operations in the original
379  /// block are moved to the new block, including the old terminator. The
380  /// original block is left without a terminator.
381  ///
382  /// The newly formed Block is returned, and the specified iterator is
383  /// invalidated.
384  Block *splitBlock(iterator splitBefore);
385  Block *splitBlock(Operation *splitBeforeOp) {
386  return splitBlock(iterator(splitBeforeOp));
387  }
388 
389  /// Returns pointer to member of operation list.
391  return &Block::operations;
392  }
393 
394  void print(raw_ostream &os);
395  void print(raw_ostream &os, AsmState &state);
396  void dump();
397 
398  /// Print out the name of the block without printing its body.
399  /// NOTE: The printType argument is ignored. We keep it for compatibility
400  /// with LLVM dominator machinery that expects it to exist.
401  void printAsOperand(raw_ostream &os, bool printType = true);
402  void printAsOperand(raw_ostream &os, AsmState &state);
403 
404 private:
405  /// Pair of the parent object that owns this block and a bit that signifies if
406  /// the operations within this block have a valid ordering.
407  llvm::PointerIntPair<Region *, /*IntBits=*/1, bool> parentValidOpOrderPair;
408 
409  /// This is the list of operations in the block.
410  OpListType operations;
411 
412  /// This is the list of arguments to the block.
413  std::vector<BlockArgument> arguments;
414 
415  Block(Block &) = delete;
416  void operator=(Block &) = delete;
417 
418  friend struct llvm::ilist_traits<Block>;
419 };
420 
421 raw_ostream &operator<<(raw_ostream &, Block &);
422 } // namespace mlir
423 
424 namespace llvm {
425 template <>
426 struct DenseMapInfo<mlir::Block::iterator> {
428  void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
429  return mlir::Block::iterator((mlir::Operation *)pointer);
430  }
433  return mlir::Block::iterator((mlir::Operation *)pointer);
434  }
435  static unsigned getHashValue(mlir::Block::iterator iter) {
436  return hash_value(iter.getNodePtr());
437  }
439  return lhs == rhs;
440  }
441 };
442 
443 } // end namespace llvm
444 
445 #endif // MLIR_IR_BLOCK_H
This class provides management for the lifetime of the state used when printing the IR.
Definition: AsmState.h:540
This class represents an argument of a Block.
Definition: Value.h:319
A block operand represents an operand that holds a reference to a Block, e.g.
Definition: BlockSupport.h:30
Block represents an ordered list of Operations.
Definition: Block.h:33
void recomputeOpOrder()
Recomputes the ordering of child operations within the block.
Definition: Block.cpp:138
OpListType::iterator iterator
Definition: Block.h:140
Block * splitBlock(Operation *splitBeforeOp)
Definition: Block.h:385
Operation * findAncestorOpInBlock(Operation &op)
Returns 'op' if 'op' lies in this block, or otherwise finds the ancestor operation of 'op' that lies ...
Definition: Block.cpp:76
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
Definition: Block.cpp:151
unsigned getNumSuccessors()
Definition: Block.cpp:257
void push_front(Operation *op)
Definition: Block.h:150
SuccessorRange::iterator succ_iterator
Definition: Block.h:264
bool empty()
Definition: Block.h:148
BlockArgument getArgument(unsigned i)
Definition: Block.h:129
bool hasNoSuccessors()
Returns true if this blocks has no successors.
Definition: Block.h:245
unsigned getNumArguments()
Definition: Block.h:128
Operation & back()
Definition: Block.h:152
void erase()
Unlink this Block from its parent region and delete it.
Definition: Block.cpp:68
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:189
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: Block.cpp:162
Block * splitBlock(iterator splitBefore)
Split the block into two blocks before the specified operation or iterator.
Definition: Block.cpp:310
Block()=default
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition: Block.cpp:29
bool isOpOrderValid()
Returns true if the ordering of the child operations is valid, false otherwise.
Definition: Block.cpp:106
op_iterator< OpT > op_begin()
Definition: Block.h:199
BlockArgListType::reverse_iterator reverse_args_iterator
Definition: Block.h:93
args_iterator args_end()
Definition: Block.h:95
succ_iterator succ_end()
Definition: Block.h:266
pred_iterator pred_begin()
Definition: Block.h:233
void dropAllDefinedValueUses()
This drops all uses of values defined in this block or in the blocks of nested regions wherever the u...
Definition: Block.cpp:96
bool verifyOpOrder()
Verifies the current ordering of child operations matches the validOpOrder flag.
Definition: Block.cpp:117
SuccessorRange getSuccessors()
Definition: Block.h:267
void invalidateOpOrder()
Invalidates the current ordering of operations.
Definition: Block.cpp:109
Block * getSinglePredecessor()
If this block has exactly one predecessor, return it.
Definition: Block.cpp:272
void printAsOperand(raw_ostream &os, bool printType=true)
Print out the name of the block without printing its body.
reverse_args_iterator args_rend()
Definition: Block.h:97
RetT walk(FnT &&callback)
Walk all nested operations, blocks (including this block) or regions, depending on the type of callba...
Definition: Block.h:305
void insertAfter(Block *block)
Insert this block (which must not already be in a region) right after the specified block.
Definition: Block.cpp:48
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:246
succ_iterator succ_begin()
Definition: Block.h:265
iterator_range< pred_iterator > getPredecessors()
Definition: Block.h:237
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:155
RetT walk(Block::iterator begin, Block::iterator end, FnT &&callback)
Walk all nested operations, blocks (excluding this block) or regions, depending on the type of callba...
Definition: Block.h:357
void clear()
Definition: Block.h:38
void eraseArguments(unsigned start, unsigned num)
Erases 'num' arguments from the index 'start'.
Definition: Block.cpp:203
reverse_iterator rend()
Definition: Block.h:146
OpListType & getOperations()
Definition: Block.h:137
void print(raw_ostream &os)
bool args_empty()
Definition: Block.h:99
bool mightHaveTerminator()
Check whether this block might have a terminator.
Definition: Block.cpp:252
BlockArgListType getArguments()
Definition: Block.h:87
PredecessorIterator pred_iterator
Definition: Block.h:232
bool isReachable(Block *other, SmallPtrSet< Block *, 16 > &&except={})
Return "true" if there is a path from this block to the given block (according to the successors rela...
Definition: Block.cpp:355
Operation & front()
Definition: Block.h:153
iterator end()
Definition: Block.h:144
iterator begin()
Definition: Block.h:143
Block * getUniquePredecessor()
If this block has a unique predecessor, i.e., all incoming edges originate from one block,...
Definition: Block.cpp:283
op_iterator< OpT > op_end()
Definition: Block.h:203
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition: Block.cpp:195
iterator_range< op_iterator< OpT > > getOps()
Return an iterator range over the operations within this block that are of 'OpT'.
Definition: Block.h:193
Block * getSuccessor(unsigned i)
Definition: Block.cpp:261
args_iterator args_begin()
Definition: Block.h:94
bool isEntryBlock()
Return if this block is the entry block in the parent region.
Definition: Block.cpp:38
void dropAllReferences()
This drops all operand uses from operations within this block, which is an essential step in breaking...
Definition: Block.cpp:91
void insertBefore(Block *block)
Insert this block (which must not already be in a region) right before the specified block.
Definition: Block.cpp:42
pred_iterator pred_end()
Definition: Block.h:236
void moveBefore(Block *block)
Unlink this block from its current region and insert it right before the specific block.
Definition: Block.cpp:56
void push_back(Operation *op)
Definition: Block.h:149
reverse_args_iterator args_rbegin()
Definition: Block.h:96
bool hasNoPredecessors()
Return true if this block has no predecessors.
Definition: Block.h:242
static OpListType Block::* getSublistAccess(Operation *)
Returns pointer to member of operation list.
Definition: Block.h:390
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
Definition: Block.h:209
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:33
BlockArgListType::iterator args_iterator
Definition: Block.h:92
reverse_iterator rbegin()
Definition: Block.h:145
OpListType::reverse_iterator reverse_iterator
Definition: Block.h:141
llvm::iplist< Operation > OpListType
This is the list of operations in the block.
Definition: Block.h:136
This class represents a single IR object that contains a use list.
Definition: UseDefLists.h:195
BlockOperand * getFirstUse() const
Return the first operand that is using this value, for use by custom use/def iterators.
Definition: UseDefLists.h:281
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Implement a predecessor iterator for blocks.
Definition: BlockSupport.h:51
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
This class implements the successor iterators for Block.
Definition: BlockSupport.h:73
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
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
decltype(walk(nullptr, std::declval< FnT >())) walkResultType
Utility to provide the return type of a templated walk method.
Definition: Visitors.h:465
inline ::llvm::hash_code hash_value(const PolynomialBase< D, T > &arg)
Definition: Polynomial.h:262
Include the generated interface declarations.
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition: Visitors.h:62
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
static mlir::Block::iterator getEmptyKey()
Definition: Block.h:427
static bool isEqual(mlir::Block::iterator lhs, mlir::Block::iterator rhs)
Definition: Block.h:438
static mlir::Block::iterator getTombstoneKey()
Definition: Block.h:431
static unsigned getHashValue(mlir::Block::iterator iter)
Definition: Block.h:435
This iterator enumerates the elements in "forward" order.
Definition: Visitors.h:65