MLIR 22.0.0git
Block.cpp
Go to the documentation of this file.
1//===- Block.cpp - MLIR Block Class ---------------------------------------===//
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#include "mlir/IR/Block.h"
10
11#include "mlir/IR/Builders.h"
12#include "mlir/IR/Operation.h"
13
14using namespace mlir;
15
16//===----------------------------------------------------------------------===//
17// Block
18//===----------------------------------------------------------------------===//
19
21 assert(!verifyOpOrder() && "Expected valid operation ordering.");
22 clear();
23 for (BlockArgument arg : arguments)
24 arg.destroy();
25}
26
27Region *Block::getParent() const { return parentValidOpOrderPair.getPointer(); }
28
29/// Returns the closest surrounding operation that contains this block or
30/// nullptr if this block is unlinked.
32 return getParent() ? getParent()->getParentOp() : nullptr;
33}
34
35/// Return if this block is the entry block in the parent region.
36bool Block::isEntryBlock() { return this == &getParent()->front(); }
37
38/// Insert this block (which must not already be in a region) right before the
39/// specified block.
41 assert(!getParent() && "already inserted into a block!");
42 assert(block->getParent() && "cannot insert before a block without a parent");
43 block->getParent()->getBlocks().insert(block->getIterator(), this);
44}
45
47 assert(!getParent() && "already inserted into a block!");
48 assert(block->getParent() && "cannot insert before a block without a parent");
49 block->getParent()->getBlocks().insertAfter(block->getIterator(), this);
50}
51
52/// Unlink this block from its current region and insert it right before the
53/// specific block.
55 assert(block->getParent() && "cannot insert before a block without a parent");
56 moveBefore(block->getParent(), block->getIterator());
57}
58
59/// Unlink this block from its current region and insert it right before the
60/// block that the given iterator points to in the region region.
61void Block::moveBefore(Region *region, llvm::iplist<Block>::iterator iterator) {
62 region->getBlocks().splice(iterator, getParent()->getBlocks(), getIterator());
63}
64
65/// Unlink this Block from its parent Region and delete it.
67 assert(getParent() && "Block has no parent");
68 getParent()->getBlocks().erase(this);
69}
70
71/// Returns 'op' if 'op' lies in this block, or otherwise finds the
72/// ancestor operation of 'op' that lies in this block. Returns nullptr if
73/// the latter fails.
75 // Traverse up the operation hierarchy starting from the owner of operand to
76 // find the ancestor operation that resides in the block of 'forOp'.
77 auto *currOp = &op;
78 while (currOp->getBlock() != this) {
79 currOp = currOp->getParentOp();
80 if (!currOp)
81 return nullptr;
82 }
83 return currOp;
84}
85
86/// This drops all operand uses from operations within this block, which is
87/// an essential step in breaking cyclic dependences between references when
88/// they are to be deleted.
90 for (Operation &i : *this)
92}
93
95 for (auto arg : getArguments())
96 arg.dropAllUses();
97 for (auto &op : *this)
98 op.dropAllDefinedValueUses();
100}
101
102/// Returns true if the ordering of the child operations is valid, false
103/// otherwise.
104bool Block::isOpOrderValid() { return parentValidOpOrderPair.getInt(); }
105
106/// Invalidates the current ordering of operations.
108 // Validate the current ordering.
109 assert(!verifyOpOrder());
110 parentValidOpOrderPair.setInt(false);
111}
112
113/// Verifies the current ordering of child operations. Returns false if the
114/// order is valid, true otherwise.
116 // The order is already known to be invalid.
117 if (!isOpOrderValid())
118 return false;
119 // The order is valid if there are less than 2 operations.
120 if (operations.empty() || llvm::hasSingleElement(operations))
121 return false;
122
123 Operation *prev = nullptr;
124 for (auto &i : *this) {
125 // The previous operation must have a smaller order index than the next as
126 // it appears earlier in the list.
127 if (prev && prev->orderIndex != Operation::kInvalidOrderIdx &&
128 prev->orderIndex >= i.orderIndex)
129 return true;
130 prev = &i;
131 }
132 return false;
133}
134
135/// Recomputes the ordering of child operations within the block.
137 parentValidOpOrderPair.setInt(true);
138
139 unsigned orderIndex = 0;
140 for (auto &op : *this)
141 op.orderIndex = (orderIndex += Operation::kOrderStride);
142}
143
145 assert(getParent() && "cannot compute block number of detached block");
146 return std::distance(getParent()->begin(), getIterator());
147}
148
149//===----------------------------------------------------------------------===//
150// Argument list management.
151//===----------------------------------------------------------------------===//
152
153/// Return a range containing the types of the arguments for this block.
157
159 BlockArgument arg = BlockArgument::create(type, this, arguments.size(), loc);
160 arguments.push_back(arg);
161 return arg;
162}
163
164/// Add one argument to the argument list for each type specified in the list.
167 assert(types.size() == locs.size() &&
168 "incorrect number of block argument locations");
169 size_t initialSize = arguments.size();
170 arguments.reserve(initialSize + types.size());
171
172 for (auto typeAndLoc : llvm::zip(types, locs))
173 addArgument(std::get<0>(typeAndLoc), std::get<1>(typeAndLoc));
174 return {arguments.data() + initialSize, arguments.data() + arguments.size()};
175}
176
178 assert(index <= arguments.size() && "invalid insertion index");
179
180 auto arg = BlockArgument::create(type, this, index, loc);
181 arguments.insert(arguments.begin() + index, arg);
182 // Update the cached position for all the arguments after the newly inserted
183 // one.
184 ++index;
185 for (BlockArgument arg : llvm::drop_begin(arguments, index))
186 arg.setArgNumber(index++);
187 return arg;
188}
189
190/// Insert one value to the given position of the argument list. The existing
191/// arguments are shifted. The block is expected not to have predecessors.
193 assert(getPredecessors().empty() &&
194 "cannot insert arguments to blocks with predecessors");
195 return insertArgument(it->getArgNumber(), type, loc);
196}
197
199 assert(index < arguments.size());
200 arguments[index].destroy();
201 arguments.erase(arguments.begin() + index);
202 for (BlockArgument arg : llvm::drop_begin(arguments, index))
203 arg.setArgNumber(index++);
204}
205
206void Block::eraseArguments(unsigned start, unsigned num) {
207 assert(start + num <= arguments.size());
208 for (unsigned i = 0; i < num; ++i)
209 arguments[start + i].destroy();
210 arguments.erase(arguments.begin() + start, arguments.begin() + start + num);
211 for (BlockArgument arg : llvm::drop_begin(arguments, start))
212 arg.setArgNumber(start++);
213}
214
215void Block::eraseArguments(const BitVector &eraseIndices) {
217 [&](BlockArgument arg) { return eraseIndices.test(arg.getArgNumber()); });
218}
219
221 auto firstDead = llvm::find_if(arguments, shouldEraseFn);
222 if (firstDead == arguments.end())
223 return;
224
225 // Destroy the first dead argument, this avoids reapplying the predicate to
226 // it.
227 unsigned index = firstDead->getArgNumber();
228 firstDead->destroy();
229
230 // Iterate the remaining arguments to remove any that are now dead.
231 for (auto it = std::next(firstDead), e = arguments.end(); it != e; ++it) {
232 // Destroy dead arguments, and shift those that are still live.
233 if (shouldEraseFn(*it)) {
234 it->destroy();
235 } else {
236 it->setArgNumber(index++);
237 *firstDead++ = *it;
238 }
239 }
240 arguments.erase(firstDead, arguments.end());
241}
242
243//===----------------------------------------------------------------------===//
244// Terminator management
245//===----------------------------------------------------------------------===//
246
247/// Get the terminator operation of this block. This function asserts that
248/// the block might have a valid terminator operation.
250 assert(mightHaveTerminator());
251 return &back();
252}
253
254/// Check whether this block might have a terminator.
258
259iterator_range<Block::iterator> Block::without_terminator_impl() {
260 // Note: When the op is unregistered, we do not know for sure if the last
261 // op is a terminator. In that case, we include it in `without_terminator`,
262 // but that decision is somewhat arbitrary.
263 if (!back().hasTrait<OpTrait::IsTerminator>())
264 return {begin(), end()};
265 auto endIt = --end();
266 return {begin(), endIt};
267}
268
269// Indexed successor access.
271 return empty() ? 0 : back().getNumSuccessors();
272}
273
275 assert(i < getNumSuccessors());
276 return getTerminator()->getSuccessor(i);
277}
278
279/// If this block has exactly one predecessor, return it. Otherwise, return
280/// null.
281///
282/// Note that multiple edges from a single block (e.g. if you have a cond
283/// branch with the same block as the true/false destinations) is not
284/// considered to be a single predecessor.
286 auto it = pred_begin();
287 if (it == pred_end())
288 return nullptr;
289 auto *firstPred = *it;
290 ++it;
291 return it == pred_end() ? firstPred : nullptr;
292}
293
294/// If this block has a unique predecessor, i.e., all incoming edges originate
295/// from one block, return it. Otherwise, return null.
297 auto it = pred_begin(), e = pred_end();
298 if (it == e)
299 return nullptr;
300
301 // Check for any conflicting predecessors.
302 auto *firstPred = *it;
303 for (++it; it != e; ++it)
304 if (*it != firstPred)
305 return nullptr;
306 return firstPred;
307}
308
309//===----------------------------------------------------------------------===//
310// Other
311//===----------------------------------------------------------------------===//
312
313/// Split the block into two blocks before the specified operation or
314/// iterator.
315///
316/// Note that all operations BEFORE the specified iterator stay as part of
317/// the original basic block, and the rest of the operations in the original
318/// block are moved to the new block, including the old terminator. The
319/// original block is left without a terminator.
320///
321/// The newly formed Block is returned, and the specified iterator is
322/// invalidated.
324 // Start by creating a new basic block, and insert it immediate after this
325 // one in the containing region.
326 auto *newBB = new Block();
327 getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB);
328
329 // Move all of the operations from the split point to the end of the region
330 // into the new block.
331 newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore,
332 end());
333 return newBB;
334}
335
336//===----------------------------------------------------------------------===//
337// Predecessors
338//===----------------------------------------------------------------------===//
339
340Block *PredecessorIterator::unwrap(BlockOperand &value) {
341 return value.getOwner()->getBlock();
342}
343
344/// Get the successor number in the predecessor terminator.
346 return I->getOperandNumber();
347}
348
349//===----------------------------------------------------------------------===//
350// Successors
351//===----------------------------------------------------------------------===//
352
354
356 if (block->empty() || llvm::hasSingleElement(*block->getParent()))
357 return;
358 Operation *term = &block->back();
359 if ((count = term->getNumSuccessors()))
360 base = term->getBlockOperands().data();
361}
362
364 if ((count = term->getNumSuccessors()))
365 base = term->getBlockOperands().data();
366}
367
369 assert(getParent() == other->getParent() && "expected same region");
370 if (except.contains(other)) {
371 // Fast path: If `other` is in the `except` set, there can be no path from
372 // "this" to `other` (that does not pass through an excluded block).
373 return false;
374 }
376 while (!worklist.empty()) {
377 Block *next = worklist.pop_back_val();
378 if (next == other)
379 return true;
380 // Note: `except` keeps track of already visited blocks.
381 if (!except.insert(next).second)
382 continue;
383 worklist.append(next->succ_begin(), next->succ_end());
384 }
385 return false;
386}
387
388//===----------------------------------------------------------------------===//
389// BlockRange
390//===----------------------------------------------------------------------===//
391
393 if ((count = blocks.size()))
394 base = blocks.data();
395}
396
398 : BlockRange(successors.begin().getBase(), successors.size()) {}
399
400/// See `llvm::detail::indexed_accessor_range_base` for details.
401BlockRange::OwnerT BlockRange::offset_base(OwnerT object, ptrdiff_t index) {
402 if (auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object))
403 return {operand + index};
404 return {llvm::dyn_cast_if_present<Block *const *>(object) + index};
405}
406
407/// See `llvm::detail::indexed_accessor_range_base` for details.
408Block *BlockRange::dereference_iterator(OwnerT object, ptrdiff_t index) {
409 if (const auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object))
410 return operand[index].get();
411 return llvm::dyn_cast_if_present<Block *const *>(object)[index];
412}
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
if(!isCopyOut)
This class represents an argument of a Block.
Definition Value.h:309
unsigned getArgNumber() const
Returns the number of this argument.
Definition Value.h:321
A block operand represents an operand that holds a reference to a Block, e.g.
BlockRange(ArrayRef< Block * > blocks={})
Definition Block.cpp:392
Block represents an ordered list of Operations.
Definition Block.h:33
void recomputeOpOrder()
Recomputes the ordering of child operations within the block.
Definition Block.cpp:136
OpListType::iterator iterator
Definition Block.h:150
Operation * findAncestorOpInBlock(Operation &op)
Returns 'op' if 'op' lies in this block, or otherwise finds the ancestor operation of 'op' that lies ...
Definition Block.cpp:74
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
Definition Block.cpp:154
unsigned getNumSuccessors()
Definition Block.cpp:270
bool empty()
Definition Block.h:158
iterator_range< pred_iterator > getPredecessors()
Definition Block.h:250
void erase()
Unlink this Block from its parent region and delete it.
Definition Block.cpp:66
BlockArgument insertArgument(args_iterator it, Type type, Location loc)
Insert one value to the position in the argument list indicated by the given iterator.
Definition Block.cpp:192
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
Definition Block.cpp:165
Block * splitBlock(iterator splitBefore)
Split the block into two blocks before the specified operation or iterator.
Definition Block.cpp:323
Block()=default
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
bool isOpOrderValid()
Returns true if the ordering of the child operations is valid, false otherwise.
Definition Block.cpp:104
OpListType & getOperations()
Definition Block.h:147
succ_iterator succ_end()
Definition Block.h:279
pred_iterator pred_begin()
Definition Block.h:246
void dropAllDefinedValueUses()
This drops all uses of values defined in this block or in the blocks of nested regions wherever the u...
Definition Block.cpp:94
bool verifyOpOrder()
Verifies the current ordering of child operations matches the validOpOrder flag.
Definition Block.cpp:115
Operation & back()
Definition Block.h:162
void invalidateOpOrder()
Invalidates the current ordering of operations.
Definition Block.cpp:107
Block * getSinglePredecessor()
If this block has exactly one predecessor, return it.
Definition Block.cpp:285
void insertAfter(Block *block)
Insert this block (which must not already be in a region) right after the specified block.
Definition Block.cpp:46
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:249
succ_iterator succ_begin()
Definition Block.h:278
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
void clear()
Definition Block.h:38
void eraseArguments(unsigned start, unsigned num)
Erases 'num' arguments from the index 'start'.
Definition Block.cpp:206
bool mightHaveTerminator()
Return "true" if this block might have a terminator.
Definition Block.cpp:255
BlockArgListType getArguments()
Definition Block.h:97
bool isReachable(Block *other, SmallPtrSet< Block *, 16 > &&except={})
Return "true" if there is a path from this block to the given block (according to the successors rela...
Definition Block.cpp:368
iterator end()
Definition Block.h:154
iterator begin()
Definition Block.h:153
Block * getUniquePredecessor()
If this block has a unique predecessor, i.e., all incoming edges originate from one block,...
Definition Block.cpp:296
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition Block.cpp:198
Block * getSuccessor(unsigned i)
Definition Block.cpp:274
bool isEntryBlock()
Return if this block is the entry block in the parent region.
Definition Block.cpp:36
void dropAllReferences()
This drops all operand uses from operations within this block, which is an essential step in breaking...
Definition Block.cpp:89
void insertBefore(Block *block)
Insert this block (which must not already be in a region) right before the specified block.
Definition Block.cpp:40
pred_iterator pred_end()
Definition Block.h:249
void moveBefore(Block *block)
Unlink this block from its current region and insert it right before the specific block.
Definition Block.cpp:54
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
BlockArgListType::iterator args_iterator
Definition Block.h:102
unsigned computeBlockNumber()
Compute the position of this block within its parent region using an O(N) linear scan.
Definition Block.cpp:144
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
MutableArrayRef< BlockOperand > getBlockOperands()
Definition Operation.h:695
unsigned getNumSuccessors()
Definition Operation.h:706
void dropAllReferences()
This drops all operand uses from this operation, which is an essential step in breaking cyclic depend...
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition Operation.h:757
Block * getBlock()
Returns the operation block that contains this operation.
Definition Operation.h:213
Block * getSuccessor(unsigned index)
Definition Operation.h:708
unsigned getSuccessorIndex() const
Get the successor number in the predecessor terminator.
Definition Block.cpp:345
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Block & front()
Definition Region.h:65
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition Region.h:200
BlockListType & getBlocks()
Definition Region.h:45
BlockListType::iterator iterator
Definition Region.h:52
This class implements the successor iterators for Block.
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:37
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class implements iteration on the types of a given range of values.
Definition TypeRange.h:135
Operation * getOwner() const
Return the owner of this operand.
Definition UseDefLists.h:38
Include the generated interface declarations.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152