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