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