MLIR  15.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 
21 namespace mlir {
22 class 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.
30 class BlockOperand : public IROperand<BlockOperand, Block *> {
31 public:
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 
54 public:
55 
56  /// Initializes the operand type iterator to the specified operand iterator.
58  : llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
59  Block *(*)(BlockOperand &)>(it, &unwrap) {}
60  explicit PredecessorIterator(BlockOperand *operand)
62 
63  /// Get the successor number in the predecessor terminator.
64  unsigned getSuccessorIndex() const;
65 };
66 
67 //===----------------------------------------------------------------------===//
68 // Successors
69 //===----------------------------------------------------------------------===//
70 
71 /// This class implements the successor iterators for Block.
72 class SuccessorRange final
74  SuccessorRange, BlockOperand *, Block *, Block *, Block *> {
75 public:
76  using RangeBaseT::RangeBaseT;
78  SuccessorRange(Block *block);
80 
81 private:
82  /// See `llvm::detail::indexed_accessor_range_base` for details.
83  static BlockOperand *offset_base(BlockOperand *object, ptrdiff_t index) {
84  return object + index;
85  }
86  /// See `llvm::detail::indexed_accessor_range_base` for details.
87  static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) {
88  return object[index].get();
89  }
90 
91  /// Allow access to `offset_base` and `dereference_iterator`.
92  friend RangeBaseT;
93 };
94 
95 //===----------------------------------------------------------------------===//
96 // BlockRange
97 //===----------------------------------------------------------------------===//
98 
99 /// This class provides an abstraction over the different types of ranges over
100 /// Blocks. In many cases, this prevents the need to explicitly materialize a
101 /// SmallVector/std::vector. This class should be used in places that are not
102 /// suitable for a more derived type (e.g. ArrayRef) or a template range
103 /// parameter.
104 class BlockRange final
106  BlockRange, llvm::PointerUnion<BlockOperand *, Block *const *>,
107  Block *, Block *, Block *> {
108 public:
109  using RangeBaseT::RangeBaseT;
110  BlockRange(ArrayRef<Block *> blocks = llvm::None);
111  BlockRange(SuccessorRange successors);
112  template <typename Arg,
113  typename = typename std::enable_if_t<
114  std::is_constructible<ArrayRef<Block *>, Arg>::value>>
115  BlockRange(Arg &&arg)
116  : BlockRange(ArrayRef<Block *>(std::forward<Arg>(arg))) {}
117  BlockRange(std::initializer_list<Block *> blocks)
118  : BlockRange(ArrayRef<Block *>(blocks)) {}
119 
120 private:
121  /// The owner of the range is either:
122  /// * A pointer to the first element of an array of block operands.
123  /// * A pointer to the first element of an array of Block *.
125 
126  /// See `llvm::detail::indexed_accessor_range_base` for details.
127  static OwnerT offset_base(OwnerT object, ptrdiff_t index);
128 
129  /// See `llvm::detail::indexed_accessor_range_base` for details.
130  static Block *dereference_iterator(OwnerT object, ptrdiff_t index);
131 
132  /// Allow access to `offset_base` and `dereference_iterator`.
133  friend RangeBaseT;
134 };
135 
136 //===----------------------------------------------------------------------===//
137 // Operation Iterators
138 //===----------------------------------------------------------------------===//
139 
140 namespace detail {
141 /// A utility iterator that filters out operations that are not 'OpT'.
142 template <typename OpT, typename IteratorT>
144  : public llvm::filter_iterator<IteratorT, bool (*)(Operation &)> {
145  static bool filter(Operation &op) { return llvm::isa<OpT>(op); }
146 
147 public:
148  op_filter_iterator(IteratorT it, IteratorT end)
149  : llvm::filter_iterator<IteratorT, bool (*)(Operation &)>(it, end,
150  &filter) {}
151 
152  /// Allow implicit conversion to the underlying iterator.
153  operator const IteratorT &() const { return this->wrapped(); }
154 };
155 
156 /// This class provides iteration over the held operations of a block for a
157 /// specific operation type.
158 template <typename OpT, typename IteratorT>
160  : public llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>,
161  OpT (*)(Operation &)> {
162  static OpT unwrap(Operation &op) { return cast<OpT>(op); }
163 
164 public:
165 
166  /// Initializes the iterator to the specified filter iterator.
168  : llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>,
169  OpT (*)(Operation &)>(it, &unwrap) {}
170 
171  /// Allow implicit conversion to the underlying block iterator.
172  operator const IteratorT &() const { return this->wrapped(); }
173 };
174 } // namespace detail
175 } // namespace mlir
176 
177 namespace llvm {
178 
179 /// Provide support for hashing successor ranges.
180 template <>
181 struct DenseMapInfo<mlir::SuccessorRange> {
184  return mlir::SuccessorRange(pointer, 0);
185  }
188  return mlir::SuccessorRange(pointer, 0);
189  }
190  static unsigned getHashValue(mlir::SuccessorRange value) {
191  return llvm::hash_combine_range(value.begin(), value.end());
192  }
194  if (rhs.getBase() == getEmptyKey().getBase())
195  return lhs.getBase() == getEmptyKey().getBase();
196  if (rhs.getBase() == getTombstoneKey().getBase())
197  return lhs.getBase() == getTombstoneKey().getBase();
198  return lhs == rhs;
199  }
200 };
201 
202 //===----------------------------------------------------------------------===//
203 // ilist_traits for Operation
204 //===----------------------------------------------------------------------===//
205 
206 namespace ilist_detail {
207 // Explicitly define the node access for the operation list so that we can
208 // break the dependence on the Operation class in this header. This allows for
209 // operations to have trailing Regions without a circular include
210 // dependence.
211 template <>
212 struct SpecificNodeAccess<
213  typename compute_node_options<::mlir::Operation>::type> : NodeAccess {
214 protected:
215  using OptionsT = typename compute_node_options<mlir::Operation>::type;
216  using pointer = typename OptionsT::pointer;
217  using const_pointer = typename OptionsT::const_pointer;
218  using node_type = ilist_node_impl<OptionsT>;
219 
220  static node_type *getNodePtr(pointer N);
221  static const node_type *getNodePtr(const_pointer N);
222 
223  static pointer getValuePtr(node_type *N);
224  static const_pointer getValuePtr(const node_type *N);
225 };
226 } // namespace ilist_detail
227 
228 template <> struct ilist_traits<::mlir::Operation> {
230  using op_iterator = simple_ilist<Operation>::iterator;
231 
232  static void deleteNode(Operation *op);
233  void addNodeToList(Operation *op);
234  void removeNodeFromList(Operation *op);
235  void transferNodesFromList(ilist_traits<Operation> &otherList,
236  op_iterator first, op_iterator last);
237 
238 private:
239  mlir::Block *getContainingBlock();
240 };
241 
242 //===----------------------------------------------------------------------===//
243 // ilist_traits for Block
244 //===----------------------------------------------------------------------===//
245 
246 template <>
247 struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
249  using block_iterator = simple_ilist<::mlir::Block>::iterator;
250 
251  void addNodeToList(Block *block);
252  void removeNodeFromList(Block *block);
253  void transferNodesFromList(ilist_traits<Block> &otherList,
254  block_iterator first, block_iterator last);
255 
256 private:
257  mlir::Region *getParentRegion();
258 };
259 
260 } // namespace llvm
261 
262 #endif // MLIR_IR_BLOCKSUPPORT_H
Include the generated interface declarations.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
Explicitly register a set of "builtin" types.
Definition: CallGraph.h:221
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
unsigned getOperandNumber()
Return which operand this is in the BlockOperand list of the Operation.
Definition: Value.cpp:203
Block represents an ordered list of Operations.
Definition: Block.h:29
PredecessorIterator(BlockOperand *operand)
Definition: BlockSupport.h:60
An iterator class that allows for iterating over the uses of an IR operand type.
Definition: UseDefLists.h:23
A block operand represents an operand that holds a reference to a Block, e.g.
Definition: BlockSupport.h:30
BlockRange(std::initializer_list< Block *> blocks)
Definition: BlockSupport.h:117
simple_ilist< Operation >::iterator op_iterator
Definition: BlockSupport.h:230
static unsigned getHashValue(mlir::SuccessorRange value)
Definition: BlockSupport.h:190
op_filter_iterator(IteratorT it, IteratorT end)
Definition: BlockSupport.h:148
This class implements the successor iterators for Block.
Definition: BlockSupport.h:72
This class provides iteration over the held operations of a block for a specific operation type...
Definition: BlockSupport.h:159
simple_ilist<::mlir::Block >::iterator block_iterator
Definition: BlockSupport.h:249
static bool isEqual(mlir::SuccessorRange lhs, mlir::SuccessorRange rhs)
Definition: BlockSupport.h:193
static IRObjectWithUseList< BlockOperand > * getUseList(Block *value)
Provide the use list that is attached to the given block.
Definition: Value.cpp:198
static mlir::SuccessorRange getEmptyKey()
Definition: BlockSupport.h:182
Implement a predecessor iterator for blocks.
Definition: BlockSupport.h:49
op_iterator(op_filter_iterator< OpT, IteratorT > it)
Initializes the iterator to the specified filter iterator.
Definition: BlockSupport.h:167
This class provides an abstraction over the different types of ranges over Blocks.
Definition: BlockSupport.h:104
A utility iterator that filters out operations that are not &#39;OpT&#39;.
Definition: BlockSupport.h:143
A reference to a value, suitable for use as an operand of an operation.
Definition: UseDefLists.h:110
mlir::Diagnostic & unwrap(MlirDiagnostic diagnostic)
Definition: Diagnostics.h:19
PredecessorIterator(ValueUseIterator< BlockOperand > it)
Initializes the operand type iterator to the specified operand iterator.
Definition: BlockSupport.h:57
BlockRange(Arg &&arg)
Definition: BlockSupport.h:115
static mlir::SuccessorRange getTombstoneKey()
Definition: BlockSupport.h:186