Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/UseDefLists.h
Line
Count
Source (jump to first uncovered line)
1
//===- UseDefLists.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 generic use/def list machinery and manipulation utilities.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef MLIR_IR_USEDEFLISTS_H
14
#define MLIR_IR_USEDEFLISTS_H
15
16
#include "mlir/IR/Location.h"
17
#include "llvm/ADT/PointerIntPair.h"
18
#include "llvm/ADT/iterator_range.h"
19
20
namespace mlir {
21
22
class Block;
23
class Operation;
24
class Value;
25
template <typename OperandType> class ValueUseIterator;
26
template <typename OperandType> class FilteredValueUseIterator;
27
template <typename UseIteratorT, typename OperandType> class ValueUserIterator;
28
29
//===----------------------------------------------------------------------===//
30
// IRObjectWithUseList
31
//===----------------------------------------------------------------------===//
32
33
/// This class represents a single IR object that contains a use list.
34
template <typename OperandType> class IRObjectWithUseList {
35
public:
36
0
  ~IRObjectWithUseList() {
37
0
    assert(use_empty() && "Cannot destroy a value that still has uses!");
38
0
  }
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_9OpOperandEED2Ev
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_12BlockOperandEED2Ev
39
40
  /// Drop all uses of this object from their respective owners.
41
0
  void dropAllUses() {
42
0
    while (!use_empty())
43
0
      use_begin()->drop();
44
0
  }
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_12BlockOperandEE11dropAllUsesEv
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_9OpOperandEE11dropAllUsesEv
45
46
  /// Replace all uses of 'this' value with the new value, updating anything in
47
  /// the IR that uses 'this' to use the other value instead.  When this returns
48
  /// there are zero uses of 'this'.
49
  void replaceAllUsesWith(typename OperandType::ValueType newValue) {
50
    assert((!newValue || this != OperandType::getUseList(newValue)) &&
51
           "cannot RAUW a value with itself");
52
    while (!use_empty())
53
      use_begin()->set(newValue);
54
  }
55
56
  //===--------------------------------------------------------------------===//
57
  // Uses
58
  //===--------------------------------------------------------------------===//
59
60
  using use_iterator = ValueUseIterator<OperandType>;
61
  using use_range = iterator_range<use_iterator>;
62
63
0
  use_iterator use_begin() const { return use_iterator(firstUse); }
Unexecuted instantiation: _ZNK4mlir19IRObjectWithUseListINS_12BlockOperandEE9use_beginEv
Unexecuted instantiation: _ZNK4mlir19IRObjectWithUseListINS_9OpOperandEE9use_beginEv
64
  use_iterator use_end() const { return use_iterator(nullptr); }
65
66
  /// Returns a range of all uses, which is useful for iterating over all uses.
67
  use_range getUses() const { return {use_begin(), use_end()}; }
68
69
  /// Returns true if this value has exactly one use.
70
0
  bool hasOneUse() const {
71
0
    return firstUse && firstUse->getNextOperandUsingThisValue() == nullptr;
72
0
  }
73
74
  /// Returns true if this value has no uses.
75
0
  bool use_empty() const { return firstUse == nullptr; }
Unexecuted instantiation: _ZNK4mlir19IRObjectWithUseListINS_9OpOperandEE9use_emptyEv
Unexecuted instantiation: _ZNK4mlir19IRObjectWithUseListINS_12BlockOperandEE9use_emptyEv
76
77
  //===--------------------------------------------------------------------===//
78
  // Users
79
  //===--------------------------------------------------------------------===//
80
81
  using user_iterator = ValueUserIterator<use_iterator, OperandType>;
82
  using user_range = iterator_range<user_iterator>;
83
84
  user_iterator user_begin() const { return user_iterator(use_begin()); }
85
  user_iterator user_end() const { return user_iterator(use_end()); }
86
87
  /// Returns a range of all users.
88
  user_range getUsers() const { return {user_begin(), user_end()}; }
89
90
protected:
91
0
  IRObjectWithUseList() {}
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_12BlockOperandEEC2Ev
Unexecuted instantiation: _ZN4mlir19IRObjectWithUseListINS_9OpOperandEEC2Ev
92
93
  /// Return the first operand that is using this value, for use by custom
94
  /// use/def iterators.
95
0
  OperandType *getFirstUse() const { return firstUse; }
96
97
private:
98
  template <typename DerivedT, typename IRValueTy> friend class IROperand;
99
  OperandType *firstUse = nullptr;
100
};
101
102
//===----------------------------------------------------------------------===//
103
// IROperand
104
//===----------------------------------------------------------------------===//
105
106
/// A reference to a value, suitable for use as an operand of an operation.
107
/// IRValueTy is the root type to use for values this tracks. Derived operand
108
/// types are expected to provide the following:
109
///  * static IRObjectWithUseList *getUseList(IRValueTy value);
110
///    - Provide the use list that is attached to the given value.
111
template <typename DerivedT, typename IRValueTy> class IROperand {
112
public:
113
  using ValueType = IRValueTy;
114
115
0
  IROperand(Operation *owner) : owner(owner) {}
116
0
  IROperand(Operation *owner, ValueType value) : value(value), owner(owner) {
117
0
    insertIntoCurrent();
118
0
  }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEEC2EPNS_9OperationES3_
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEEC2EPNS_9OperationES3_
119
120
  /// Return the current value being used by this operand.
121
0
  ValueType get() const { return value; }
Unexecuted instantiation: _ZNK4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE3getEv
Unexecuted instantiation: _ZNK4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE3getEv
122
123
  /// Set the current value being used by this operand.
124
0
  void set(ValueType newValue) {
125
0
    // It isn't worth optimizing for the case of switching operands on a single
126
0
    // value.
127
0
    removeFromCurrent();
128
0
    value = newValue;
129
0
    insertIntoCurrent();
130
0
  }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE3setES3_
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE3setES3_
131
132
  /// Returns true if this operand contains the given value.
133
  bool is(ValueType other) const { return value == other; }
134
135
  /// Return the owner of this operand.
136
0
  Operation *getOwner() { return owner; }
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE8getOwnerEv
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE8getOwnerEv
137
  Operation *getOwner() const { return owner; }
138
139
  /// \brief Remove this use of the operand.
140
0
  void drop() {
141
0
    removeFromCurrent();
142
0
    value = nullptr;
143
0
    nextUse = nullptr;
144
0
    back = nullptr;
145
0
  }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE4dropEv
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE4dropEv
146
147
0
  ~IROperand() { removeFromCurrent(); }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEED2Ev
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEED2Ev
148
149
  /// Return the next operand on the use-list of the value we are referring to.
150
  /// This should generally only be used by the internal implementation details
151
  /// of the SSA machinery.
152
0
  DerivedT *getNextOperandUsingThisValue() { return nextUse; }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE28getNextOperandUsingThisValueEv
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE28getNextOperandUsingThisValueEv
153
154
  /// We support a move constructor so IROperand's can be in vectors, but this
155
  /// shouldn't be used by general clients.
156
0
  IROperand(IROperand &&other) : owner(other.owner) {
157
0
    *this = std::move(other);
158
0
  }
159
0
  IROperand &operator=(IROperand &&other) {
160
0
    removeFromCurrent();
161
0
    other.removeFromCurrent();
162
0
    value = other.value;
163
0
    other.value = nullptr;
164
0
    other.back = nullptr;
165
0
    nextUse = nullptr;
166
0
    back = nullptr;
167
0
    if (value)
168
0
      insertIntoCurrent();
169
0
    return *this;
170
0
  }
171
172
private:
173
  /// The value used as this operand. This can be null when in a 'dropAllUses'
174
  /// state.
175
  ValueType value = {};
176
177
  /// The next operand in the use-chain.
178
  DerivedT *nextUse = nullptr;
179
180
  /// This points to the previous link in the use-chain.
181
  DerivedT **back = nullptr;
182
183
  /// The operation owner of this operand.
184
  Operation *const owner;
185
186
  /// Operands are not copyable or assignable.
187
  IROperand(const IROperand &use) = delete;
188
  IROperand &operator=(const IROperand &use) = delete;
189
190
0
  void removeFromCurrent() {
191
0
    if (!back)
192
0
      return;
193
0
    *back = nextUse;
194
0
    if (nextUse)
195
0
      nextUse->back = back;
196
0
  }
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE17removeFromCurrentEv
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE17removeFromCurrentEv
197
198
0
  void insertIntoCurrent() {
199
0
    auto *useList = DerivedT::getUseList(value);
200
0
    back = &useList->firstUse;
201
0
    nextUse = useList->firstUse;
202
0
    if (nextUse)
203
0
      nextUse->back = &nextUse;
204
0
    useList->firstUse = static_cast<DerivedT *>(this);
205
0
  }
Unexecuted instantiation: _ZN4mlir9IROperandINS_12BlockOperandEPNS_5BlockEE17insertIntoCurrentEv
Unexecuted instantiation: _ZN4mlir9IROperandINS_9OpOperandENS_6detail11OpaqueValueEE17insertIntoCurrentEv
206
};
207
208
//===----------------------------------------------------------------------===//
209
// BlockOperand
210
//===----------------------------------------------------------------------===//
211
212
/// Terminator operations can have Block operands to represent successors.
213
class BlockOperand : public IROperand<BlockOperand, Block *> {
214
public:
215
  using IROperand<BlockOperand, Block *>::IROperand;
216
217
  /// Provide the use list that is attached to the given block.
218
  static IRObjectWithUseList<BlockOperand> *getUseList(Block *value);
219
220
  /// Return which operand this is in the operand list of the User.
221
  unsigned getOperandNumber();
222
};
223
224
//===----------------------------------------------------------------------===//
225
// OpOperand
226
//===----------------------------------------------------------------------===//
227
228
namespace detail {
229
/// This class provides an opaque type erased wrapper around a `Value`.
230
class OpaqueValue {
231
public:
232
  /// Implicit conversion from 'Value'.
233
  OpaqueValue(Value value);
234
0
  OpaqueValue(std::nullptr_t = nullptr) : impl(nullptr) {}
235
  OpaqueValue(const OpaqueValue &) = default;
236
  OpaqueValue &operator=(const OpaqueValue &) = default;
237
0
  bool operator==(const OpaqueValue &other) const { return impl == other.impl; }
238
0
  operator bool() const { return impl; }
239
240
  /// Implicit conversion back to 'Value'.
241
  operator Value() const;
242
243
private:
244
  void *impl;
245
};
246
} // namespace detail
247
248
/// This class represents an operand of an operation. Instances of this class
249
/// contain a reference to a specific `Value`.
250
class OpOperand : public IROperand<OpOperand, detail::OpaqueValue> {
251
public:
252
  using IROperand<OpOperand, detail::OpaqueValue>::IROperand;
253
254
  /// Provide the use list that is attached to the given value.
255
  static IRObjectWithUseList<OpOperand> *getUseList(Value value);
256
257
  /// Return the current value being used by this operand.
258
  Value get() const;
259
260
  /// Set the operand to the given value.
261
  void set(Value value);
262
263
  /// Return which operand this is in the operand list of the User.
264
  unsigned getOperandNumber();
265
};
266
267
//===----------------------------------------------------------------------===//
268
// ValueUseIterator
269
//===----------------------------------------------------------------------===//
270
271
/// An iterator class that allows for iterating over the uses of an IR operand
272
/// type.
273
template <typename OperandType>
274
class ValueUseIterator
275
    : public llvm::iterator_facade_base<ValueUseIterator<OperandType>,
276
                                        std::forward_iterator_tag,
277
                                        OperandType> {
278
public:
279
0
  ValueUseIterator(OperandType *current = nullptr) : current(current) {}
Unexecuted instantiation: _ZN4mlir16ValueUseIteratorINS_12BlockOperandEEC2EPS1_
Unexecuted instantiation: _ZN4mlir16ValueUseIteratorINS_9OpOperandEEC2EPS1_
280
281
  /// Returns the user that owns this use.
282
  Operation *getUser() const { return current->getOwner(); }
283
284
  /// Returns the current operands.
285
0
  OperandType *getOperand() const { return current; }
286
0
  OperandType &operator*() const { return *current; }
Unexecuted instantiation: _ZNK4mlir16ValueUseIteratorINS_9OpOperandEEdeEv
Unexecuted instantiation: _ZNK4mlir16ValueUseIteratorINS_12BlockOperandEEdeEv
287
288
  using llvm::iterator_facade_base<ValueUseIterator<OperandType>,
289
                                   std::forward_iterator_tag,
290
                                   OperandType>::operator++;
291
0
  ValueUseIterator &operator++() {
292
0
    assert(current && "incrementing past end()!");
293
0
    current = (OperandType *)current->getNextOperandUsingThisValue();
294
0
    return *this;
295
0
  }
Unexecuted instantiation: _ZN4mlir16ValueUseIteratorINS_12BlockOperandEEppEv
Unexecuted instantiation: _ZN4mlir16ValueUseIteratorINS_9OpOperandEEppEv
296
297
0
  bool operator==(const ValueUseIterator &rhs) const {
298
0
    return current == rhs.current;
299
0
  }
Unexecuted instantiation: _ZNK4mlir16ValueUseIteratorINS_9OpOperandEEeqERKS2_
Unexecuted instantiation: _ZNK4mlir16ValueUseIteratorINS_12BlockOperandEEeqERKS2_
300
301
protected:
302
  OperandType *current;
303
};
304
305
//===----------------------------------------------------------------------===//
306
// ValueUserIterator
307
//===----------------------------------------------------------------------===//
308
309
/// An iterator over the users of an IRObject. This is a wrapper iterator around
310
/// a specific use iterator.
311
template <typename UseIteratorT, typename OperandType>
312
class ValueUserIterator final
313
    : public llvm::mapped_iterator<UseIteratorT,
314
                                   Operation *(*)(OperandType &)> {
315
0
  static Operation *unwrap(OperandType &value) { return value.getOwner(); }
Unexecuted instantiation: _ZN4mlir17ValueUserIteratorINS_16ValueUseIteratorINS_9OpOperandEEES2_E6unwrapERS2_
Unexecuted instantiation: _ZN4mlir17ValueUserIteratorINS_9Operation11UseIteratorENS_9OpOperandEE6unwrapERS3_
316
317
public:
318
  using pointer = Operation *;
319
  using reference = Operation *;
320
321
  /// Initializes the user iterator to the specified use iterator.
322
  ValueUserIterator(UseIteratorT it)
323
      : llvm::mapped_iterator<UseIteratorT, Operation *(*)(OperandType &)>(
324
0
            it, &unwrap) {}
325
  Operation *operator->() { return **this; }
326
};
327
328
} // namespace mlir
329
330
#endif