MLIR 23.0.0git
Block.h
Go to the documentation of this file.
1//===- Block.h - MLIR Block Class -------------------------------*- C++ -*-===//
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// This file defines the Block class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_IR_BLOCK_H
14#define MLIR_IR_BLOCK_H
15
17#include "mlir/IR/Visitors.h"
18
19#include "llvm/ADT/SmallPtrSet.h"
20
21namespace llvm {
22class BitVector;
23class raw_ostream;
24} // namespace llvm
25
26namespace mlir {
27class TypeRange;
28template <typename ValueRangeT>
29class ValueTypeRange;
30
31/// `Block` represents an ordered list of `Operation`s.
32class alignas(8) Block : public IRObjectWithUseList<BlockOperand>,
33 public llvm::ilist_node_with_parent<Block, Region> {
34public:
35 explicit Block() = default;
36 ~Block();
37
38 void clear() {
39 // Drop all references from within this block.
41
42 // Clear operations in the reverse order so that uses are destroyed
43 // before their defs.
44 while (!empty())
45 operations.pop_back();
46 }
47
48 /// Provide a 'getParent' method for ilist_node_with_parent methods.
49 /// We mark it as a const function because ilist_node_with_parent specifically
50 /// requires a 'getParent() const' method. Once ilist_node removes this
51 /// constraint, we should drop the const to fit the rest of the MLIR const
52 /// model.
53 Region *getParent() const;
54
55 /// Return an ID uniquely identifying this block within its parent region.
56 /// The ID is assigned when the block joins a region and reassigned when the
57 /// block is moved to a different region; it is stable while the block stays
58 /// in a region, and removing a block leaves a hole (IDs are not reused). Only
59 /// valid for a block that is in a region.
60 ///
61 /// Unlike computeBlockNumber(), this is O(1) and stable; it exists so that
62 /// generic graph algorithms (e.g. LoopInfo, DominatorTree) can index blocks
63 /// by ID.
64 unsigned getBlockID() const {
65 assert(getParent() && "only blocks in a region have a valid ID");
66 return blockID;
67 }
68
69 /// Returns the closest surrounding operation that contains this block.
71
72 /// Return if this block is the entry block in the parent region.
73 bool isEntryBlock();
74
75 /// Insert this block (which must not already be in a region) right before
76 /// the specified block.
77 void insertBefore(Block *block);
78
79 /// Insert this block (which must not already be in a region) right after
80 /// the specified block.
81 void insertAfter(Block *block);
82
83 /// Unlink this block from its current region and insert it right before the
84 /// specific block.
85 void moveBefore(Block *block);
86
87 /// Unlink this block from its current region and insert it right before the
88 /// block that the given iterator points to in the region region.
89 void moveBefore(Region *region, llvm::iplist<Block>::iterator iterator);
90
91 /// Unlink this Block from its parent region and delete it.
92 void erase();
93
94 /// Compute the position of this block within its parent region using an O(N)
95 /// linear scan.
96 ///
97 /// Note: There is no semantic meaning to a block number. Blocks are used for
98 /// unstructured control flow and relying on block numbers for functional
99 /// purposes may indicate a design flaw. (You can give semantic meaning to
100 /// region numbers instead.) Block numbers are useful for debugging purposes
101 /// and for error messages.
102 unsigned computeBlockNumber();
103
104 //===--------------------------------------------------------------------===//
105 // Block argument management
106 //===--------------------------------------------------------------------===//
107
108 // This is the list of arguments to the block.
110
111 BlockArgListType getArguments() { return arguments; }
112
113 /// Return a range containing the types of the arguments for this block.
115
116 using args_iterator = BlockArgListType::iterator;
117 using reverse_args_iterator = BlockArgListType::reverse_iterator;
118 args_iterator args_begin() { return getArguments().begin(); }
119 args_iterator args_end() { return getArguments().end(); }
122
123 bool args_empty() { return arguments.empty(); }
124
125 /// Add one value to the argument list.
127
128 /// Insert one value to the position in the argument list indicated by the
129 /// given iterator. The existing arguments are shifted. The block is expected
130 /// not to have predecessors.
132
133 /// Add one argument to the argument list for each type specified in the list.
134 /// `locs` is required to have the same number of elements as `types`.
136 ArrayRef<Location> locs);
137
138 /// Add one value to the argument list at the specified position.
139 BlockArgument insertArgument(unsigned index, Type type, Location loc);
140
141 /// Erase the argument at 'index' and remove it from the argument list.
142 void eraseArgument(unsigned index);
143 /// Erases 'num' arguments from the index 'start'.
144 void eraseArguments(unsigned start, unsigned num);
145 /// Erases the arguments that have their corresponding bit set in
146 /// `eraseIndices` and removes them from the argument list.
147 void eraseArguments(const BitVector &eraseIndices);
148 /// Erases arguments using the given predicate. If the predicate returns true,
149 /// that argument is erased.
150 void eraseArguments(function_ref<bool(BlockArgument)> shouldEraseFn);
151
152 unsigned getNumArguments() { return arguments.size(); }
153 BlockArgument getArgument(unsigned i) { return arguments[i]; }
154
155 //===--------------------------------------------------------------------===//
156 // Operation list management
157 //===--------------------------------------------------------------------===//
158
159 /// This is the list of operations in the block.
160 using OpListType = llvm::iplist<Operation>;
161 OpListType &getOperations() { return operations; }
162
163 // Iteration over the operations in the block.
164 using iterator = OpListType::iterator;
165 using reverse_iterator = OpListType::reverse_iterator;
166
167 iterator begin() { return operations.begin(); }
168 iterator end() { return operations.end(); }
169 reverse_iterator rbegin() { return operations.rbegin(); }
170 reverse_iterator rend() { return operations.rend(); }
171
172 bool empty() { return operations.empty(); }
173 void push_back(Operation *op) { operations.push_back(op); }
174 void push_front(Operation *op) { operations.push_front(op); }
175
176 Operation &back() { return operations.back(); }
177 Operation &front() { return operations.front(); }
178
179 /// Returns 'op' if 'op' lies in this block, or otherwise finds the
180 /// ancestor operation of 'op' that lies in this block. Returns nullptr if
181 /// the latter fails.
182 /// TODO: This is very specific functionality that should live somewhere else,
183 /// probably in Dominance.cpp.
185
186 /// This drops all operand uses from operations within this block, which is
187 /// an essential step in breaking cyclic dependences between references when
188 /// they are to be deleted.
189 void dropAllReferences();
190
191 /// This drops all uses of values defined in this block or in the blocks of
192 /// nested regions wherever the uses are located.
194
195 /// Returns true if the ordering of the child operations is valid, false
196 /// otherwise.
197 bool isOpOrderValid();
198
199 /// Invalidates the current ordering of operations.
200 void invalidateOpOrder();
201
202 /// Verifies the current ordering of child operations matches the
203 /// validOpOrder flag. Returns false if the order is valid, true otherwise.
204 bool verifyOpOrder();
205
206 /// Recomputes the ordering of child operations within the block.
207 void recomputeOpOrder();
208
209 /// This class provides iteration over the held operations of a block for a
210 /// specific operation type.
211 template <typename OpT>
213
214 /// Return an iterator range over the operations within this block that are of
215 /// 'OpT'.
216 template <typename OpT>
222 template <typename OpT>
226 template <typename OpT>
230
231 /// Return an iterator range over the operation within this block excluding
232 /// the terminator operation at the end. If the block has no terminator,
233 /// return an iterator range over the entire block. If it is unknown if the
234 /// block has a terminator (i.e., last block operation is unregistered), also
235 /// return an iterator range over the entire block.
237 if (begin() == end())
238 return {begin(), end()};
239 return without_terminator_impl();
240 }
241
242 //===--------------------------------------------------------------------===//
243 // Terminator management
244 //===--------------------------------------------------------------------===//
245
246 /// Get the terminator operation of this block. This function asserts that
247 /// the block might have a valid terminator operation.
249
250 /// Return "true" if this block might have a terminator. Return "true" if
251 /// the last operation is unregistered.
252 bool mightHaveTerminator();
253
254 //===--------------------------------------------------------------------===//
255 // Predecessors and successors.
256 //===--------------------------------------------------------------------===//
257
258 // Predecessor iteration.
263 pred_iterator pred_end() { return pred_iterator(nullptr); }
267
268 /// Return true if this block has no predecessors.
269 bool hasNoPredecessors() { return pred_begin() == pred_end(); }
270
271 /// Returns true if this blocks has no successors.
272 bool hasNoSuccessors() { return succ_begin() == succ_end(); }
273
274 /// If this block has exactly one predecessor, return it. Otherwise, return
275 /// null.
276 ///
277 /// Note that if a block has duplicate predecessors from a single block (e.g.
278 /// if you have a conditional branch with the same block as the true/false
279 /// destinations) is not considered to be a single predecessor.
281
282 /// If this block has a unique predecessor, i.e., all incoming edges originate
283 /// from one block, return it. Otherwise, return null.
285
286 // Indexed successor access.
287 unsigned getNumSuccessors();
288 Block *getSuccessor(unsigned i);
289
290 // Successor iteration.
291 using succ_iterator = SuccessorRange::iterator;
292 succ_iterator succ_begin() { return getSuccessors().begin(); }
295
296 /// Return "true" if there is a path from this block to the given block
297 /// (according to the successors relationship). Both blocks must be in the
298 /// same region. Paths that contain a block from `except` do not count.
299 /// This function returns "false" if `other` is in `except`.
300 ///
301 /// Note: This function performs a block graph traversal and its complexity
302 /// linear in the number of blocks in the parent region.
303 ///
304 /// Note: Reachability is a necessary but insufficient condition for
305 /// dominance. Do not use this function in places where you need to check for
306 /// dominance.
307 bool isReachable(Block *other, SmallPtrSet<Block *, 16> &&except = {});
308
309 //===--------------------------------------------------------------------===//
310 // Walkers
311 //===--------------------------------------------------------------------===//
312
313 /// Walk all nested operations, blocks (including this block) or regions,
314 /// depending on the type of callback.
315 ///
316 /// The order in which operations, blocks or regions at the same nesting
317 /// level are visited (e.g., lexicographical or reverse lexicographical order)
318 /// is determined by `Iterator`. The walk order for enclosing operations,
319 /// blocks or regions with respect to their nested ones is specified by
320 /// `Order` (post-order by default).
321 ///
322 /// A callback on a operation or block is allowed to erase that operation or
323 /// block if either:
324 /// * the walk is in post-order, or
325 /// * the walk is in pre-order and the walk is skipped after the erasure.
326 ///
327 /// See Operation::walk for more details.
328 template <WalkOrder Order = WalkOrder::PostOrder,
329 typename Iterator = ForwardIterator, typename FnT,
330 typename ArgT = detail::first_argument<FnT>,
331 typename RetT = detail::walkResultType<FnT>>
332 RetT walk(FnT &&callback) {
333 if constexpr (std::is_same<ArgT, Block *>::value &&
334 Order == WalkOrder::PreOrder) {
335 // Pre-order walk on blocks: invoke the callback on this block.
336 if constexpr (std::is_same<RetT, void>::value) {
337 callback(this);
338 } else {
339 RetT result = callback(this);
340 if (result.wasSkipped())
341 return WalkResult::advance();
342 if (result.wasInterrupted())
343 return WalkResult::interrupt();
344 }
345 }
346
347 // Walk nested operations, blocks or regions.
348 if constexpr (std::is_same<RetT, void>::value) {
349 walk<Order, Iterator>(begin(), end(), std::forward<FnT>(callback));
350 } else {
351 if (walk<Order, Iterator>(begin(), end(), std::forward<FnT>(callback))
352 .wasInterrupted())
353 return WalkResult::interrupt();
354 }
355
356 if constexpr (std::is_same<ArgT, Block *>::value &&
357 Order == WalkOrder::PostOrder) {
358 // Post-order walk on blocks: invoke the callback on this block.
359 return callback(this);
360 }
361 if constexpr (!std::is_same<RetT, void>::value)
362 return WalkResult::advance();
363 }
364
365 /// Walk all nested operations, blocks (excluding this block) or regions,
366 /// depending on the type of callback, in the specified [begin, end) range of
367 /// this block.
368 ///
369 /// The order in which operations, blocks or regions at the same nesting
370 /// level are visited (e.g., lexicographical or reverse lexicographical order)
371 /// is determined by `Iterator`. The walk order for enclosing operations,
372 /// blocks or regions with respect to their nested ones is specified by
373 /// `Order` (post-order by default).
374 ///
375 /// A callback on a operation or block is allowed to erase that operation or
376 /// block if either:
377 /// * the walk is in post-order, or
378 /// * the walk is in pre-order and the walk is skipped after the erasure.
379 ///
380 /// See Operation::walk for more details.
381 template <WalkOrder Order = WalkOrder::PostOrder,
382 typename Iterator = ForwardIterator, typename FnT,
383 typename RetT = detail::walkResultType<FnT>>
385 for (auto &op : llvm::make_early_inc_range(llvm::make_range(begin, end))) {
386 if constexpr (std::is_same<RetT, WalkResult>::value) {
387 if (detail::walk<Order, Iterator>(&op, callback).wasInterrupted())
388 return WalkResult::interrupt();
389 } else {
390 detail::walk<Order, Iterator>(&op, callback);
391 }
392 }
393 if constexpr (std::is_same<RetT, WalkResult>::value)
394 return WalkResult::advance();
395 }
396
397 //===--------------------------------------------------------------------===//
398 // Other
399 //===--------------------------------------------------------------------===//
400
401 /// Split the block into two blocks before the specified operation or
402 /// iterator.
403 ///
404 /// Note that all operations BEFORE the specified iterator stay as part of
405 /// the original basic block, and the rest of the operations in the original
406 /// block are moved to the new block, including the old terminator. The
407 /// original block is left without a terminator.
408 ///
409 /// The newly formed Block is returned, and the specified iterator is
410 /// invalidated.
411 Block *splitBlock(iterator splitBefore);
412 Block *splitBlock(Operation *splitBeforeOp) {
413 return splitBlock(iterator(splitBeforeOp));
414 }
415
416 /// Returns pointer to member of operation list.
418 return &Block::operations;
419 }
420
421 void print(raw_ostream &os);
422 void print(raw_ostream &os, AsmState &state);
423 void dump();
424
425 /// Print out the name of the block without printing its body.
426 /// NOTE: The printType argument is ignored. We keep it for compatibility
427 /// with LLVM dominator machinery that expects it to exist.
428 void printAsOperand(raw_ostream &os, bool printType = true);
429 void printAsOperand(raw_ostream &os, AsmState &state);
430
431private:
432 /// Same as `without_terminator`, but assumes that the block is not empty.
433 iterator_range<iterator> without_terminator_impl();
434
435 /// Pair of the parent object that owns this block and a bit that signifies if
436 /// the operations within this block have a valid ordering.
437 llvm::PointerIntPair<Region *, /*IntBits=*/1, bool> parentValidOpOrderPair;
438
439 /// Unique ID of this block within its parent region, (re)assigned when the
440 /// block joins a region; -1u while the block has no parent. See getBlockID().
441 unsigned blockID = -1u;
442
443 /// This is the list of operations in the block.
444 OpListType operations;
445
446 /// This is the list of arguments to the block.
447 std::vector<BlockArgument> arguments;
448
449 Block(Block &) = delete;
450 void operator=(Block &) = delete;
451
452 friend struct llvm::ilist_traits<Block>;
453 friend class Region;
454};
455
457} // namespace mlir
458
459namespace llvm {
460template <>
461struct DenseMapInfo<mlir::Block::iterator> {
462 static unsigned getHashValue(mlir::Block::iterator iter) {
463 return hash_value(iter.getNodePtr());
464 }
466 return lhs == rhs;
467 }
468};
469
470} // end namespace llvm
471
472#endif // MLIR_IR_BLOCK_H
lhs
This class provides management for the lifetime of the state used when printing the IR.
Definition AsmState.h:542
This class represents an argument of a Block.
Definition Value.h:306
A block operand represents an operand that holds a reference to a Block, e.g.
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
MutableArrayRef< BlockArgument > BlockArgListType
Definition Block.h:109
OpListType::iterator iterator
Definition Block.h:164
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
void push_front(Operation *op)
Definition Block.h:174
SuccessorRange::iterator succ_iterator
Definition Block.h:291
bool empty()
Definition Block.h:172
BlockArgument getArgument(unsigned i)
Definition Block.h:153
bool hasNoSuccessors()
Returns true if this blocks has no successors.
Definition Block.h:272
unsigned getNumArguments()
Definition Block.h:152
iterator_range< pred_iterator > getPredecessors()
Definition Block.h:264
op_iterator< OpT > op_begin()
Definition Block.h:223
void erase()
Unlink this Block from its parent region and delete it.
Definition Block.cpp:66
iterator_range< op_iterator< OpT > > getOps()
Return an iterator range over the operations within this block that are of 'OpT'.
Definition Block.h:217
detail::op_iterator< OpT, iterator > op_iterator
This class provides iteration over the held operations of a block for a specific operation type.
Definition Block.h:212
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:161
BlockArgListType::reverse_iterator reverse_args_iterator
Definition Block.h:117
args_iterator args_end()
Definition Block.h:119
Operation & front()
Definition Block.h:177
succ_iterator succ_end()
Definition Block.h:293
pred_iterator pred_begin()
Definition Block.h:260
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
SuccessorRange getSuccessors()
Definition Block.h:294
Operation & back()
Definition Block.h:176
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 printAsOperand(raw_ostream &os, bool printType=true)
Print out the name of the block without printing its body.
reverse_args_iterator args_rend()
Definition Block.h:121
RetT walk(FnT &&callback)
Walk all nested operations, blocks (including this block) or regions, depending on the type of callba...
Definition Block.h:332
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:292
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
RetT walk(Block::iterator begin, Block::iterator end, FnT &&callback)
Walk all nested operations, blocks (excluding this block) or regions, depending on the type of callba...
Definition Block.h:384
void clear()
Definition Block.h:38
void eraseArguments(unsigned start, unsigned num)
Erases 'num' arguments from the index 'start'.
Definition Block.cpp:206
reverse_iterator rend()
Definition Block.h:170
void print(raw_ostream &os)
bool args_empty()
Definition Block.h:123
bool mightHaveTerminator()
Return "true" if this block might have a terminator.
Definition Block.cpp:255
BlockArgListType getArguments()
Definition Block.h:111
PredecessorIterator pred_iterator
Definition Block.h:259
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
Definition Block.h:236
op_iterator< OpT > op_end()
Definition Block.h:227
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:168
iterator begin()
Definition Block.h:167
friend class Region
Definition Block.h:453
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
args_iterator args_begin()
Definition Block.h:118
unsigned getBlockID() const
Return an ID uniquely identifying this block within its parent region.
Definition Block.h:64
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
Block * splitBlock(Operation *splitBeforeOp)
Definition Block.h:412
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:263
void moveBefore(Block *block)
Unlink this block from its current region and insert it right before the specific block.
Definition Block.cpp:54
void push_back(Operation *op)
Definition Block.h:173
reverse_args_iterator args_rbegin()
Definition Block.h:120
bool hasNoPredecessors()
Return true if this block has no predecessors.
Definition Block.h:269
static OpListType Block::* getSublistAccess(Operation *)
Returns pointer to member of operation list.
Definition Block.h:417
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
BlockArgListType::iterator args_iterator
Definition Block.h:116
reverse_iterator rbegin()
Definition Block.h:169
OpListType::reverse_iterator reverse_iterator
Definition Block.h:165
llvm::iplist< Operation > OpListType
This is the list of operations in the block.
Definition Block.h:160
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
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
Implement a predecessor iterator for blocks.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
This class implements the successor iterators for Block.
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:40
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:147
static WalkResult advance()
Definition WalkResult.h:47
static WalkResult interrupt()
Definition WalkResult.h:46
A utility iterator that filters out operations that are not 'OpT'.
This class provides iteration over the held operations of a block for a specific operation type.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:227
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
Definition Visitors.h:102
decltype(first_argument_type(std::declval< T >())) first_argument
Type definition of the first argument to the given callable 'T'.
Definition Visitors.h:90
decltype(walk(nullptr, std::declval< FnT >())) walkResultType
Utility to provide the return type of a templated walk method.
Definition Visitors.h:433
Include the generated interface declarations.
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition Visitors.h:28
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147
static bool isEqual(mlir::Block::iterator lhs, mlir::Block::iterator rhs)
Definition Block.h:465
static unsigned getHashValue(mlir::Block::iterator iter)
Definition Block.h:462
This iterator enumerates the elements in "forward" order.
Definition Visitors.h:31