github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/IR/Block.cpp (about) 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(!verifyInstOrder() && "Expected valid operation ordering."); 40 clear(); 41 42 for (auto *arg : arguments) 43 if (!arg->use_empty()) 44 arg->user_begin()->dump(); 45 46 llvm::DeleteContainerPointers(arguments); 47 } 48 49 Region *Block::getParent() { return parentValidInstOrderPair.getPointer(); } 50 51 /// Returns the closest surrounding operation that contains this block or 52 /// nullptr if this block is unlinked. 53 Operation *Block::getParentOp() { 54 return getParent() ? getParent()->getParentOp() : nullptr; 55 } 56 57 /// Return if this block is the entry block in the parent region. 58 bool Block::isEntryBlock() { return this == &getParent()->front(); } 59 60 /// Insert this block (which must not already be in a region) right before the 61 /// specified block. 62 void Block::insertBefore(Block *block) { 63 assert(!getParent() && "already inserted into a block!"); 64 assert(block->getParent() && "cannot insert before a block without a parent"); 65 block->getParent()->getBlocks().insert(Region::iterator(block), this); 66 } 67 68 /// Unlink this Block from its parent Region and delete it. 69 void Block::erase() { 70 assert(getParent() && "Block has no parent"); 71 getParent()->getBlocks().erase(this); 72 } 73 74 /// Returns 'op' if 'op' lies in this block, or otherwise finds the 75 /// ancestor operation of 'op' that lies in this block. Returns nullptr if 76 /// the latter fails. 77 Operation *Block::findAncestorInstInBlock(Operation &op) { 78 // Traverse up the operation hierarchy starting from the owner of operand to 79 // find the ancestor operation that resides in the block of 'forInst'. 80 auto *currInst = &op; 81 while (currInst->getBlock() != this) { 82 currInst = currInst->getParentOp(); 83 if (!currInst) 84 return nullptr; 85 } 86 return currInst; 87 } 88 89 /// This drops all operand uses from operations within this block, which is 90 /// an essential step in breaking cyclic dependences between references when 91 /// they are to be deleted. 92 void Block::dropAllReferences() { 93 for (Operation &i : *this) 94 i.dropAllReferences(); 95 } 96 97 void Block::dropAllDefinedValueUses() { 98 for (auto *arg : getArguments()) 99 arg->dropAllUses(); 100 for (auto &op : *this) 101 op.dropAllDefinedValueUses(); 102 dropAllUses(); 103 } 104 105 /// Returns true if the ordering of the child operations is valid, false 106 /// otherwise. 107 bool Block::isInstOrderValid() { return parentValidInstOrderPair.getInt(); } 108 109 /// Invalidates the current ordering of operations. 110 void Block::invalidateInstOrder() { 111 // Validate the current ordering. 112 assert(!verifyInstOrder()); 113 parentValidInstOrderPair.setInt(false); 114 } 115 116 /// Verifies the current ordering of child operations. Returns false if the 117 /// order is valid, true otherwise. 118 bool Block::verifyInstOrder() { 119 // The order is already known to be invalid. 120 if (!isInstOrderValid()) 121 return false; 122 // The order is valid if there are less than 2 operations. 123 if (operations.empty() || std::next(operations.begin()) == operations.end()) 124 return false; 125 126 Operation *prev = nullptr; 127 for (auto &i : *this) { 128 // The previous operation must have a smaller order index than the next as 129 // it appears earlier in the list. 130 if (prev && prev->orderIndex >= i.orderIndex) 131 return true; 132 prev = &i; 133 } 134 return false; 135 } 136 137 /// Recomputes the ordering of child operations within the block. 138 void Block::recomputeInstOrder() { 139 parentValidInstOrderPair.setInt(true); 140 141 // TODO(riverriddle) Have non-congruent indices to reduce the number of times 142 // an insert invalidates the list. 143 unsigned orderIndex = 0; 144 for (auto &op : *this) 145 op.orderIndex = orderIndex++; 146 } 147 148 //===----------------------------------------------------------------------===// 149 // Argument list management. 150 //===----------------------------------------------------------------------===// 151 152 BlockArgument *Block::addArgument(Type type) { 153 auto *arg = new BlockArgument(type, this); 154 arguments.push_back(arg); 155 return arg; 156 } 157 158 /// Add one argument to the argument list for each type specified in the list. 159 auto Block::addArguments(ArrayRef<Type> types) 160 -> llvm::iterator_range<args_iterator> { 161 arguments.reserve(arguments.size() + types.size()); 162 auto initialSize = arguments.size(); 163 for (auto type : types) { 164 addArgument(type); 165 } 166 return {arguments.data() + initialSize, arguments.data() + arguments.size()}; 167 } 168 169 void Block::eraseArgument(unsigned index, bool updatePredTerms) { 170 assert(index < arguments.size()); 171 172 // Delete the argument. 173 delete arguments[index]; 174 arguments.erase(arguments.begin() + index); 175 176 // If we aren't updating predecessors, there is nothing left to do. 177 if (!updatePredTerms) 178 return; 179 180 // Erase this argument from each of the predecessor's terminator. 181 for (auto predIt = pred_begin(), predE = pred_end(); predIt != predE; 182 ++predIt) { 183 auto *predTerminator = (*predIt)->getTerminator(); 184 predTerminator->eraseSuccessorOperand(predIt.getSuccessorIndex(), index); 185 } 186 } 187 188 //===----------------------------------------------------------------------===// 189 // Terminator management 190 //===----------------------------------------------------------------------===// 191 192 /// Get the terminator operation of this block. This function asserts that 193 /// the block has a valid terminator operation. 194 Operation *Block::getTerminator() { 195 assert(!empty() && !back().isKnownNonTerminator()); 196 return &back(); 197 } 198 199 /// Return true if this block has no predecessors. 200 bool Block::hasNoPredecessors() { return pred_begin() == pred_end(); } 201 202 // Indexed successor access. 203 unsigned Block::getNumSuccessors() { 204 return empty() ? 0 : back().getNumSuccessors(); 205 } 206 207 Block *Block::getSuccessor(unsigned i) { 208 assert(i < getNumSuccessors()); 209 return getTerminator()->getSuccessor(i); 210 } 211 212 /// If this block has exactly one predecessor, return it. Otherwise, return 213 /// null. 214 /// 215 /// Note that multiple edges from a single block (e.g. if you have a cond 216 /// branch with the same block as the true/false destinations) is not 217 /// considered to be a single predecessor. 218 Block *Block::getSinglePredecessor() { 219 auto it = pred_begin(); 220 if (it == pred_end()) 221 return nullptr; 222 auto *firstPred = *it; 223 ++it; 224 return it == pred_end() ? firstPred : nullptr; 225 } 226 227 //===----------------------------------------------------------------------===// 228 // Other 229 //===----------------------------------------------------------------------===// 230 231 /// Split the block into two blocks before the specified operation or 232 /// iterator. 233 /// 234 /// Note that all operations BEFORE the specified iterator stay as part of 235 /// the original basic block, and the rest of the operations in the original 236 /// block are moved to the new block, including the old terminator. The 237 /// original block is left without a terminator. 238 /// 239 /// The newly formed Block is returned, and the specified iterator is 240 /// invalidated. 241 Block *Block::splitBlock(iterator splitBefore) { 242 // Start by creating a new basic block, and insert it immediate after this 243 // one in the containing region. 244 auto newBB = new Block(); 245 getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB); 246 247 // Move all of the operations from the split point to the end of the region 248 // into the new block. 249 newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore, 250 end()); 251 return newBB; 252 } 253 254 //===----------------------------------------------------------------------===// 255 // Predecessors 256 //===----------------------------------------------------------------------===// 257 258 Block *PredecessorIterator::unwrap(BlockOperand &value) { 259 return value.getOwner()->getBlock(); 260 } 261 262 /// Get the successor number in the predecessor terminator. 263 unsigned PredecessorIterator::getSuccessorIndex() const { 264 return I->getOperandNumber(); 265 }