xref: /llvm-project-15.0.7/mlir/lib/IR/Block.cpp (revision 6273fa0c)
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