/home/arjun/llvm-project/mlir/include/mlir/IR/BlockSupport.h
Line | Count | Source (jump to first uncovered line) |
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_BLOCK_SUPPORT_H |
14 | | #define MLIR_IR_BLOCK_SUPPORT_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 | | // Predecessors |
26 | | //===----------------------------------------------------------------------===// |
27 | | |
28 | | /// Implement a predecessor iterator for blocks. This works by walking the use |
29 | | /// lists of the blocks. The entries on this list are the BlockOperands that |
30 | | /// are embedded into terminator operations. From the operand, we can get the |
31 | | /// terminator that contains it, and its parent block is the predecessor. |
32 | | class PredecessorIterator final |
33 | | : public llvm::mapped_iterator<ValueUseIterator<BlockOperand>, |
34 | | Block *(*)(BlockOperand &)> { |
35 | | static Block *unwrap(BlockOperand &value); |
36 | | |
37 | | public: |
38 | | using reference = Block *; |
39 | | |
40 | | /// Initializes the operand type iterator to the specified operand iterator. |
41 | | PredecessorIterator(ValueUseIterator<BlockOperand> it) |
42 | | : llvm::mapped_iterator<ValueUseIterator<BlockOperand>, |
43 | 0 | Block *(*)(BlockOperand &)>(it, &unwrap) {} |
44 | | explicit PredecessorIterator(BlockOperand *operand) |
45 | 0 | : PredecessorIterator(ValueUseIterator<BlockOperand>(operand)) {} |
46 | | |
47 | | /// Get the successor number in the predecessor terminator. |
48 | | unsigned getSuccessorIndex() const; |
49 | | }; |
50 | | |
51 | | //===----------------------------------------------------------------------===// |
52 | | // Successors |
53 | | //===----------------------------------------------------------------------===// |
54 | | |
55 | | /// This class implements the successor iterators for Block. |
56 | | class SuccessorRange final |
57 | | : public llvm::detail::indexed_accessor_range_base< |
58 | | SuccessorRange, BlockOperand *, Block *, Block *, Block *> { |
59 | | public: |
60 | | using RangeBaseT::RangeBaseT; |
61 | | SuccessorRange(Block *block); |
62 | | SuccessorRange(Operation *term); |
63 | | |
64 | | private: |
65 | | /// See `llvm::detail::indexed_accessor_range_base` for details. |
66 | 0 | static BlockOperand *offset_base(BlockOperand *object, ptrdiff_t index) { |
67 | 0 | return object + index; |
68 | 0 | } |
69 | | /// See `llvm::detail::indexed_accessor_range_base` for details. |
70 | 0 | static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) { |
71 | 0 | return object[index].get(); |
72 | 0 | } |
73 | | |
74 | | /// Allow access to `offset_base` and `dereference_iterator`. |
75 | | friend RangeBaseT; |
76 | | }; |
77 | | |
78 | | //===----------------------------------------------------------------------===// |
79 | | // Operation Iterators |
80 | | //===----------------------------------------------------------------------===// |
81 | | |
82 | | namespace detail { |
83 | | /// A utility iterator that filters out operations that are not 'OpT'. |
84 | | template <typename OpT, typename IteratorT> |
85 | | class op_filter_iterator |
86 | | : public llvm::filter_iterator<IteratorT, bool (*)(Operation &)> { |
87 | | static bool filter(Operation &op) { return llvm::isa<OpT>(op); } |
88 | | |
89 | | public: |
90 | | op_filter_iterator(IteratorT it, IteratorT end) |
91 | | : llvm::filter_iterator<IteratorT, bool (*)(Operation &)>(it, end, |
92 | | &filter) {} |
93 | | |
94 | | /// Allow implicit conversion to the underlying iterator. |
95 | | operator IteratorT() const { return this->wrapped(); } |
96 | | }; |
97 | | |
98 | | /// This class provides iteration over the held operations of a block for a |
99 | | /// specific operation type. |
100 | | template <typename OpT, typename IteratorT> |
101 | | class op_iterator |
102 | | : public llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>, |
103 | | OpT (*)(Operation &)> { |
104 | | static OpT unwrap(Operation &op) { return cast<OpT>(op); } |
105 | | |
106 | | public: |
107 | | using reference = OpT; |
108 | | |
109 | | /// Initializes the iterator to the specified filter iterator. |
110 | | op_iterator(op_filter_iterator<OpT, IteratorT> it) |
111 | | : llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>, |
112 | | OpT (*)(Operation &)>(it, &unwrap) {} |
113 | | |
114 | | /// Allow implicit conversion to the underlying block iterator. |
115 | | operator IteratorT() const { return this->wrapped(); } |
116 | | }; |
117 | | } // end namespace detail |
118 | | } // end namespace mlir |
119 | | |
120 | | namespace llvm { |
121 | | |
122 | | /// Provide support for hashing successor ranges. |
123 | | template <> |
124 | | struct DenseMapInfo<mlir::SuccessorRange> { |
125 | 0 | static mlir::SuccessorRange getEmptyKey() { |
126 | 0 | auto *pointer = llvm::DenseMapInfo<mlir::BlockOperand *>::getEmptyKey(); |
127 | 0 | return mlir::SuccessorRange(pointer, 0); |
128 | 0 | } |
129 | 0 | static mlir::SuccessorRange getTombstoneKey() { |
130 | 0 | auto *pointer = llvm::DenseMapInfo<mlir::BlockOperand *>::getTombstoneKey(); |
131 | 0 | return mlir::SuccessorRange(pointer, 0); |
132 | 0 | } |
133 | 0 | static unsigned getHashValue(mlir::SuccessorRange value) { |
134 | 0 | return llvm::hash_combine_range(value.begin(), value.end()); |
135 | 0 | } |
136 | 0 | static bool isEqual(mlir::SuccessorRange lhs, mlir::SuccessorRange rhs) { |
137 | 0 | if (rhs.getBase() == getEmptyKey().getBase()) |
138 | 0 | return lhs.getBase() == getEmptyKey().getBase(); |
139 | 0 | if (rhs.getBase() == getTombstoneKey().getBase()) |
140 | 0 | return lhs.getBase() == getTombstoneKey().getBase(); |
141 | 0 | return lhs == rhs; |
142 | 0 | } |
143 | | }; |
144 | | |
145 | | //===----------------------------------------------------------------------===// |
146 | | // ilist_traits for Operation |
147 | | //===----------------------------------------------------------------------===// |
148 | | |
149 | | namespace ilist_detail { |
150 | | // Explicitly define the node access for the operation list so that we can |
151 | | // break the dependence on the Operation class in this header. This allows for |
152 | | // operations to have trailing Regions without a circular include |
153 | | // dependence. |
154 | | template <> |
155 | | struct SpecificNodeAccess< |
156 | | typename compute_node_options<::mlir::Operation>::type> : NodeAccess { |
157 | | protected: |
158 | | using OptionsT = typename compute_node_options<mlir::Operation>::type; |
159 | | using pointer = typename OptionsT::pointer; |
160 | | using const_pointer = typename OptionsT::const_pointer; |
161 | | using node_type = ilist_node_impl<OptionsT>; |
162 | | |
163 | | static node_type *getNodePtr(pointer N); |
164 | | static const node_type *getNodePtr(const_pointer N); |
165 | | |
166 | | static pointer getValuePtr(node_type *N); |
167 | | static const_pointer getValuePtr(const node_type *N); |
168 | | }; |
169 | | } // end namespace ilist_detail |
170 | | |
171 | | template <> struct ilist_traits<::mlir::Operation> { |
172 | | using Operation = ::mlir::Operation; |
173 | | using op_iterator = simple_ilist<Operation>::iterator; |
174 | | |
175 | | static void deleteNode(Operation *op); |
176 | | void addNodeToList(Operation *op); |
177 | | void removeNodeFromList(Operation *op); |
178 | | void transferNodesFromList(ilist_traits<Operation> &otherList, |
179 | | op_iterator first, op_iterator last); |
180 | | |
181 | | private: |
182 | | mlir::Block *getContainingBlock(); |
183 | | }; |
184 | | |
185 | | //===----------------------------------------------------------------------===// |
186 | | // ilist_traits for Block |
187 | | //===----------------------------------------------------------------------===// |
188 | | |
189 | | template <> |
190 | | struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> { |
191 | | using Block = ::mlir::Block; |
192 | | using block_iterator = simple_ilist<::mlir::Block>::iterator; |
193 | | |
194 | | void addNodeToList(Block *block); |
195 | | void removeNodeFromList(Block *block); |
196 | | void transferNodesFromList(ilist_traits<Block> &otherList, |
197 | | block_iterator first, block_iterator last); |
198 | | |
199 | | private: |
200 | | mlir::Region *getParentRegion(); |
201 | | }; |
202 | | |
203 | | } // end namespace llvm |
204 | | |
205 | | #endif // MLIR_IR_BLOCK_SUPPORT_H |