MLIR 23.0.0git
BlockSupport.h
Go to the documentation of this file.
1//===- BlockSupport.h -------------------------------------------*- 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 a number of support types for the Block class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_IR_BLOCKSUPPORT_H
14#define MLIR_IR_BLOCKSUPPORT_H
15
16#include "mlir/IR/Value.h"
17#include "llvm/ADT/PointerUnion.h"
18#include "llvm/ADT/ilist.h"
19#include "llvm/ADT/ilist_node.h"
20
21namespace mlir {
22class Block;
23
24//===----------------------------------------------------------------------===//
25// BlockOperand
26//===----------------------------------------------------------------------===//
27
28/// A block operand represents an operand that holds a reference to a Block,
29/// e.g. for terminator operations.
30class BlockOperand : public IROperand<BlockOperand, Block *> {
31public:
33
34 /// Provide the use list that is attached to the given block.
36
37 /// Return which operand this is in the BlockOperand list of the Operation.
38 unsigned getOperandNumber() const;
39};
40
41//===----------------------------------------------------------------------===//
42// Predecessors
43//===----------------------------------------------------------------------===//
44
45/// Implement a predecessor iterator for blocks. This works by walking the use
46/// lists of the blocks. The entries on this list are the BlockOperands that
47/// are embedded into terminator operations. From the operand, we can get the
48/// terminator that contains it, and its parent block is the predecessor.
50 : public llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
51 Block *(*)(BlockOperand &)> {
52 static Block *unwrap(BlockOperand &value);
53
54public:
55 /// Initializes the operand type iterator to the specified operand iterator.
61
62 /// Get the successor number in the predecessor terminator.
63 unsigned getSuccessorIndex() const;
64};
65
66//===----------------------------------------------------------------------===//
67// Successors
68//===----------------------------------------------------------------------===//
69
70/// This class implements the successor iterators for Block.
71class SuccessorRange final
73 SuccessorRange, BlockOperand *, Block *, Block *, Block *> {
74public:
75 using RangeBaseT::RangeBaseT;
77 SuccessorRange(Block *block);
79
80private:
81 /// See `llvm::detail::indexed_accessor_range_base` for details.
82 static BlockOperand *offset_base(BlockOperand *object, ptrdiff_t index) {
83 return object + index;
84 }
85 /// See `llvm::detail::indexed_accessor_range_base` for details.
86 static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) {
87 return object[index].get();
88 }
89
90 /// Allow access to `offset_base` and `dereference_iterator`.
91 friend RangeBaseT;
92};
93
94//===----------------------------------------------------------------------===//
95// BlockRange
96//===----------------------------------------------------------------------===//
97
98/// This class provides an abstraction over the different types of ranges over
99/// Blocks. In many cases, this prevents the need to explicitly materialize a
100/// SmallVector/std::vector. This class should be used in places that are not
101/// suitable for a more derived type (e.g. ArrayRef) or a template range
102/// parameter.
103class BlockRange final
105 BlockRange, llvm::PointerUnion<BlockOperand *, Block *const *>,
106 Block *, Block *, Block *> {
107public:
108 using RangeBaseT::RangeBaseT;
109 BlockRange(ArrayRef<Block *> blocks = {});
110 BlockRange(SuccessorRange successors);
111 template <typename Arg, typename = std::enable_if_t<std::is_constructible<
112 ArrayRef<Block *>, Arg>::value>>
113 BlockRange(Arg &&arg LLVM_LIFETIME_BOUND)
114 : BlockRange(ArrayRef<Block *>(std::forward<Arg>(arg))) {}
115 BlockRange(std::initializer_list<Block *> blocks LLVM_LIFETIME_BOUND)
116 : BlockRange(ArrayRef<Block *>(blocks)) {}
117
118private:
119 /// The owner of the range is either:
120 /// * A pointer to the first element of an array of block operands.
121 /// * A pointer to the first element of an array of Block *.
123
124 /// See `llvm::detail::indexed_accessor_range_base` for details.
125 static OwnerT offset_base(OwnerT object, ptrdiff_t index);
126
127 /// See `llvm::detail::indexed_accessor_range_base` for details.
128 static Block *dereference_iterator(OwnerT object, ptrdiff_t index);
129
130 /// Allow access to `offset_base` and `dereference_iterator`.
131 friend RangeBaseT;
132};
133
134//===----------------------------------------------------------------------===//
135// Operation Iterators
136//===----------------------------------------------------------------------===//
137
138namespace detail {
139/// A utility iterator that filters out operations that are not 'OpT'.
140template <typename OpT, typename IteratorT>
142 : public llvm::filter_iterator<IteratorT, bool (*)(Operation &)> {
143 static bool filter(Operation &op) { return llvm::isa<OpT>(op); }
144
145public:
146 op_filter_iterator(IteratorT it, IteratorT end)
147 : llvm::filter_iterator<IteratorT, bool (*)(Operation &)>(it, end,
148 &filter) {}
149
150 /// Allow implicit conversion to the underlying iterator.
151 operator const IteratorT &() const { return this->wrapped(); }
152};
153
154/// This class provides iteration over the held operations of a block for a
155/// specific operation type.
156template <typename OpT, typename IteratorT>
158 : public llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>,
159 OpT (*)(Operation &)> {
160 static OpT unwrap(Operation &op) { return cast<OpT>(op); }
161
162public:
163 /// Initializes the iterator to the specified filter iterator.
165 : llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>,
166 OpT (*)(Operation &)>(it, &unwrap) {}
167
168 /// Allow implicit conversion to the underlying block iterator.
169 operator const IteratorT &() const { return this->wrapped(); }
170};
171} // namespace detail
172} // namespace mlir
173
174namespace llvm {
175
176/// Provide support for hashing successor ranges.
177template <>
178struct DenseMapInfo<mlir::SuccessorRange> {
183 static unsigned getHashValue(mlir::SuccessorRange value) {
184 return llvm::hash_combine_range(value);
185 }
187 if (rhs.getBase() == getEmptyKey().getBase())
188 return lhs.getBase() == getEmptyKey().getBase();
189 return lhs == rhs;
190 }
191};
192
193//===----------------------------------------------------------------------===//
194// ilist_traits for Operation
195//===----------------------------------------------------------------------===//
196
197namespace ilist_detail {
198// Explicitly define the node access for the operation list so that we can
199// break the dependence on the Operation class in this header. This allows for
200// operations to have trailing Regions without a circular include
201// dependence.
202template <>
203struct SpecificNodeAccess<compute_node_options<::mlir::Operation>::type>
204 : NodeAccess {
205protected:
206 using OptionsT = compute_node_options<mlir::Operation>::type;
207 using pointer = OptionsT::pointer;
208 using const_pointer = OptionsT::const_pointer;
209 using node_type = ilist_node_impl<OptionsT>;
210
213
216};
217} // namespace ilist_detail
218
219template <>
220struct ilist_traits<::mlir::Operation> {
222 using op_iterator = simple_ilist<Operation>::iterator;
223
224 static void deleteNode(Operation *op);
225 void addNodeToList(Operation *op);
227 void transferNodesFromList(ilist_traits<Operation> &otherList,
228 op_iterator first, op_iterator last);
229
230private:
231 mlir::Block *getContainingBlock();
232};
233
234//===----------------------------------------------------------------------===//
235// ilist_traits for Block
236//===----------------------------------------------------------------------===//
237
238template <>
239struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
241 using block_iterator = simple_ilist<::mlir::Block>::iterator;
242
243 void addNodeToList(Block *block);
244 void removeNodeFromList(Block *block);
245 void transferNodesFromList(ilist_traits<Block> &otherList,
246 block_iterator first, block_iterator last);
247
248private:
249 mlir::Region *getParentRegion();
250};
251
252} // namespace llvm
253
254#endif // MLIR_IR_BLOCKSUPPORT_H
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
lhs
A block operand represents an operand that holds a reference to a Block, e.g.
unsigned getOperandNumber() const
Return which operand this is in the BlockOperand list of the Operation.
Definition Value.cpp:217
static IRObjectWithUseList< BlockOperand > * getUseList(Block *value)
Provide the use list that is attached to the given block.
Definition Value.cpp:212
BlockRange(Arg &&arg LLVM_LIFETIME_BOUND)
BlockRange(ArrayRef< Block * > blocks={})
Definition Block.cpp:392
BlockRange(std::initializer_list< Block * > blocks LLVM_LIFETIME_BOUND)
Block represents an ordered list of Operations.
Definition Block.h:33
This class represents a single IR object that contains a use list.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
PredecessorIterator(ValueUseIterator< BlockOperand > it)
Initializes the operand type iterator to the specified operand iterator.
PredecessorIterator(BlockOperand *operand)
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
This class implements the successor iterators for Block.
An iterator class that allows for iterating over the uses of an IR operand type.
A utility iterator that filters out operations that are not 'OpT'.
op_filter_iterator(IteratorT it, IteratorT end)
op_iterator(op_filter_iterator< OpT, IteratorT > it)
Initializes the iterator to the specified filter iterator.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:228
Include the generated interface declarations.
static bool isEqual(mlir::SuccessorRange lhs, mlir::SuccessorRange rhs)
static unsigned getHashValue(mlir::SuccessorRange value)
static mlir::SuccessorRange getEmptyKey()
void transferNodesFromList(ilist_traits< Block > &otherList, block_iterator first, block_iterator last)
This is a trait method invoked when an operation is moved from one block to another.
Definition Region.cpp:209
simple_ilist<::mlir::Block >::iterator block_iterator
void removeNodeFromList(Block *block)
This is a trait method invoked when an operation is removed from a region.
Definition Region.cpp:202
void addNodeToList(Block *block)
This is a trait method invoked when a basic block is added to a region.
Definition Region.cpp:195
void removeNodeFromList(Operation *op)
This is a trait method invoked when an operation is removed from a block.
void transferNodesFromList(ilist_traits< Operation > &otherList, op_iterator first, op_iterator last)
This is a trait method invoked when an operation is moved from one block to another.
void addNodeToList(Operation *op)
This is a trait method invoked when an operation is added to a block.
static void deleteNode(Operation *op)
simple_ilist< Operation >::iterator op_iterator