1 //===- Block.cpp - MLIR Block Class ---------------------------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 18 #include "mlir/IR/Block.h" 19 #include "mlir/IR/Builders.h" 20 #include "mlir/IR/Operation.h" 21 using namespace mlir; 22 23 //===----------------------------------------------------------------------===// 24 // BlockArgument 25 //===----------------------------------------------------------------------===// 26 27 /// Returns the number of this argument. 28 unsigned BlockArgument::getArgNumber() { 29 // Arguments are not stored in place, so we have to find it within the list. 30 auto argList = getOwner()->getArguments(); 31 return std::distance(argList.begin(), llvm::find(argList, this)); 32 } 33 34 //===----------------------------------------------------------------------===// 35 // Block 36 //===----------------------------------------------------------------------===// 37 38 Block::~Block() { 39 assert(!verifyOpOrder() && "Expected valid operation ordering."); 40 clear(); 41 llvm::DeleteContainerPointers(arguments); 42 } 43 44 Region *Block::getParent() const { return parentValidOpOrderPair.getPointer(); } 45 46 /// Returns the closest surrounding operation that contains this block or 47 /// nullptr if this block is unlinked. 48 Operation *Block::getParentOp() { 49 return getParent() ? getParent()->getParentOp() : nullptr; 50 } 51 52 /// Return if this block is the entry block in the parent region. 53 bool Block::isEntryBlock() { return this == &getParent()->front(); } 54 55 /// Insert this block (which must not already be in a region) right before the 56 /// specified block. 57 void Block::insertBefore(Block *block) { 58 assert(!getParent() && "already inserted into a block!"); 59 assert(block->getParent() && "cannot insert before a block without a parent"); 60 block->getParent()->getBlocks().insert(block->getIterator(), this); 61 } 62 63 /// Unlink this block from its current region and insert it right before the 64 /// specific block. 65 void Block::moveBefore(Block *block) { 66 assert(block->getParent() && "cannot insert before a block without a parent"); 67 block->getParent()->getBlocks().splice( 68 block->getIterator(), getParent()->getBlocks(), getIterator()); 69 } 70 71 /// Unlink this Block from its parent Region and delete it. 72 void Block::erase() { 73 assert(getParent() && "Block has no parent"); 74 getParent()->getBlocks().erase(this); 75 } 76 77 /// Returns 'op' if 'op' lies in this block, or otherwise finds the 78 /// ancestor operation of 'op' that lies in this block. Returns nullptr if 79 /// the latter fails. 80 Operation *Block::findAncestorOpInBlock(Operation &op) { 81 // Traverse up the operation hierarchy starting from the owner of operand to 82 // find the ancestor operation that resides in the block of 'forOp'. 83 auto *currOp = &op; 84 while (currOp->getBlock() != this) { 85 currOp = currOp->getParentOp(); 86 if (!currOp) 87 return nullptr; 88 } 89 return currOp; 90 } 91 92 /// This drops all operand uses from operations within this block, which is 93 /// an essential step in breaking cyclic dependences between references when 94 /// they are to be deleted. 95 void Block::dropAllReferences() { 96 for (Operation &i : *this) 97 i.dropAllReferences(); 98 } 99 100 void Block::dropAllDefinedValueUses() { 101 for (auto *arg : getArguments()) 102 arg->dropAllUses(); 103 for (auto &op : *this) 104 op.dropAllDefinedValueUses(); 105 dropAllUses(); 106 } 107 108 /// Returns true if the ordering of the child operations is valid, false 109 /// otherwise. 110 bool Block::isOpOrderValid() { return parentValidOpOrderPair.getInt(); } 111 112 /// Invalidates the current ordering of operations. 113 void Block::invalidateOpOrder() { 114 // Validate the current ordering. 115 assert(!verifyOpOrder()); 116 parentValidOpOrderPair.setInt(false); 117 } 118 119 /// Verifies the current ordering of child operations. Returns false if the 120 /// order is valid, true otherwise. 121 bool Block::verifyOpOrder() { 122 // The order is already known to be invalid. 123 if (!isOpOrderValid()) 124 return false; 125 // The order is valid if there are less than 2 operations. 126 if (operations.empty() || std::next(operations.begin()) == operations.end()) 127 return false; 128 129 Operation *prev = nullptr; 130 for (auto &i : *this) { 131 // The previous operation must have a smaller order index than the next as 132 // it appears earlier in the list. 133 if (prev && prev->orderIndex != Operation::kInvalidOrderIdx && 134 prev->orderIndex >= i.orderIndex) 135 return true; 136 prev = &i; 137 } 138 return false; 139 } 140 141 /// Recomputes the ordering of child operations within the block. 142 void Block::recomputeOpOrder() { 143 parentValidOpOrderPair.setInt(true); 144 145 unsigned orderIndex = 0; 146 for (auto &op : *this) 147 op.orderIndex = (orderIndex += Operation::kOrderStride); 148 } 149 150 //===----------------------------------------------------------------------===// 151 // Argument list management. 152 //===----------------------------------------------------------------------===// 153 154 BlockArgument *Block::addArgument(Type type) { 155 auto *arg = new BlockArgument(type, this); 156 arguments.push_back(arg); 157 return arg; 158 } 159 160 /// Add one argument to the argument list for each type specified in the list. 161 auto Block::addArguments(ArrayRef<Type> types) 162 -> llvm::iterator_range<args_iterator> { 163 arguments.reserve(arguments.size() + types.size()); 164 auto initialSize = arguments.size(); 165 for (auto type : types) { 166 addArgument(type); 167 } 168 return {arguments.data() + initialSize, arguments.data() + arguments.size()}; 169 } 170 171 void Block::eraseArgument(unsigned index, bool updatePredTerms) { 172 assert(index < arguments.size()); 173 174 // Delete the argument. 175 delete arguments[index]; 176 arguments.erase(arguments.begin() + index); 177 178 // If we aren't updating predecessors, there is nothing left to do. 179 if (!updatePredTerms) 180 return; 181 182 // Erase this argument from each of the predecessor's terminator. 183 for (auto predIt = pred_begin(), predE = pred_end(); predIt != predE; 184 ++predIt) { 185 auto *predTerminator = (*predIt)->getTerminator(); 186 predTerminator->eraseSuccessorOperand(predIt.getSuccessorIndex(), index); 187 } 188 } 189 190 //===----------------------------------------------------------------------===// 191 // Terminator management 192 //===----------------------------------------------------------------------===// 193 194 /// Get the terminator operation of this block. This function asserts that 195 /// the block has a valid terminator operation. 196 Operation *Block::getTerminator() { 197 assert(!empty() && !back().isKnownNonTerminator()); 198 return &back(); 199 } 200 201 /// Return true if this block has no predecessors. 202 bool Block::hasNoPredecessors() { return pred_begin() == pred_end(); } 203 204 // Indexed successor access. 205 unsigned Block::getNumSuccessors() { 206 return empty() ? 0 : back().getNumSuccessors(); 207 } 208 209 Block *Block::getSuccessor(unsigned i) { 210 assert(i < getNumSuccessors()); 211 return getTerminator()->getSuccessor(i); 212 } 213 214 /// If this block has exactly one predecessor, return it. Otherwise, return 215 /// null. 216 /// 217 /// Note that multiple edges from a single block (e.g. if you have a cond 218 /// branch with the same block as the true/false destinations) is not 219 /// considered to be a single predecessor. 220 Block *Block::getSinglePredecessor() { 221 auto it = pred_begin(); 222 if (it == pred_end()) 223 return nullptr; 224 auto *firstPred = *it; 225 ++it; 226 return it == pred_end() ? firstPred : nullptr; 227 } 228 229 //===----------------------------------------------------------------------===// 230 // Other 231 //===----------------------------------------------------------------------===// 232 233 /// Split the block into two blocks before the specified operation or 234 /// iterator. 235 /// 236 /// Note that all operations BEFORE the specified iterator stay as part of 237 /// the original basic block, and the rest of the operations in the original 238 /// block are moved to the new block, including the old terminator. The 239 /// original block is left without a terminator. 240 /// 241 /// The newly formed Block is returned, and the specified iterator is 242 /// invalidated. 243 Block *Block::splitBlock(iterator splitBefore) { 244 // Start by creating a new basic block, and insert it immediate after this 245 // one in the containing region. 246 auto newBB = new Block(); 247 getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB); 248 249 // Move all of the operations from the split point to the end of the region 250 // into the new block. 251 newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore, 252 end()); 253 return newBB; 254 } 255 256 //===----------------------------------------------------------------------===// 257 // Predecessors 258 //===----------------------------------------------------------------------===// 259 260 Block *PredecessorIterator::unwrap(BlockOperand &value) { 261 return value.getOwner()->getBlock(); 262 } 263 264 /// Get the successor number in the predecessor terminator. 265 unsigned PredecessorIterator::getSuccessorIndex() const { 266 return I->getOperandNumber(); 267 } 268 269 //===----------------------------------------------------------------------===// 270 // Successors 271 //===----------------------------------------------------------------------===// 272 273 SuccessorRange::SuccessorRange(Block *block) : SuccessorRange(nullptr, 0) { 274 if (Operation *term = block->getTerminator()) 275 if ((count = term->getNumSuccessors())) 276 base = term->getBlockOperands().data(); 277 } 278