Coverage Report

Created: 2020-06-26 05:44

/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