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 Block;
24 class BlockArgument;
25 class Operation;
26 class OpOperand;
27 class OpPrintingFlags;
28 class OpResult;
29 class Region;
30 class Value;
31
32 //===----------------------------------------------------------------------===//
33 // Value
34 //===----------------------------------------------------------------------===//
35
36 namespace detail {
37
38 /// The base class for all derived Value classes. It contains all of the
39 /// components that are shared across Value classes.
40 class alignas(8) ValueImpl : public IRObjectWithUseList<OpOperand> {
41 public:
42 /// The enumeration represents the various different kinds of values the
43 /// internal representation may take. We use all of the bits from Type that we
44 /// can to store indices inline.
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. This removes
48 /// the need to store an additional index value. The derived class here is
49 /// an `OpResultImpl`.
50 InlineOpResult = 0,
51
52 /// The next kind represents a 'out-of-line' operation result. This is for
53 /// results with numbers larger than we can represent inline. The derived
54 /// class here is an `OpResultImpl`.
55 OutOfLineOpResult = 6,
56
57 /// The last kind represents a block argument. The derived class here is an
58 /// `BlockArgumentImpl`.
59 BlockArgument = 7
60 };
61
62 /// Return the type of this value.
getType()63 Type getType() const { return typeAndKind.getPointer(); }
64
65 /// Set the type of this value.
setType(Type type)66 void setType(Type type) { return typeAndKind.setPointer(type); }
67
68 /// Return the kind of this value.
getKind()69 Kind getKind() const { return typeAndKind.getInt(); }
70
71 protected:
ValueImpl(Type type,Kind kind)72 ValueImpl(Type type, Kind kind) : typeAndKind(type, kind) {}
73
74 /// The type of this result and the kind.
75 llvm::PointerIntPair<Type, 3, Kind> typeAndKind;
76 };
77 } // namespace detail
78
79 /// This class represents an instance of an SSA value in the MLIR system,
80 /// representing a computable value that has a type and a set of users. An SSA
81 /// value is either a BlockArgument or the result of an operation. Note: This
82 /// class has value-type semantics and is just a simple wrapper around a
83 /// ValueImpl that is either owner by a block(in the case of a BlockArgument) or
84 /// an Operation(in the case of an OpResult).
85 class Value {
86 public:
impl(impl)87 constexpr Value(detail::ValueImpl *impl = nullptr) : impl(impl) {}
88
89 template <typename U>
isa()90 bool isa() const {
91 assert(*this && "isa<> used on a null type.");
92 return U::classof(*this);
93 }
94
95 template <typename First, typename Second, typename... Rest>
isa()96 bool isa() const {
97 return isa<First>() || isa<Second, Rest...>();
98 }
99 template <typename U>
dyn_cast()100 U dyn_cast() const {
101 return isa<U>() ? U(impl) : U(nullptr);
102 }
103 template <typename U>
dyn_cast_or_null()104 U dyn_cast_or_null() const {
105 return (*this && isa<U>()) ? U(impl) : U(nullptr);
106 }
107 template <typename U>
cast()108 U cast() const {
109 assert(isa<U>());
110 return U(impl);
111 }
112
113 explicit operator bool() const { return impl; }
114 bool operator==(const Value &other) const { return impl == other.impl; }
115 bool operator!=(const Value &other) const { return !(*this == other); }
116
117 /// Return the type of this value.
getType()118 Type getType() const { return impl->getType(); }
119
120 /// Utility to get the associated MLIRContext that this value is defined in.
getContext()121 MLIRContext *getContext() const { return getType().getContext(); }
122
123 /// Mutate the type of this Value to be of the specified type.
124 ///
125 /// Note that this is an extremely dangerous operation which can create
126 /// completely invalid IR very easily. It is strongly recommended that you
127 /// recreate IR objects with the right types instead of mutating them in
128 /// place.
setType(Type newType)129 void setType(Type newType) { impl->setType(newType); }
130
131 /// If this value is the result of an operation, return the operation that
132 /// defines it.
133 Operation *getDefiningOp() const;
134
135 /// If this value is the result of an operation of type OpTy, return the
136 /// operation that defines it.
137 template <typename OpTy>
getDefiningOp()138 OpTy getDefiningOp() const {
139 return llvm::dyn_cast_or_null<OpTy>(getDefiningOp());
140 }
141
142 /// Return the location of this value.
143 Location getLoc() const;
144 void setLoc(Location loc);
145
146 /// Return the Region in which this Value is defined.
147 Region *getParentRegion();
148
149 /// Return the Block in which this Value is defined.
150 Block *getParentBlock();
151
152 //===--------------------------------------------------------------------===//
153 // UseLists
154 //===--------------------------------------------------------------------===//
155
156 /// Drop all uses of this object from their respective owners.
dropAllUses()157 void dropAllUses() const { return impl->dropAllUses(); }
158
159 /// Replace all uses of 'this' value with the new value, updating anything in
160 /// the IR that uses 'this' to use the other value instead. When this returns
161 /// there are zero uses of 'this'.
replaceAllUsesWith(Value newValue)162 void replaceAllUsesWith(Value newValue) const {
163 impl->replaceAllUsesWith(newValue);
164 }
165
166 /// Replace all uses of 'this' value with 'newValue', updating anything in the
167 /// IR that uses 'this' to use the other value instead except if the user is
168 /// listed in 'exceptions' .
169 void
170 replaceAllUsesExcept(Value newValue,
171 const SmallPtrSetImpl<Operation *> &exceptions) const;
172
173 /// Replace all uses of 'this' value with 'newValue', updating anything in the
174 /// IR that uses 'this' to use the other value instead except if the user is
175 /// 'exceptedUser'.
176 void replaceAllUsesExcept(Value newValue, Operation *exceptedUser) const;
177
178 /// Replace all uses of 'this' value with 'newValue' if the given callback
179 /// returns true.
180 void replaceUsesWithIf(Value newValue,
181 function_ref<bool(OpOperand &)> shouldReplace);
182
183 /// Returns true if the value is used outside of the given block.
184 bool isUsedOutsideOfBlock(Block *block);
185
186 //===--------------------------------------------------------------------===//
187 // Uses
188
189 /// This class implements an iterator over the uses of a value.
190 using use_iterator = ValueUseIterator<OpOperand>;
191 using use_range = iterator_range<use_iterator>;
192
use_begin()193 use_iterator use_begin() const { return impl->use_begin(); }
use_end()194 use_iterator use_end() const { return use_iterator(); }
195
196 /// Returns a range of all uses, which is useful for iterating over all uses.
getUses()197 use_range getUses() const { return {use_begin(), use_end()}; }
198
199 /// Returns true if this value has exactly one use.
hasOneUse()200 bool hasOneUse() const { return impl->hasOneUse(); }
201
202 /// Returns true if this value has no uses.
use_empty()203 bool use_empty() const { return impl->use_empty(); }
204
205 //===--------------------------------------------------------------------===//
206 // Users
207
208 using user_iterator = ValueUserIterator<use_iterator, OpOperand>;
209 using user_range = iterator_range<user_iterator>;
210
user_begin()211 user_iterator user_begin() const { return use_begin(); }
user_end()212 user_iterator user_end() const { return use_end(); }
getUsers()213 user_range getUsers() const { return {user_begin(), user_end()}; }
214
215 //===--------------------------------------------------------------------===//
216 // Utilities
217
218 void print(raw_ostream &os);
219 void print(raw_ostream &os, const OpPrintingFlags &flags);
220 void print(raw_ostream &os, AsmState &state);
221 void dump();
222
223 /// Print this value as if it were an operand.
224 void printAsOperand(raw_ostream &os, AsmState &state);
225
226 /// Methods for supporting PointerLikeTypeTraits.
getAsOpaquePointer()227 void *getAsOpaquePointer() const { return impl; }
getFromOpaquePointer(const void * pointer)228 static Value getFromOpaquePointer(const void *pointer) {
229 return reinterpret_cast<detail::ValueImpl *>(const_cast<void *>(pointer));
230 }
getImpl()231 detail::ValueImpl *getImpl() const { return impl; }
232
233 friend ::llvm::hash_code hash_value(Value arg);
234
235 protected:
236 /// A pointer to the internal implementation of the value.
237 detail::ValueImpl *impl;
238 };
239
240 inline raw_ostream &operator<<(raw_ostream &os, Value value) {
241 value.print(os);
242 return os;
243 }
244
245 //===----------------------------------------------------------------------===//
246 // OpOperand
247 //===----------------------------------------------------------------------===//
248
249 /// This class represents an operand of an operation. Instances of this class
250 /// contain a reference to a specific `Value`.
251 class OpOperand : public IROperand<OpOperand, Value> {
252 public:
253 /// Provide the use list that is attached to the given value.
getUseList(Value value)254 static IRObjectWithUseList<OpOperand> *getUseList(Value value) {
255 return value.getImpl();
256 }
257
258 /// Return which operand this is in the OpOperand list of the Operation.
259 unsigned getOperandNumber();
260
261 private:
262 /// Keep the constructor private and accessible to the OperandStorage class
263 /// only to avoid hard-to-debug typo/programming mistakes.
264 friend class OperandStorage;
265 using IROperand<OpOperand, Value>::IROperand;
266 };
267
268 //===----------------------------------------------------------------------===//
269 // BlockArgument
270 //===----------------------------------------------------------------------===//
271
272 namespace detail {
273 /// The internal implementation of a BlockArgument.
274 class BlockArgumentImpl : public ValueImpl {
275 public:
classof(const ValueImpl * value)276 static bool classof(const ValueImpl *value) {
277 return value->getKind() == ValueImpl::Kind::BlockArgument;
278 }
279
280 private:
BlockArgumentImpl(Type type,Block * owner,int64_t index,Location loc)281 BlockArgumentImpl(Type type, Block *owner, int64_t index, Location loc)
282 : ValueImpl(type, Kind::BlockArgument), owner(owner), index(index),
283 loc(loc) {}
284
285 /// The owner of this argument.
286 Block *owner;
287
288 /// The position in the argument list.
289 int64_t index;
290
291 /// The source location of this argument.
292 Location loc;
293
294 /// Allow access to owner and constructor.
295 friend BlockArgument;
296 };
297 } // namespace detail
298
299 /// This class represents an argument of a Block.
300 class BlockArgument : public Value {
301 public:
302 using Value::Value;
303
classof(Value value)304 static bool classof(Value value) {
305 return llvm::isa<detail::BlockArgumentImpl>(value.getImpl());
306 }
307
308 /// Returns the block that owns this argument.
getOwner()309 Block *getOwner() const { return getImpl()->owner; }
310
311 /// Returns the number of this argument.
getArgNumber()312 unsigned getArgNumber() const { return getImpl()->index; }
313
314 /// Return the location for this argument.
getLoc()315 Location getLoc() const { return getImpl()->loc; }
setLoc(Location loc)316 void setLoc(Location loc) { getImpl()->loc = loc; }
317
318 private:
319 /// Allocate a new argument with the given type and owner.
create(Type type,Block * owner,int64_t index,Location loc)320 static BlockArgument create(Type type, Block *owner, int64_t index,
321 Location loc) {
322 return new detail::BlockArgumentImpl(type, owner, index, loc);
323 }
324
325 /// Destroy and deallocate this argument.
destroy()326 void destroy() { delete getImpl(); }
327
328 /// Get a raw pointer to the internal implementation.
getImpl()329 detail::BlockArgumentImpl *getImpl() const {
330 return reinterpret_cast<detail::BlockArgumentImpl *>(impl);
331 }
332
333 /// Cache the position in the block argument list.
setArgNumber(int64_t index)334 void setArgNumber(int64_t index) { getImpl()->index = index; }
335
336 /// Allow access to `create`, `destroy` and `setArgNumber`.
337 friend Block;
338
339 /// Allow access to 'getImpl'.
340 friend Value;
341 };
342
343 //===----------------------------------------------------------------------===//
344 // OpResult
345 //===----------------------------------------------------------------------===//
346
347 namespace detail {
348 /// This class provides the implementation for an operation result.
349 class alignas(8) OpResultImpl : public ValueImpl {
350 public:
351 using ValueImpl::ValueImpl;
352
classof(const ValueImpl * value)353 static bool classof(const ValueImpl *value) {
354 return value->getKind() != ValueImpl::Kind::BlockArgument;
355 }
356
357 /// Returns the parent operation of this result.
358 Operation *getOwner() const;
359
360 /// Returns the result number of this op result.
361 unsigned getResultNumber() const;
362
363 /// Returns the next operation result at `offset` after this result. This
364 /// method is useful when indexing the result storage of an operation, given
365 /// that there is more than one kind of operation result (with the different
366 /// kinds having different sizes) and that operations are stored in reverse
367 /// order.
368 OpResultImpl *getNextResultAtOffset(intptr_t offset);
369
370 /// Returns the maximum number of results that can be stored inline.
getMaxInlineResults()371 static unsigned getMaxInlineResults() {
372 return static_cast<unsigned>(Kind::OutOfLineOpResult);
373 }
374 };
375
376 /// This class provides the implementation for an operation result whose index
377 /// can be represented "inline" in the underlying ValueImpl.
378 struct InlineOpResult : public OpResultImpl {
379 public:
InlineOpResultInlineOpResult380 InlineOpResult(Type type, unsigned resultNo)
381 : OpResultImpl(type, static_cast<ValueImpl::Kind>(resultNo)) {
382 assert(resultNo < getMaxInlineResults());
383 }
384
385 /// Return the result number of this op result.
getResultNumberInlineOpResult386 unsigned getResultNumber() const { return static_cast<unsigned>(getKind()); }
387
classofInlineOpResult388 static bool classof(const OpResultImpl *value) {
389 return value->getKind() != ValueImpl::Kind::OutOfLineOpResult;
390 }
391 };
392
393 /// This class provides the implementation for an operation result whose index
394 /// cannot be represented "inline", and thus requires an additional index field.
395 class OutOfLineOpResult : public OpResultImpl {
396 public:
OutOfLineOpResult(Type type,uint64_t outOfLineIndex)397 OutOfLineOpResult(Type type, uint64_t outOfLineIndex)
398 : OpResultImpl(type, Kind::OutOfLineOpResult),
399 outOfLineIndex(outOfLineIndex) {}
400
classof(const OpResultImpl * value)401 static bool classof(const OpResultImpl *value) {
402 return value->getKind() == ValueImpl::Kind::OutOfLineOpResult;
403 }
404
405 /// Return the result number of this op result.
getResultNumber()406 unsigned getResultNumber() const {
407 return outOfLineIndex + getMaxInlineResults();
408 }
409
410 /// The trailing result number, or the offset from the beginning of the
411 /// `OutOfLineOpResult` array.
412 uint64_t outOfLineIndex;
413 };
414
415 /// Return the result number of this op result.
getResultNumber()416 inline unsigned OpResultImpl::getResultNumber() const {
417 if (const auto *outOfLineResult = dyn_cast<OutOfLineOpResult>(this))
418 return outOfLineResult->getResultNumber();
419 return cast<InlineOpResult>(this)->getResultNumber();
420 }
421
422 } // namespace detail
423
424 /// This is a value defined by a result of an operation.
425 class OpResult : public Value {
426 public:
427 using Value::Value;
428
classof(Value value)429 static bool classof(Value value) {
430 return llvm::isa<detail::OpResultImpl>(value.getImpl());
431 }
432
433 /// Returns the operation that owns this result.
getOwner()434 Operation *getOwner() const { return getImpl()->getOwner(); }
435
436 /// Returns the number of this result.
getResultNumber()437 unsigned getResultNumber() const { return getImpl()->getResultNumber(); }
438
439 private:
440 /// Get a raw pointer to the internal implementation.
getImpl()441 detail::OpResultImpl *getImpl() const {
442 return reinterpret_cast<detail::OpResultImpl *>(impl);
443 }
444
445 /// Given a number of operation results, returns the number that need to be
446 /// stored inline.
447 static unsigned getNumInline(unsigned numResults);
448
449 /// Given a number of operation results, returns the number that need to be
450 /// stored as trailing.
451 static unsigned getNumTrailing(unsigned numResults);
452
453 /// Allow access to constructor.
454 friend Operation;
455 };
456
457 /// Make Value hashable.
hash_value(Value arg)458 inline ::llvm::hash_code hash_value(Value arg) {
459 return ::llvm::hash_value(arg.getImpl());
460 }
461
462 } // namespace mlir
463
464 namespace llvm {
465
466 template <>
467 struct DenseMapInfo<mlir::Value> {
468 static mlir::Value getEmptyKey() {
469 void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
470 return mlir::Value::getFromOpaquePointer(pointer);
471 }
472 static mlir::Value getTombstoneKey() {
473 void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
474 return mlir::Value::getFromOpaquePointer(pointer);
475 }
476 static unsigned getHashValue(mlir::Value val) {
477 return mlir::hash_value(val);
478 }
479 static bool isEqual(mlir::Value lhs, mlir::Value rhs) { return lhs == rhs; }
480 };
481 template <>
482 struct DenseMapInfo<mlir::BlockArgument> : public DenseMapInfo<mlir::Value> {
483 static mlir::BlockArgument getEmptyKey() {
484 void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
485 return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
486 }
487 static mlir::BlockArgument getTombstoneKey() {
488 void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
489 return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
490 }
491 };
492 template <>
493 struct DenseMapInfo<mlir::OpResult> : public DenseMapInfo<mlir::Value> {
494 static mlir::OpResult getEmptyKey() {
495 void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
496 return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
497 }
498 static mlir::OpResult getTombstoneKey() {
499 void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
500 return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
501 }
502 };
503
504 /// Allow stealing the low bits of a value.
505 template <>
506 struct PointerLikeTypeTraits<mlir::Value> {
507 public:
508 static inline void *getAsVoidPointer(mlir::Value value) {
509 return const_cast<void *>(value.getAsOpaquePointer());
510 }
511 static inline mlir::Value getFromVoidPointer(void *pointer) {
512 return mlir::Value::getFromOpaquePointer(pointer);
513 }
514 enum {
515 NumLowBitsAvailable =
516 PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable
517 };
518 };
519 template <>
520 struct PointerLikeTypeTraits<mlir::BlockArgument>
521 : public PointerLikeTypeTraits<mlir::Value> {
522 public:
523 static inline mlir::BlockArgument getFromVoidPointer(void *pointer) {
524 return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
525 }
526 };
527 template <>
528 struct PointerLikeTypeTraits<mlir::OpResult>
529 : public PointerLikeTypeTraits<mlir::Value> {
530 public:
531 static inline mlir::OpResult getFromVoidPointer(void *pointer) {
532 return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
533 }
534 };
535
536 } // namespace llvm
537
538 #endif
539