Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/Value.h
Line
Count
Source (jump to first uncovered line)
1
//===- Value.h - Base of the SSA Value hierarchy ----------------*- 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 Value type and manipulation utilities.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef MLIR_IR_VALUE_H
14
#define MLIR_IR_VALUE_H
15
16
#include "mlir/IR/Types.h"
17
#include "mlir/IR/UseDefLists.h"
18
#include "mlir/Support/LLVM.h"
19
#include "llvm/Support/PointerLikeTypeTraits.h"
20
21
namespace mlir {
22
class AsmState;
23
class BlockArgument;
24
class Operation;
25
class OpResult;
26
class Region;
27
class Value;
28
29
namespace detail {
30
/// The internal implementation of a BlockArgument.
31
class BlockArgumentImpl;
32
} // end namespace detail
33
34
/// This class represents an instance of an SSA value in the MLIR system,
35
/// representing a computable value that has a type and a set of users. An SSA
36
/// value is either a BlockArgument or the result of an operation. Note: This
37
/// class has value-type semantics and is just a simple wrapper around a
38
/// ValueImpl that is either owner by a block(in the case of a BlockArgument) or
39
/// an Operation(in the case of an OpResult).
40
class Value {
41
public:
42
  /// The enumeration represents the various different kinds of values the
43
  /// internal representation may take. We steal 2 bits to support a total of 4
44
  /// possible values.
45
  enum class Kind {
46
    /// The first N kinds are all inline operation results. An inline operation
47
    /// result means that the kind represents the result number, and the owner
48
    /// pointer is the owning `Operation*`. Note: These are packed first to make
49
    /// result number lookups more efficient.
50
    OpResult0 = 0,
51
    OpResult1 = 1,
52
53
    /// The next kind represents a 'trailing' operation result. This is for
54
    /// results with numbers larger than we can represent inline. The owner here
55
    /// is an `TrailingOpResult*` that points to a trailing storage on the
56
    /// parent operation.
57
    TrailingOpResult = 2,
58
59
    /// The last kind represents a block argument. The owner here is a
60
    /// `BlockArgumentImpl*`.
61
    BlockArgument = 3
62
  };
63
64
  /// This value represents the 'owner' of the value and its kind. See the
65
  /// 'Kind' enumeration above for a more detailed description of each kind of
66
  /// owner.
67
  struct ImplTypeTraits : public llvm::PointerLikeTypeTraits<void *> {
68
    // We know that all pointers within the ImplType are aligned by 8-bytes,
69
    // meaning that we can steal up to 3 bits for the different values.
70
    static constexpr int NumLowBitsAvailable = 3;
71
  };
72
  using ImplType = llvm::PointerIntPair<void *, 2, Kind, ImplTypeTraits>;
73
74
public:
75
0
  constexpr Value(std::nullptr_t) : ownerAndKind() {}
76
0
  Value(ImplType ownerAndKind = {}) : ownerAndKind(ownerAndKind) {}
77
  Value(const Value &) = default;
78
  Value &operator=(const Value &) = default;
79
80
0
  template <typename U> bool isa() const {
81
0
    assert(*this && "isa<> used on a null type.");
82
0
    return U::classof(*this);
83
0
  }
Unexecuted instantiation: _ZNK4mlir5Value3isaINS_13BlockArgumentEEEbv
Unexecuted instantiation: _ZNK4mlir5Value3isaINS_8OpResultEEEbv
84
0
  template <typename U> U dyn_cast() const {
85
0
    return isa<U>() ? U(ownerAndKind) : U(nullptr);
86
0
  }
Unexecuted instantiation: _ZNK4mlir5Value8dyn_castINS_13BlockArgumentEEET_v
Unexecuted instantiation: _ZNK4mlir5Value8dyn_castINS_8OpResultEEET_v
87
  template <typename U> U dyn_cast_or_null() const {
88
    return (*this && isa<U>()) ? U(ownerAndKind) : U(nullptr);
89
  }
90
0
  template <typename U> U cast() const {
91
0
    assert(isa<U>());
92
0
    return U(ownerAndKind);
93
0
  }
Unexecuted instantiation: _ZNK4mlir5Value4castINS_13BlockArgumentEEET_v
Unexecuted instantiation: _ZNK4mlir5Value4castINS_8OpResultEEET_v
94
95
0
  explicit operator bool() const { return ownerAndKind.getPointer(); }
96
0
  bool operator==(const Value &other) const {
97
0
    return ownerAndKind == other.ownerAndKind;
98
0
  }
99
0
  bool operator!=(const Value &other) const { return !(*this == other); }
100
101
  /// Return the type of this value.
102
  Type getType() const;
103
104
  /// Utility to get the associated MLIRContext that this value is defined in.
105
0
  MLIRContext *getContext() const { return getType().getContext(); }
106
107
  /// Mutate the type of this Value to be of the specified type.
108
  ///
109
  /// Note that this is an extremely dangerous operation which can create
110
  /// completely invalid IR very easily.  It is strongly recommended that you
111
  /// recreate IR objects with the right types instead of mutating them in
112
  /// place.
113
  void setType(Type newType);
114
115
  /// If this value is the result of an operation, return the operation that
116
  /// defines it.
117
  Operation *getDefiningOp() const;
118
119
  /// If this value is the result of an operation of type OpTy, return the
120
  /// operation that defines it.
121
  template <typename OpTy>
122
0
  OpTy getDefiningOp() const {
123
0
    return llvm::dyn_cast_or_null<OpTy>(getDefiningOp());
124
0
  }
Unexecuted instantiation: _ZNK4mlir5Value13getDefiningOpINS_15ConstantIndexOpEEET_v
Unexecuted instantiation: _ZNK4mlir5Value13getDefiningOpINS_12MemRefCastOpEEET_v
Unexecuted instantiation: _ZNK4mlir5Value13getDefiningOpINS_13AffineApplyOpEEET_v
Unexecuted instantiation: _ZNK4mlir5Value13getDefiningOpINS_11IndexCastOpEEET_v
Unexecuted instantiation: _ZNK4mlir5Value13getDefiningOpINS_7AllocOpEEET_v
125
126
  /// If this value is the result of an operation, use it as a location,
127
  /// otherwise return an unknown location.
128
  Location getLoc() const;
129
130
  /// Return the Region in which this Value is defined.
131
  Region *getParentRegion();
132
133
  /// Return the Block in which this Value is defined.
134
  Block *getParentBlock();
135
136
  //===--------------------------------------------------------------------===//
137
  // UseLists
138
  //===--------------------------------------------------------------------===//
139
140
  /// Provide the use list that is attached to this value.
141
  IRObjectWithUseList<OpOperand> *getUseList() const;
142
143
  /// Drop all uses of this object from their respective owners.
144
  void dropAllUses() const;
145
146
  /// Replace all uses of 'this' value with the new value, updating anything in
147
  /// the IR that uses 'this' to use the other value instead.  When this returns
148
  /// there are zero uses of 'this'.
149
  void replaceAllUsesWith(Value newValue) const;
150
151
  /// Replace all uses of 'this' value with 'newValue', updating anything in the
152
  /// IR that uses 'this' to use the other value instead except if the user is
153
  /// listed in 'exceptions' .
154
  void
155
  replaceAllUsesExcept(Value newValue,
156
                       const SmallPtrSetImpl<Operation *> &exceptions) const;
157
158
  /// Replace all uses of 'this' value with 'newValue' if the given callback
159
  /// returns true.
160
  void replaceUsesWithIf(Value newValue,
161
                         function_ref<bool(OpOperand &)> shouldReplace);
162
163
  /// Returns true if the value is used outside of the given block.
164
  bool isUsedOutsideOfBlock(Block *block);
165
166
  //===--------------------------------------------------------------------===//
167
  // Uses
168
169
  /// This class implements an iterator over the uses of a value.
170
  using use_iterator = ValueUseIterator<OpOperand>;
171
  using use_range = iterator_range<use_iterator>;
172
173
  use_iterator use_begin() const;
174
0
  use_iterator use_end() const { return use_iterator(); }
175
176
  /// Returns a range of all uses, which is useful for iterating over all uses.
177
0
  use_range getUses() const { return {use_begin(), use_end()}; }
178
179
  /// Returns true if this value has exactly one use.
180
  bool hasOneUse() const;
181
182
  /// Returns true if this value has no uses.
183
  bool use_empty() const;
184
185
  //===--------------------------------------------------------------------===//
186
  // Users
187
188
  using user_iterator = ValueUserIterator<use_iterator, OpOperand>;
189
  using user_range = iterator_range<user_iterator>;
190
191
0
  user_iterator user_begin() const { return use_begin(); }
192
0
  user_iterator user_end() const { return use_end(); }
193
0
  user_range getUsers() const { return {user_begin(), user_end()}; }
194
195
  //===--------------------------------------------------------------------===//
196
  // Utilities
197
198
  /// Returns the kind of this value.
199
0
  Kind getKind() const { return ownerAndKind.getInt(); }
200
201
  void print(raw_ostream &os);
202
  void print(raw_ostream &os, AsmState &state);
203
  void dump();
204
205
  /// Print this value as if it were an operand.
206
  void printAsOperand(raw_ostream &os, AsmState &state);
207
208
  /// Methods for supporting PointerLikeTypeTraits.
209
0
  void *getAsOpaquePointer() const { return ownerAndKind.getOpaqueValue(); }
210
0
  static Value getFromOpaquePointer(const void *pointer) {
211
0
    Value value;
212
0
    value.ownerAndKind.setFromOpaqueValue(const_cast<void *>(pointer));
213
0
    return value;
214
0
  }
215
216
  friend ::llvm::hash_code hash_value(Value arg);
217
218
protected:
219
  /// Returns true if the given operation result can be packed inline.
220
0
  static bool canPackResultInline(unsigned resultNo) {
221
0
    return resultNo < static_cast<unsigned>(Kind::TrailingOpResult);
222
0
  }
223
224
  /// Construct a value.
225
  Value(detail::BlockArgumentImpl *impl);
226
  Value(Operation *op, unsigned resultNo);
227
228
  /// This value represents the 'owner' of the value and its kind. See the
229
  /// 'Kind' enumeration above for a more detailed description of each kind of
230
  /// owner.
231
  ImplType ownerAndKind;
232
};
233
234
0
inline raw_ostream &operator<<(raw_ostream &os, Value value) {
235
0
  value.print(os);
236
0
  return os;
237
0
}
238
239
//===----------------------------------------------------------------------===//
240
// BlockArgument
241
//===----------------------------------------------------------------------===//
242
243
namespace detail {
244
/// The internal implementation of a BlockArgument.
245
class BlockArgumentImpl : public IRObjectWithUseList<OpOperand> {
246
0
  BlockArgumentImpl(Type type, Block *owner) : type(type), owner(owner) {}
247
248
  /// The type of this argument.
249
  Type type;
250
251
  /// The owner of this argument.
252
  Block *owner;
253
254
  /// Allow access to owner and constructor.
255
  friend BlockArgument;
256
};
257
} // end namespace detail
258
259
/// Block arguments are values.
260
class BlockArgument : public Value {
261
public:
262
  using Value::Value;
263
264
0
  static bool classof(Value value) {
265
0
    return value.getKind() == Kind::BlockArgument;
266
0
  }
267
268
  /// Returns the block that owns this argument.
269
0
  Block *getOwner() const { return getImpl()->owner; }
270
271
  /// Return the type of this value.
272
0
  Type getType() const { return getImpl()->type; }
273
274
  /// Set the type of this value.
275
0
  void setType(Type newType) { getImpl()->type = newType; }
276
277
  /// Returns the number of this argument.
278
  unsigned getArgNumber() const;
279
280
private:
281
  /// Allocate a new argument with the given type and owner.
282
0
  static BlockArgument create(Type type, Block *owner) {
283
0
    return new detail::BlockArgumentImpl(type, owner);
284
0
  }
285
286
  /// Destroy and deallocate this argument.
287
0
  void destroy() { delete getImpl(); }
288
289
  /// Get a raw pointer to the internal implementation.
290
0
  detail::BlockArgumentImpl *getImpl() const {
291
0
    return reinterpret_cast<detail::BlockArgumentImpl *>(
292
0
        ownerAndKind.getPointer());
293
0
  }
294
295
  /// Allow access to `create` and `destroy`.
296
  friend Block;
297
298
  /// Allow access to 'getImpl'.
299
  friend Value;
300
};
301
302
//===----------------------------------------------------------------------===//
303
// OpResult
304
//===----------------------------------------------------------------------===//
305
306
/// This is a value defined by a result of an operation.
307
class OpResult : public Value {
308
public:
309
  using Value::Value;
310
311
0
  static bool classof(Value value) {
312
0
    return value.getKind() != Kind::BlockArgument;
313
0
  }
314
315
  /// Returns the operation that owns this result.
316
  Operation *getOwner() const;
317
318
  /// Returns the number of this result.
319
  unsigned getResultNumber() const;
320
321
  /// Returns the maximum number of results that can be stored inline.
322
0
  static unsigned getMaxInlineResults() {
323
0
    return static_cast<unsigned>(Kind::TrailingOpResult);
324
0
  }
325
326
private:
327
  /// Given a number of operation results, returns the number that need to be
328
  /// stored inline.
329
  static unsigned getNumInline(unsigned numResults);
330
331
  /// Given a number of operation results, returns the number that need to be
332
  /// stored as trailing.
333
  static unsigned getNumTrailing(unsigned numResults);
334
335
  /// Allow access to constructor.
336
  friend Operation;
337
};
338
339
/// Make Value hashable.
340
0
inline ::llvm::hash_code hash_value(Value arg) {
341
0
  return ::llvm::hash_value(arg.ownerAndKind.getOpaqueValue());
342
0
}
343
344
} // namespace mlir
345
346
namespace llvm {
347
348
template <> struct DenseMapInfo<mlir::Value> {
349
0
  static mlir::Value getEmptyKey() {
350
0
    auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
351
0
    return mlir::Value::getFromOpaquePointer(pointer);
352
0
  }
353
0
  static mlir::Value getTombstoneKey() {
354
0
    auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
355
0
    return mlir::Value::getFromOpaquePointer(pointer);
356
0
  }
357
0
  static unsigned getHashValue(mlir::Value val) {
358
0
    return mlir::hash_value(val);
359
0
  }
360
0
  static bool isEqual(mlir::Value lhs, mlir::Value rhs) { return lhs == rhs; }
361
};
362
363
/// Allow stealing the low bits of a value.
364
template <> struct PointerLikeTypeTraits<mlir::Value> {
365
public:
366
0
  static inline void *getAsVoidPointer(mlir::Value I) {
367
0
    return const_cast<void *>(I.getAsOpaquePointer());
368
0
  }
369
0
  static inline mlir::Value getFromVoidPointer(void *P) {
370
0
    return mlir::Value::getFromOpaquePointer(P);
371
0
  }
372
  enum {
373
    NumLowBitsAvailable =
374
        PointerLikeTypeTraits<mlir::Value::ImplType>::NumLowBitsAvailable
375
  };
376
};
377
378
template <> struct DenseMapInfo<mlir::BlockArgument> {
379
0
  static mlir::BlockArgument getEmptyKey() {
380
0
    auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
381
0
    return mlir::BlockArgument(
382
0
        mlir::Value::ImplType::getFromOpaqueValue(pointer));
383
0
  }
384
0
  static mlir::BlockArgument getTombstoneKey() {
385
0
    auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
386
0
    return mlir::BlockArgument(
387
0
        mlir::Value::ImplType::getFromOpaqueValue(pointer));
388
0
  }
389
0
  static unsigned getHashValue(mlir::BlockArgument val) {
390
0
    return mlir::hash_value(val);
391
0
  }
392
0
  static bool isEqual(mlir::BlockArgument LHS, mlir::BlockArgument RHS) {
393
0
    return LHS == RHS;
394
0
  }
395
};
396
397
/// Allow stealing the low bits of a value.
398
template <> struct PointerLikeTypeTraits<mlir::BlockArgument> {
399
public:
400
0
  static inline void *getAsVoidPointer(mlir::Value I) {
401
0
    return const_cast<void *>(I.getAsOpaquePointer());
402
0
  }
403
0
  static inline mlir::BlockArgument getFromVoidPointer(void *P) {
404
0
    return mlir::Value::getFromOpaquePointer(P).cast<mlir::BlockArgument>();
405
0
  }
406
  enum {
407
    NumLowBitsAvailable =
408
        PointerLikeTypeTraits<mlir::Value>::NumLowBitsAvailable
409
  };
410
};
411
} // end namespace llvm
412
413
#endif