/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 |