xref: /llvm-project/mlir/include/mlir/IR/Block.h (revision 804d3c4ce192391ef7ba8724c6b9eff456b5c4b2)
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.
40     dropAllReferences();
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.
56   Operation *getParentOp();
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.
85   using BlockArgListType = MutableArrayRef<BlockArgument>;
86 
87   BlockArgListType getArguments() { return arguments; }
88 
89   /// Return a range containing the types of the arguments for this block.
90   ValueTypeRange<BlockArgListType> getArgumentTypes();
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(); }
96   reverse_args_iterator args_rbegin() { return getArguments().rbegin(); }
97   reverse_args_iterator args_rend() { return getArguments().rend(); }
98 
99   bool args_empty() { return arguments.empty(); }
100 
101   /// Add one value to the argument list.
102   BlockArgument addArgument(Type type, Location loc);
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.
107   BlockArgument insertArgument(args_iterator it, Type type, Location loc);
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`.
111   iterator_range<args_iterator> addArguments(TypeRange 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.
160   Operation *findAncestorOpInBlock(Operation &op);
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.
169   void dropAllDefinedValueUses();
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>
188   using op_iterator = detail::op_iterator<OpT, iterator>;
189 
190   /// Return an iterator range over the operations within this block that are of
191   /// 'OpT'.
192   template <typename OpT>
193   iterator_range<op_iterator<OpT>> getOps() {
194     auto endIt = end();
195     return {detail::op_filter_iterator<OpT, iterator>(begin(), endIt),
196             detail::op_filter_iterator<OpT, iterator>(endIt, endIt)};
197   }
198   template <typename OpT>
199   op_iterator<OpT> op_begin() {
200     return detail::op_filter_iterator<OpT, iterator>(begin(), end());
201   }
202   template <typename OpT>
203   op_iterator<OpT> op_end() {
204     return detail::op_filter_iterator<OpT, iterator>(end(), end());
205   }
206 
207   /// Return an iterator range over the operation within this block excluding
208   /// the terminator operation at the end.
209   iterator_range<iterator> without_terminator() {
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.
222   Operation *getTerminator();
223 
224   /// Check whether this block might have a terminator.
225   bool mightHaveTerminator();
226 
227   //===--------------------------------------------------------------------===//
228   // Predecessors and successors.
229   //===--------------------------------------------------------------------===//
230 
231   // Predecessor iteration.
232   using pred_iterator = PredecessorIterator;
233   pred_iterator pred_begin() {
234     return pred_iterator((BlockOperand *)getFirstUse());
235   }
236   pred_iterator pred_end() { return pred_iterator(nullptr); }
237   iterator_range<pred_iterator> getPredecessors() {
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.
253   Block *getSinglePredecessor();
254 
255   /// If this block has a unique predecessor, i.e., all incoming edges originate
256   /// from one block, return it. Otherwise, return null.
257   Block *getUniquePredecessor();
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(); }
267   SuccessorRange getSuccessors() { return SuccessorRange(this); }
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.
390   static OpListType Block::*getSublistAccess(Operation *) {
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> {
427   static mlir::Block::iterator getEmptyKey() {
428     void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
429     return mlir::Block::iterator((mlir::Operation *)pointer);
430   }
431   static mlir::Block::iterator getTombstoneKey() {
432     void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
433     return mlir::Block::iterator((mlir::Operation *)pointer);
434   }
435   static unsigned getHashValue(mlir::Block::iterator iter) {
436     return hash_value(iter.getNodePtr());
437   }
438   static bool isEqual(mlir::Block::iterator lhs, mlir::Block::iterator rhs) {
439     return lhs == rhs;
440   }
441 };
442 
443 } // end namespace llvm
444 
445 #endif // MLIR_IR_BLOCK_H
446