MLIR 24.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
138} // namespace mlir
139
140namespace llvm {
141
142/// Provide support for hashing successor ranges.
143template <>
144struct DenseMapInfo<mlir::SuccessorRange> {
145 static unsigned getHashValue(mlir::SuccessorRange value) {
146 return llvm::hash_combine_range(value);
147 }
149 return lhs == rhs;
150 }
151};
152
153//===----------------------------------------------------------------------===//
154// ilist_traits for Operation
155//===----------------------------------------------------------------------===//
156
157namespace ilist_detail {
158// Explicitly define the node access for the operation list so that we can
159// break the dependence on the Operation class in this header. This allows for
160// operations to have trailing Regions without a circular include
161// dependence.
162template <>
163struct SpecificNodeAccess<compute_node_options<::mlir::Operation>::type>
164 : NodeAccess {
165protected:
166 using OptionsT = compute_node_options<mlir::Operation>::type;
167 using pointer = OptionsT::pointer;
168 using const_pointer = OptionsT::const_pointer;
169 using node_type = ilist_node_impl<OptionsT>;
170
173
176};
177} // namespace ilist_detail
178
179template <>
180struct ilist_traits<::mlir::Operation> {
182 using op_iterator = simple_ilist<Operation>::iterator;
183
184 static void deleteNode(Operation *op);
185 void addNodeToList(Operation *op);
187 void transferNodesFromList(ilist_traits<Operation> &otherList,
188 op_iterator first, op_iterator last);
189
190private:
191 mlir::Block *getContainingBlock();
192};
193
194//===----------------------------------------------------------------------===//
195// ilist_traits for Block
196//===----------------------------------------------------------------------===//
197
198template <>
199struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
201 using block_iterator = simple_ilist<::mlir::Block>::iterator;
202
203 void addNodeToList(Block *block);
204 void removeNodeFromList(Block *block);
205 void transferNodesFromList(ilist_traits<Block> &otherList,
206 block_iterator first, block_iterator last);
207
208private:
209 mlir::Region *getParentRegion();
210};
211
212} // namespace llvm
213
214#endif // MLIR_IR_BLOCKSUPPORT_H
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:34
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.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:227
Include the generated interface declarations.
static bool isEqual(mlir::SuccessorRange lhs, mlir::SuccessorRange rhs)
static unsigned getHashValue(mlir::SuccessorRange value)
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:213
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:204
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