105cf3216SChris Lattner //===- Block.cpp - MLIR Block Class ---------------------------------------===// 2315a466aSChris Lattner // 330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information. 556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6315a466aSChris Lattner // 756222a06SMehdi Amini //===----------------------------------------------------------------------===// 8315a466aSChris Lattner 9315a466aSChris Lattner #include "mlir/IR/Block.h" 10*804d3c4cSMatthias Springer 11315a466aSChris Lattner #include "mlir/IR/Builders.h" 129ffdc930SRiver Riddle #include "mlir/IR/Operation.h" 132e36e0daSmikeurbach #include "llvm/ADT/BitVector.h" 14*804d3c4cSMatthias Springer #include "llvm/ADT/SmallPtrSet.h" 15*804d3c4cSMatthias Springer 16315a466aSChris Lattner using namespace mlir; 17315a466aSChris Lattner 1856b99b40SRiver Riddle //===----------------------------------------------------------------------===// 1956b99b40SRiver Riddle // Block 2056b99b40SRiver Riddle //===----------------------------------------------------------------------===// 2156b99b40SRiver Riddle 22315a466aSChris Lattner Block::~Block() { 23f6188b5bSSean Silva assert(!verifyOpOrder() && "Expected valid operation ordering."); 24315a466aSChris Lattner clear(); 25ab46543cSRiver Riddle for (BlockArgument arg : arguments) 26ab46543cSRiver Riddle arg.destroy(); 27315a466aSChris Lattner } 28315a466aSChris Lattner 29f6188b5bSSean Silva Region *Block::getParent() const { return parentValidOpOrderPair.getPointer(); } 3005cf3216SChris Lattner 31f9d91531SRiver Riddle /// Returns the closest surrounding operation that contains this block or 321e429540SRiver Riddle /// nullptr if this block is unlinked. 331e429540SRiver Riddle Operation *Block::getParentOp() { 341e429540SRiver Riddle return getParent() ? getParent()->getParentOp() : nullptr; 35315a466aSChris Lattner } 36315a466aSChris Lattner 379e3c2650SRiver Riddle /// Return if this block is the entry block in the parent region. 389e3c2650SRiver Riddle bool Block::isEntryBlock() { return this == &getParent()->front(); } 399e3c2650SRiver Riddle 40ce502af9SRiver Riddle /// Insert this block (which must not already be in a region) right before the 41ce502af9SRiver Riddle /// specified block. 42ae618428SChris Lattner void Block::insertBefore(Block *block) { 43ae618428SChris Lattner assert(!getParent() && "already inserted into a block!"); 44ae618428SChris Lattner assert(block->getParent() && "cannot insert before a block without a parent"); 45ab610e8aSRiver Riddle block->getParent()->getBlocks().insert(block->getIterator(), this); 46ab610e8aSRiver Riddle } 47ab610e8aSRiver Riddle 483b45fe2eSMarkus Böck void Block::insertAfter(Block *block) { 493b45fe2eSMarkus Böck assert(!getParent() && "already inserted into a block!"); 503b45fe2eSMarkus Böck assert(block->getParent() && "cannot insert before a block without a parent"); 513b45fe2eSMarkus Böck block->getParent()->getBlocks().insertAfter(block->getIterator(), this); 523b45fe2eSMarkus Böck } 533b45fe2eSMarkus Böck 54ab610e8aSRiver Riddle /// Unlink this block from its current region and insert it right before the 55ab610e8aSRiver Riddle /// specific block. 56ab610e8aSRiver Riddle void Block::moveBefore(Block *block) { 57ab610e8aSRiver Riddle assert(block->getParent() && "cannot insert before a block without a parent"); 58da784a25SMatthias Springer moveBefore(block->getParent(), block->getIterator()); 59da784a25SMatthias Springer } 60da784a25SMatthias Springer 61da784a25SMatthias Springer /// Unlink this block from its current region and insert it right before the 62da784a25SMatthias Springer /// block that the given iterator points to in the region region. 63da784a25SMatthias Springer void Block::moveBefore(Region *region, llvm::iplist<Block>::iterator iterator) { 64da784a25SMatthias Springer region->getBlocks().splice(iterator, getParent()->getBlocks(), getIterator()); 65ae618428SChris Lattner } 66ae618428SChris Lattner 67e7d594bbSRiver Riddle /// Unlink this Block from its parent Region and delete it. 68c2d10581SAlex Zinenko void Block::erase() { 69c2d10581SAlex Zinenko assert(getParent() && "Block has no parent"); 70c2d10581SAlex Zinenko getParent()->getBlocks().erase(this); 71ae618428SChris Lattner } 72ae618428SChris Lattner 73f9d91531SRiver Riddle /// Returns 'op' if 'op' lies in this block, or otherwise finds the 74f9d91531SRiver Riddle /// ancestor operation of 'op' that lies in this block. Returns nullptr if 75315a466aSChris Lattner /// the latter fails. 76f6188b5bSSean Silva Operation *Block::findAncestorOpInBlock(Operation &op) { 77f9d91531SRiver Riddle // Traverse up the operation hierarchy starting from the owner of operand to 78f6188b5bSSean Silva // find the ancestor operation that resides in the block of 'forOp'. 79f6188b5bSSean Silva auto *currOp = &op; 80f6188b5bSSean Silva while (currOp->getBlock() != this) { 81f6188b5bSSean Silva currOp = currOp->getParentOp(); 82f6188b5bSSean Silva if (!currOp) 83315a466aSChris Lattner return nullptr; 84315a466aSChris Lattner } 85f6188b5bSSean Silva return currOp; 86315a466aSChris Lattner } 87315a466aSChris Lattner 88f9d91531SRiver Riddle /// This drops all operand uses from operations within this block, which is 89d6b71b0dSRiver Riddle /// an essential step in breaking cyclic dependences between references when 90d6b71b0dSRiver Riddle /// they are to be deleted. 91d6b71b0dSRiver Riddle void Block::dropAllReferences() { 92f9d91531SRiver Riddle for (Operation &i : *this) 93d6b71b0dSRiver Riddle i.dropAllReferences(); 94d6b71b0dSRiver Riddle } 95d6b71b0dSRiver Riddle 96a7215a90SAlex Zinenko void Block::dropAllDefinedValueUses() { 9735807bc4SRiver Riddle for (auto arg : getArguments()) 982bdf33ccSRiver Riddle arg.dropAllUses(); 99f9d91531SRiver Riddle for (auto &op : *this) 100f9d91531SRiver Riddle op.dropAllDefinedValueUses(); 101a7215a90SAlex Zinenko dropAllUses(); 102a7215a90SAlex Zinenko } 103a7215a90SAlex Zinenko 10405cf3216SChris Lattner /// Returns true if the ordering of the child operations is valid, false 10505cf3216SChris Lattner /// otherwise. 106f6188b5bSSean Silva bool Block::isOpOrderValid() { return parentValidOpOrderPair.getInt(); } 10705cf3216SChris Lattner 10805cf3216SChris Lattner /// Invalidates the current ordering of operations. 109f6188b5bSSean Silva void Block::invalidateOpOrder() { 11005cf3216SChris Lattner // Validate the current ordering. 111f6188b5bSSean Silva assert(!verifyOpOrder()); 112f6188b5bSSean Silva parentValidOpOrderPair.setInt(false); 11305cf3216SChris Lattner } 11405cf3216SChris Lattner 115f9d91531SRiver Riddle /// Verifies the current ordering of child operations. Returns false if the 1164a7dfa78SRiver Riddle /// order is valid, true otherwise. 117f6188b5bSSean Silva bool Block::verifyOpOrder() { 1184a7dfa78SRiver Riddle // The order is already known to be invalid. 119f6188b5bSSean Silva if (!isOpOrderValid()) 1204a7dfa78SRiver Riddle return false; 121f9d91531SRiver Riddle // The order is valid if there are less than 2 operations. 122f9d91531SRiver Riddle if (operations.empty() || std::next(operations.begin()) == operations.end()) 1234a7dfa78SRiver Riddle return false; 1244a7dfa78SRiver Riddle 125f9d91531SRiver Riddle Operation *prev = nullptr; 1264a7dfa78SRiver Riddle for (auto &i : *this) { 127f9d91531SRiver Riddle // The previous operation must have a smaller order index than the next as 1284a7dfa78SRiver Riddle // it appears earlier in the list. 129d9da8b64SRiver Riddle if (prev && prev->orderIndex != Operation::kInvalidOrderIdx && 130d9da8b64SRiver Riddle prev->orderIndex >= i.orderIndex) 1314a7dfa78SRiver Riddle return true; 1324a7dfa78SRiver Riddle prev = &i; 1334a7dfa78SRiver Riddle } 1344a7dfa78SRiver Riddle return false; 1354a7dfa78SRiver Riddle } 1364a7dfa78SRiver Riddle 137f9d91531SRiver Riddle /// Recomputes the ordering of child operations within the block. 138f6188b5bSSean Silva void Block::recomputeOpOrder() { 139f6188b5bSSean Silva parentValidOpOrderPair.setInt(true); 1404a7dfa78SRiver Riddle 1414a7dfa78SRiver Riddle unsigned orderIndex = 0; 142f9d91531SRiver Riddle for (auto &op : *this) 143d9da8b64SRiver Riddle op.orderIndex = (orderIndex += Operation::kOrderStride); 1444a7dfa78SRiver Riddle } 1454a7dfa78SRiver Riddle 146315a466aSChris Lattner //===----------------------------------------------------------------------===// 147315a466aSChris Lattner // Argument list management. 148315a466aSChris Lattner //===----------------------------------------------------------------------===// 149315a466aSChris Lattner 150988249a5SRiver Riddle /// Return a range containing the types of the arguments for this block. 151988249a5SRiver Riddle auto Block::getArgumentTypes() -> ValueTypeRange<BlockArgListType> { 152988249a5SRiver Riddle return ValueTypeRange<BlockArgListType>(getArguments()); 153988249a5SRiver Riddle } 154988249a5SRiver Riddle 155e084679fSRiver Riddle BlockArgument Block::addArgument(Type type, Location loc) { 156e084679fSRiver Riddle BlockArgument arg = BlockArgument::create(type, this, arguments.size(), loc); 157315a466aSChris Lattner arguments.push_back(arg); 158315a466aSChris Lattner return arg; 159315a466aSChris Lattner } 160315a466aSChris Lattner 161315a466aSChris Lattner /// Add one argument to the argument list for each type specified in the list. 16281467f50SChris Lattner auto Block::addArguments(TypeRange types, ArrayRef<Location> locs) 16381467f50SChris Lattner -> iterator_range<args_iterator> { 164e084679fSRiver Riddle assert(types.size() == locs.size() && 16581467f50SChris Lattner "incorrect number of block argument locations"); 166988249a5SRiver Riddle size_t initialSize = arguments.size(); 167988249a5SRiver Riddle arguments.reserve(initialSize + types.size()); 16881467f50SChris Lattner 16981467f50SChris Lattner for (auto typeAndLoc : llvm::zip(types, locs)) 17081467f50SChris Lattner addArgument(std::get<0>(typeAndLoc), std::get<1>(typeAndLoc)); 171315a466aSChris Lattner return {arguments.data() + initialSize, arguments.data() + arguments.size()}; 172315a466aSChris Lattner } 173315a466aSChris Lattner 174e084679fSRiver Riddle BlockArgument Block::insertArgument(unsigned index, Type type, Location loc) { 175e084679fSRiver Riddle assert(index <= arguments.size() && "invalid insertion index"); 17681467f50SChris Lattner 177e084679fSRiver Riddle auto arg = BlockArgument::create(type, this, index, loc); 1788b2eb7c4SChristian Sigg arguments.insert(arguments.begin() + index, arg); 179ee90bb34SMehdi Amini // Update the cached position for all the arguments after the newly inserted 180ee90bb34SMehdi Amini // one. 181ee90bb34SMehdi Amini ++index; 182ee90bb34SMehdi Amini for (BlockArgument arg : llvm::drop_begin(arguments, index)) 183ee90bb34SMehdi Amini arg.setArgNumber(index++); 1848b2eb7c4SChristian Sigg return arg; 1858b2eb7c4SChristian Sigg } 1868b2eb7c4SChristian Sigg 187ee90bb34SMehdi Amini /// Insert one value to the given position of the argument list. The existing 188ee90bb34SMehdi Amini /// arguments are shifted. The block is expected not to have predecessors. 189e084679fSRiver Riddle BlockArgument Block::insertArgument(args_iterator it, Type type, Location loc) { 190f55ed889SKazu Hirata assert(getPredecessors().empty() && 191ee90bb34SMehdi Amini "cannot insert arguments to blocks with predecessors"); 19281467f50SChris Lattner return insertArgument(it->getArgNumber(), type, loc); 193ee90bb34SMehdi Amini } 194ee90bb34SMehdi Amini 195988249a5SRiver Riddle void Block::eraseArgument(unsigned index) { 196315a466aSChris Lattner assert(index < arguments.size()); 197e84aa592SSean Silva arguments[index].destroy(); 198e84aa592SSean Silva arguments.erase(arguments.begin() + index); 199ee90bb34SMehdi Amini for (BlockArgument arg : llvm::drop_begin(arguments, index)) 200ee90bb34SMehdi Amini arg.setArgNumber(index++); 201e84aa592SSean Silva } 202e84aa592SSean Silva 2035b569ed2SJeff Niu void Block::eraseArguments(unsigned start, unsigned num) { 2045b569ed2SJeff Niu assert(start + num <= arguments.size()); 2055b569ed2SJeff Niu for (unsigned i = 0; i < num; ++i) 2065b569ed2SJeff Niu arguments[start + i].destroy(); 2075b569ed2SJeff Niu arguments.erase(arguments.begin() + start, arguments.begin() + start + num); 2085b569ed2SJeff Niu for (BlockArgument arg : llvm::drop_begin(arguments, start)) 2095b569ed2SJeff Niu arg.setArgNumber(start++); 2105b569ed2SJeff Niu } 2115b569ed2SJeff Niu 212d10d49dcSRiver Riddle void Block::eraseArguments(const BitVector &eraseIndices) { 2134e02eb80SRiver Riddle eraseArguments( 2144e02eb80SRiver Riddle [&](BlockArgument arg) { return eraseIndices.test(arg.getArgNumber()); }); 2154e02eb80SRiver Riddle } 2164e02eb80SRiver Riddle 2174e02eb80SRiver Riddle void Block::eraseArguments(function_ref<bool(BlockArgument)> shouldEraseFn) { 2184e02eb80SRiver Riddle auto firstDead = llvm::find_if(arguments, shouldEraseFn); 2194e02eb80SRiver Riddle if (firstDead == arguments.end()) 2204e02eb80SRiver Riddle return; 2214e02eb80SRiver Riddle 2224e02eb80SRiver Riddle // Destroy the first dead argument, this avoids reapplying the predicate to 2234e02eb80SRiver Riddle // it. 2244e02eb80SRiver Riddle unsigned index = firstDead->getArgNumber(); 2254e02eb80SRiver Riddle firstDead->destroy(); 2264e02eb80SRiver Riddle 2274e02eb80SRiver Riddle // Iterate the remaining arguments to remove any that are now dead. 2284e02eb80SRiver Riddle for (auto it = std::next(firstDead), e = arguments.end(); it != e; ++it) { 2294e02eb80SRiver Riddle // Destroy dead arguments, and shift those that are still live. 2304e02eb80SRiver Riddle if (shouldEraseFn(*it)) { 2314e02eb80SRiver Riddle it->destroy(); 2324e02eb80SRiver Riddle } else { 2334e02eb80SRiver Riddle it->setArgNumber(index++); 2344e02eb80SRiver Riddle *firstDead++ = *it; 2352e36e0daSmikeurbach } 236ee90bb34SMehdi Amini } 2374e02eb80SRiver Riddle arguments.erase(firstDead, arguments.end()); 23808778d8cSAlex Zinenko } 23908778d8cSAlex Zinenko 240315a466aSChris Lattner //===----------------------------------------------------------------------===// 241315a466aSChris Lattner // Terminator management 242315a466aSChris Lattner //===----------------------------------------------------------------------===// 243315a466aSChris Lattner 244f9d91531SRiver Riddle /// Get the terminator operation of this block. This function asserts that 24502981c96Svic /// the block might have a valid terminator operation. 246f9d91531SRiver Riddle Operation *Block::getTerminator() { 24702981c96Svic assert(mightHaveTerminator()); 248366ebcf6SRiver Riddle return &back(); 249315a466aSChris Lattner } 250315a466aSChris Lattner 25102981c96Svic /// Check whether this block might have a terminator. 25202981c96Svic bool Block::mightHaveTerminator() { 25387d77d3cSvic return !empty() && back().mightHaveTrait<OpTrait::IsTerminator>(); 25487d77d3cSvic } 25587d77d3cSvic 256315a466aSChris Lattner // Indexed successor access. 2573d6c74ffSChris Lattner unsigned Block::getNumSuccessors() { 258366ebcf6SRiver Riddle return empty() ? 0 : back().getNumSuccessors(); 259315a466aSChris Lattner } 260315a466aSChris Lattner 261315a466aSChris Lattner Block *Block::getSuccessor(unsigned i) { 262366ebcf6SRiver Riddle assert(i < getNumSuccessors()); 263315a466aSChris Lattner return getTerminator()->getSuccessor(i); 264315a466aSChris Lattner } 265315a466aSChris Lattner 266315a466aSChris Lattner /// If this block has exactly one predecessor, return it. Otherwise, return 267315a466aSChris Lattner /// null. 268315a466aSChris Lattner /// 269315a466aSChris Lattner /// Note that multiple edges from a single block (e.g. if you have a cond 270315a466aSChris Lattner /// branch with the same block as the true/false destinations) is not 271315a466aSChris Lattner /// considered to be a single predecessor. 272315a466aSChris Lattner Block *Block::getSinglePredecessor() { 273315a466aSChris Lattner auto it = pred_begin(); 274315a466aSChris Lattner if (it == pred_end()) 275315a466aSChris Lattner return nullptr; 276315a466aSChris Lattner auto *firstPred = *it; 277315a466aSChris Lattner ++it; 278315a466aSChris Lattner return it == pred_end() ? firstPred : nullptr; 279315a466aSChris Lattner } 280315a466aSChris Lattner 281af331bc5SRiver Riddle /// If this block has a unique predecessor, i.e., all incoming edges originate 282af331bc5SRiver Riddle /// from one block, return it. Otherwise, return null. 283af331bc5SRiver Riddle Block *Block::getUniquePredecessor() { 284af331bc5SRiver Riddle auto it = pred_begin(), e = pred_end(); 285af331bc5SRiver Riddle if (it == e) 286af331bc5SRiver Riddle return nullptr; 287af331bc5SRiver Riddle 288af331bc5SRiver Riddle // Check for any conflicting predecessors. 289af331bc5SRiver Riddle auto *firstPred = *it; 290af331bc5SRiver Riddle for (++it; it != e; ++it) 291af331bc5SRiver Riddle if (*it != firstPred) 292af331bc5SRiver Riddle return nullptr; 293af331bc5SRiver Riddle return firstPred; 294af331bc5SRiver Riddle } 295af331bc5SRiver Riddle 296315a466aSChris Lattner //===----------------------------------------------------------------------===// 297315a466aSChris Lattner // Other 298315a466aSChris Lattner //===----------------------------------------------------------------------===// 299315a466aSChris Lattner 300f9d91531SRiver Riddle /// Split the block into two blocks before the specified operation or 301ae618428SChris Lattner /// iterator. 302315a466aSChris Lattner /// 303f9d91531SRiver Riddle /// Note that all operations BEFORE the specified iterator stay as part of 304f9d91531SRiver Riddle /// the original basic block, and the rest of the operations in the original 305ae618428SChris Lattner /// block are moved to the new block, including the old terminator. The 306ae618428SChris Lattner /// original block is left without a terminator. 307315a466aSChris Lattner /// 308ae618428SChris Lattner /// The newly formed Block is returned, and the specified iterator is 309ae618428SChris Lattner /// invalidated. 310315a466aSChris Lattner Block *Block::splitBlock(iterator splitBefore) { 311315a466aSChris Lattner // Start by creating a new basic block, and insert it immediate after this 312ce502af9SRiver Riddle // one in the containing region. 31302b6fb21SMehdi Amini auto *newBB = new Block(); 314c2d10581SAlex Zinenko getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB); 315315a466aSChris Lattner 316ce502af9SRiver Riddle // Move all of the operations from the split point to the end of the region 317315a466aSChris Lattner // into the new block. 318f9d91531SRiver Riddle newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore, 319315a466aSChris Lattner end()); 320315a466aSChris Lattner return newBB; 321315a466aSChris Lattner } 322e4f8f3bcSRiver Riddle 323e4f8f3bcSRiver Riddle //===----------------------------------------------------------------------===// 324e4f8f3bcSRiver Riddle // Predecessors 325e4f8f3bcSRiver Riddle //===----------------------------------------------------------------------===// 326e4f8f3bcSRiver Riddle 327e4f8f3bcSRiver Riddle Block *PredecessorIterator::unwrap(BlockOperand &value) { 328e4f8f3bcSRiver Riddle return value.getOwner()->getBlock(); 329e4f8f3bcSRiver Riddle } 330e4f8f3bcSRiver Riddle 331e4f8f3bcSRiver Riddle /// Get the successor number in the predecessor terminator. 332e4f8f3bcSRiver Riddle unsigned PredecessorIterator::getSuccessorIndex() const { 333e4f8f3bcSRiver Riddle return I->getOperandNumber(); 334e4f8f3bcSRiver Riddle } 3353f9744a6SRiver Riddle 3363f9744a6SRiver Riddle //===----------------------------------------------------------------------===// 337*804d3c4cSMatthias Springer // Successors 3383f9744a6SRiver Riddle //===----------------------------------------------------------------------===// 3393f9744a6SRiver Riddle 340abfd1a8bSRiver Riddle SuccessorRange::SuccessorRange() : SuccessorRange(nullptr, 0) {} 341abfd1a8bSRiver Riddle 342abfd1a8bSRiver Riddle SuccessorRange::SuccessorRange(Block *block) : SuccessorRange() { 343066b3207SMehdi Amini if (block->empty() || llvm::hasSingleElement(*block->getParent())) 344066b3207SMehdi Amini return; 345a6559b42SMehdi Amini Operation *term = &block->back(); 3463f9744a6SRiver Riddle if ((count = term->getNumSuccessors())) 3473f9744a6SRiver Riddle base = term->getBlockOperands().data(); 3483f9744a6SRiver Riddle } 3495d5bd2e1SRiver Riddle 350abfd1a8bSRiver Riddle SuccessorRange::SuccessorRange(Operation *term) : SuccessorRange() { 3515d5bd2e1SRiver Riddle if ((count = term->getNumSuccessors())) 3525d5bd2e1SRiver Riddle base = term->getBlockOperands().data(); 3535d5bd2e1SRiver Riddle } 3548893d081SRahul Joshi 355*804d3c4cSMatthias Springer bool Block::isReachable(Block *other, SmallPtrSet<Block *, 16> &&except) { 356*804d3c4cSMatthias Springer assert(getParent() == other->getParent() && "expected same region"); 357*804d3c4cSMatthias Springer if (except.contains(other)) { 358*804d3c4cSMatthias Springer // Fast path: If `other` is in the `except` set, there can be no path from 359*804d3c4cSMatthias Springer // "this" to `other` (that does not pass through an excluded block). 360*804d3c4cSMatthias Springer return false; 361*804d3c4cSMatthias Springer } 362*804d3c4cSMatthias Springer SmallVector<Block *> worklist(succ_begin(), succ_end()); 363*804d3c4cSMatthias Springer while (!worklist.empty()) { 364*804d3c4cSMatthias Springer Block *next = worklist.pop_back_val(); 365*804d3c4cSMatthias Springer if (next == other) 366*804d3c4cSMatthias Springer return true; 367*804d3c4cSMatthias Springer // Note: `except` keeps track of already visited blocks. 368*804d3c4cSMatthias Springer if (!except.insert(next).second) 369*804d3c4cSMatthias Springer continue; 370*804d3c4cSMatthias Springer worklist.append(next->succ_begin(), next->succ_end()); 371*804d3c4cSMatthias Springer } 372*804d3c4cSMatthias Springer return false; 373*804d3c4cSMatthias Springer } 374*804d3c4cSMatthias Springer 3758893d081SRahul Joshi //===----------------------------------------------------------------------===// 3768893d081SRahul Joshi // BlockRange 3778893d081SRahul Joshi //===----------------------------------------------------------------------===// 3788893d081SRahul Joshi 3798893d081SRahul Joshi BlockRange::BlockRange(ArrayRef<Block *> blocks) : BlockRange(nullptr, 0) { 3808893d081SRahul Joshi if ((count = blocks.size())) 3818893d081SRahul Joshi base = blocks.data(); 3828893d081SRahul Joshi } 3838893d081SRahul Joshi 3848893d081SRahul Joshi BlockRange::BlockRange(SuccessorRange successors) 3858893d081SRahul Joshi : BlockRange(successors.begin().getBase(), successors.size()) {} 3868893d081SRahul Joshi 3878893d081SRahul Joshi /// See `llvm::detail::indexed_accessor_range_base` for details. 3888893d081SRahul Joshi BlockRange::OwnerT BlockRange::offset_base(OwnerT object, ptrdiff_t index) { 38968f58812STres Popp if (auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object)) 3908893d081SRahul Joshi return {operand + index}; 39168f58812STres Popp return {llvm::dyn_cast_if_present<Block *const *>(object) + index}; 3928893d081SRahul Joshi } 3938893d081SRahul Joshi 3948893d081SRahul Joshi /// See `llvm::detail::indexed_accessor_range_base` for details. 3958893d081SRahul Joshi Block *BlockRange::dereference_iterator(OwnerT object, ptrdiff_t index) { 39668f58812STres Popp if (const auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object)) 3978893d081SRahul Joshi return operand[index].get(); 39868f58812STres Popp return llvm::dyn_cast_if_present<Block *const *>(object)[index]; 3998893d081SRahul Joshi } 400