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