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
144//===----------------------------------------------------------------------===//
145// Argument list management.
146//===----------------------------------------------------------------------===//
147
148/// Return a range containing the types of the arguments for this block.
152
154 BlockArgument arg = BlockArgument::create(type, this, arguments.size(), loc);
155 arguments.push_back(arg);
156 return arg;
157}
158
159/// Add one argument to the argument list for each type specified in the list.
162 assert(types.size() == locs.size() &&
163 "incorrect number of block argument locations");
164 size_t initialSize = arguments.size();
165 arguments.reserve(initialSize + types.size());
166
167 for (auto typeAndLoc : llvm::zip(types, locs))
168 addArgument(std::get<0>(typeAndLoc), std::get<1>(typeAndLoc));
169 return {arguments.data() + initialSize, arguments.data() + arguments.size()};
170}
171
173 assert(index <= arguments.size() && "invalid insertion index");
174
175 auto arg = BlockArgument::create(type, this, index, loc);
176 arguments.insert(arguments.begin() + index, arg);
177 // Update the cached position for all the arguments after the newly inserted
178 // one.
179 ++index;
180 for (BlockArgument arg : llvm::drop_begin(arguments, index))
181 arg.setArgNumber(index++);
182 return arg;
183}
184
185/// Insert one value to the given position of the argument list. The existing
186/// arguments are shifted. The block is expected not to have predecessors.
188 assert(getPredecessors().empty() &&
189 "cannot insert arguments to blocks with predecessors");
190 return insertArgument(it->getArgNumber(), type, loc);
191}
192
194 assert(index < arguments.size());
195 arguments[index].destroy();
196 arguments.erase(arguments.begin() + index);
197 for (BlockArgument arg : llvm::drop_begin(arguments, index))
198 arg.setArgNumber(index++);
199}
200
201void Block::eraseArguments(unsigned start, unsigned num) {
202 assert(start + num <= arguments.size());
203 for (unsigned i = 0; i < num; ++i)
204 arguments[start + i].destroy();
205 arguments.erase(arguments.begin() + start, arguments.begin() + start + num);
206 for (BlockArgument arg : llvm::drop_begin(arguments, start))
207 arg.setArgNumber(start++);
208}
209
210void Block::eraseArguments(const BitVector &eraseIndices) {
212 [&](BlockArgument arg) { return eraseIndices.test(arg.getArgNumber()); });
213}
214
216 auto firstDead = llvm::find_if(arguments, shouldEraseFn);
217 if (firstDead == arguments.end())
218 return;
219
220 // Destroy the first dead argument, this avoids reapplying the predicate to
221 // it.
222 unsigned index = firstDead->getArgNumber();
223 firstDead->destroy();
224
225 // Iterate the remaining arguments to remove any that are now dead.
226 for (auto it = std::next(firstDead), e = arguments.end(); it != e; ++it) {
227 // Destroy dead arguments, and shift those that are still live.
228 if (shouldEraseFn(*it)) {
229 it->destroy();
230 } else {
231 it->setArgNumber(index++);
232 *firstDead++ = *it;
233 }
234 }
235 arguments.erase(firstDead, arguments.end());
236}
237
238//===----------------------------------------------------------------------===//
239// Terminator management
240//===----------------------------------------------------------------------===//
241
242/// Get the terminator operation of this block. This function asserts that
243/// the block might have a valid terminator operation.
245 assert(mightHaveTerminator());
246 return &back();
247}
248
249/// Check whether this block might have a terminator.
253
254iterator_range<Block::iterator> Block::without_terminator_impl() {
255 // Note: When the op is unregistered, we do not know for sure if the last
256 // op is a terminator. In that case, we include it in `without_terminator`,
257 // but that decision is somewhat arbitrary.
258 if (!back().hasTrait<OpTrait::IsTerminator>())
259 return {begin(), end()};
260 auto endIt = --end();
261 return {begin(), endIt};
262}
263
264// Indexed successor access.
266 return empty() ? 0 : back().getNumSuccessors();
267}
268
270 assert(i < getNumSuccessors());
271 return getTerminator()->getSuccessor(i);
272}
273
274/// If this block has exactly one predecessor, return it. Otherwise, return
275/// null.
276///
277/// Note that multiple edges from a single block (e.g. if you have a cond
278/// branch with the same block as the true/false destinations) is not
279/// considered to be a single predecessor.
281 auto it = pred_begin();
282 if (it == pred_end())
283 return nullptr;
284 auto *firstPred = *it;
285 ++it;
286 return it == pred_end() ? firstPred : nullptr;
287}
288
289/// If this block has a unique predecessor, i.e., all incoming edges originate
290/// from one block, return it. Otherwise, return null.
292 auto it = pred_begin(), e = pred_end();
293 if (it == e)
294 return nullptr;
295
296 // Check for any conflicting predecessors.
297 auto *firstPred = *it;
298 for (++it; it != e; ++it)
299 if (*it != firstPred)
300 return nullptr;
301 return firstPred;
302}
303
304//===----------------------------------------------------------------------===//
305// Other
306//===----------------------------------------------------------------------===//
307
308/// Split the block into two blocks before the specified operation or
309/// iterator.
310///
311/// Note that all operations BEFORE the specified iterator stay as part of
312/// the original basic block, and the rest of the operations in the original
313/// block are moved to the new block, including the old terminator. The
314/// original block is left without a terminator.
315///
316/// The newly formed Block is returned, and the specified iterator is
317/// invalidated.
319 // Start by creating a new basic block, and insert it immediate after this
320 // one in the containing region.
321 auto *newBB = new Block();
322 getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB);
323
324 // Move all of the operations from the split point to the end of the region
325 // into the new block.
326 newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore,
327 end());
328 return newBB;
329}
330
331//===----------------------------------------------------------------------===//
332// Predecessors
333//===----------------------------------------------------------------------===//
334
335Block *PredecessorIterator::unwrap(BlockOperand &value) {
336 return value.getOwner()->getBlock();
337}
338
339/// Get the successor number in the predecessor terminator.
341 return I->getOperandNumber();
342}
343
344//===----------------------------------------------------------------------===//
345// Successors
346//===----------------------------------------------------------------------===//
347
349
351 if (block->empty() || llvm::hasSingleElement(*block->getParent()))
352 return;
353 Operation *term = &block->back();
354 if ((count = term->getNumSuccessors()))
355 base = term->getBlockOperands().data();
356}
357
359 if ((count = term->getNumSuccessors()))
360 base = term->getBlockOperands().data();
361}
362
364 assert(getParent() == other->getParent() && "expected same region");
365 if (except.contains(other)) {
366 // Fast path: If `other` is in the `except` set, there can be no path from
367 // "this" to `other` (that does not pass through an excluded block).
368 return false;
369 }
371 while (!worklist.empty()) {
372 Block *next = worklist.pop_back_val();
373 if (next == other)
374 return true;
375 // Note: `except` keeps track of already visited blocks.
376 if (!except.insert(next).second)
377 continue;
378 worklist.append(next->succ_begin(), next->succ_end());
379 }
380 return false;
381}
382
383//===----------------------------------------------------------------------===//
384// BlockRange
385//===----------------------------------------------------------------------===//
386
388 if ((count = blocks.size()))
389 base = blocks.data();
390}
391
393 : BlockRange(successors.begin().getBase(), successors.size()) {}
394
395/// See `llvm::detail::indexed_accessor_range_base` for details.
396BlockRange::OwnerT BlockRange::offset_base(OwnerT object, ptrdiff_t index) {
397 if (auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object))
398 return {operand + index};
399 return {llvm::dyn_cast_if_present<Block *const *>(object) + index};
400}
401
402/// See `llvm::detail::indexed_accessor_range_base` for details.
403Block *BlockRange::dereference_iterator(OwnerT object, ptrdiff_t index) {
404 if (const auto *operand = llvm::dyn_cast_if_present<BlockOperand *>(object))
405 return operand[index].get();
406 return llvm::dyn_cast_if_present<Block *const *>(object)[index];
407}
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:387
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:140
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:149
unsigned getNumSuccessors()
Definition Block.cpp:265
bool empty()
Definition Block.h:148
iterator_range< pred_iterator > getPredecessors()
Definition Block.h:240
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:187
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:160
Block * splitBlock(iterator splitBefore)
Split the block into two blocks before the specified operation or iterator.
Definition Block.cpp:318
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:137
succ_iterator succ_end()
Definition Block.h:269
pred_iterator pred_begin()
Definition Block.h:236
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:152
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:280
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:244
succ_iterator succ_begin()
Definition Block.h:268
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:153
void clear()
Definition Block.h:38
void eraseArguments(unsigned start, unsigned num)
Erases 'num' arguments from the index 'start'.
Definition Block.cpp:201
bool mightHaveTerminator()
Return "true" if this block might have a terminator.
Definition Block.cpp:250
BlockArgListType getArguments()
Definition Block.h:87
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:363
iterator end()
Definition Block.h:144
iterator begin()
Definition Block.h:143
Block * getUniquePredecessor()
If this block has a unique predecessor, i.e., all incoming edges originate from one block,...
Definition Block.cpp:291
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
Definition Block.cpp:193
Block * getSuccessor(unsigned i)
Definition Block.cpp:269
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:239
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:92
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:340
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