MLIR 22.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();
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> {
187 static unsigned getHashValue(mlir::SuccessorRange value) {
188 return llvm::hash_combine_range(value);
189 }
191 if (rhs.getBase() == getEmptyKey().getBase())
192 return lhs.getBase() == getEmptyKey().getBase();
193 if (rhs.getBase() == getTombstoneKey().getBase())
194 return lhs.getBase() == getTombstoneKey().getBase();
195 return lhs == rhs;
196 }
197};
198
199//===----------------------------------------------------------------------===//
200// ilist_traits for Operation
201//===----------------------------------------------------------------------===//
202
203namespace ilist_detail {
204// Explicitly define the node access for the operation list so that we can
205// break the dependence on the Operation class in this header. This allows for
206// operations to have trailing Regions without a circular include
207// dependence.
208template <>
209struct SpecificNodeAccess<compute_node_options<::mlir::Operation>::type>
210 : NodeAccess {
211protected:
212 using OptionsT = compute_node_options<mlir::Operation>::type;
213 using pointer = OptionsT::pointer;
214 using const_pointer = OptionsT::const_pointer;
215 using node_type = ilist_node_impl<OptionsT>;
216
219
222};
223} // namespace ilist_detail
224
225template <>
226struct ilist_traits<::mlir::Operation> {
228 using op_iterator = simple_ilist<Operation>::iterator;
229
230 static void deleteNode(Operation *op);
231 void addNodeToList(Operation *op);
233 void transferNodesFromList(ilist_traits<Operation> &otherList,
234 op_iterator first, op_iterator last);
235
236private:
237 mlir::Block *getContainingBlock();
238};
239
240//===----------------------------------------------------------------------===//
241// ilist_traits for Block
242//===----------------------------------------------------------------------===//
243
244template <>
245struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
247 using block_iterator = simple_ilist<::mlir::Block>::iterator;
248
249 void addNodeToList(Block *block);
250 void removeNodeFromList(Block *block);
251 void transferNodesFromList(ilist_traits<Block> &otherList,
252 block_iterator first, block_iterator last);
253
254private:
255 mlir::Region *getParentRegion();
256};
257
258} // namespace llvm
259
260#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()
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:387
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:88
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:340
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:229
Include the generated interface declarations.
static bool isEqual(mlir::SuccessorRange lhs, mlir::SuccessorRange rhs)
static mlir::SuccessorRange getTombstoneKey()
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