xref: /llvm-project-15.0.7/mlir/lib/IR/Value.cpp (revision abb4cd3e)
1 //===- Value.cpp - MLIR Value Classes -------------------------------------===//
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 #include "mlir/IR/Value.h"
10 #include "mlir/IR/Block.h"
11 #include "mlir/IR/BuiltinTypes.h"
12 #include "mlir/IR/Operation.h"
13 #include "llvm/ADT/SmallPtrSet.h"
14 
15 using namespace mlir;
16 using namespace mlir::detail;
17 
18 /// Construct a value.
19 Value::Value(BlockArgumentImpl *impl)
20     : ownerAndKind(impl, Kind::BlockArgument) {}
21 Value::Value(Operation *op, unsigned resultNo) {
22   assert(op->getNumResults() > resultNo && "invalid result number");
23   if (LLVM_LIKELY(canPackResultInline(resultNo))) {
24     ownerAndKind = {op, static_cast<Kind>(resultNo)};
25     return;
26   }
27 
28   // If we can't pack the result directly, grab the use list from the parent op.
29   unsigned trailingNo = resultNo - OpResult::getMaxInlineResults();
30   ownerAndKind = {op->getTrailingResult(trailingNo), Kind::TrailingOpResult};
31 }
32 
33 /// Return the type of this value.
34 Type Value::getType() const {
35   // Support a null Value so the asmprinter doesn't crash on invalid IR (e.g.
36   // operations that have dropAllReferences() called on them).
37   if (!*this)
38     return Type();
39 
40   if (BlockArgument arg = dyn_cast<BlockArgument>())
41     return arg.getType();
42 
43   // If this is an operation result, query the parent operation.
44   OpResult result = cast<OpResult>();
45   Operation *owner = result.getOwner();
46   if (owner->hasSingleResult)
47     return owner->resultType;
48   return owner->resultType.cast<TupleType>().getType(result.getResultNumber());
49 }
50 
51 /// Mutate the type of this Value to be of the specified type.
52 void Value::setType(Type newType) {
53   if (BlockArgument arg = dyn_cast<BlockArgument>())
54     return arg.setType(newType);
55   OpResult result = cast<OpResult>();
56 
57   // If the owner has a single result, simply update it directly.
58   Operation *owner = result.getOwner();
59   if (owner->hasSingleResult) {
60     owner->resultType = newType;
61     return;
62   }
63   unsigned resultNo = result.getResultNumber();
64 
65   // Otherwise, rebuild the tuple if the new type is different from the current.
66   auto curTypes = owner->resultType.cast<TupleType>().getTypes();
67   if (curTypes[resultNo] == newType)
68     return;
69   auto newTypes = llvm::to_vector<4>(curTypes);
70   newTypes[resultNo] = newType;
71   owner->resultType = TupleType::get(newType.getContext(), newTypes);
72 }
73 
74 /// If this value is the result of an Operation, return the operation that
75 /// defines it.
76 Operation *Value::getDefiningOp() const {
77   if (auto result = dyn_cast<OpResult>())
78     return result.getOwner();
79   return nullptr;
80 }
81 
82 Location Value::getLoc() const {
83   if (auto *op = getDefiningOp())
84     return op->getLoc();
85 
86   // Use the location of the parent operation if this is a block argument.
87   // TODO: Should we just add locations to block arguments?
88   Operation *parentOp = cast<BlockArgument>().getOwner()->getParentOp();
89   return parentOp ? parentOp->getLoc() : UnknownLoc::get(getContext());
90 }
91 
92 /// Return the Region in which this Value is defined.
93 Region *Value::getParentRegion() {
94   if (auto *op = getDefiningOp())
95     return op->getParentRegion();
96   return cast<BlockArgument>().getOwner()->getParent();
97 }
98 
99 /// Return the Block in which this Value is defined.
100 Block *Value::getParentBlock() {
101   if (Operation *op = getDefiningOp())
102     return op->getBlock();
103   return cast<BlockArgument>().getOwner();
104 }
105 
106 //===----------------------------------------------------------------------===//
107 // Value::UseLists
108 //===----------------------------------------------------------------------===//
109 
110 /// Provide the use list that is attached to this value.
111 IRObjectWithUseList<OpOperand> *Value::getUseList() const {
112   if (BlockArgument arg = dyn_cast<BlockArgument>())
113     return arg.getImpl();
114   if (getKind() != Kind::TrailingOpResult) {
115     OpResult result = cast<OpResult>();
116     return result.getOwner()->getInlineResult(result.getResultNumber());
117   }
118 
119   // Otherwise this is a trailing operation result, which contains a use list.
120   return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer());
121 }
122 
123 /// Drop all uses of this object from their respective owners.
124 void Value::dropAllUses() const { return getUseList()->dropAllUses(); }
125 
126 /// Replace all uses of 'this' value with the new value, updating anything in
127 /// the IR that uses 'this' to use the other value instead.  When this returns
128 /// there are zero uses of 'this'.
129 void Value::replaceAllUsesWith(Value newValue) const {
130   return getUseList()->replaceAllUsesWith(newValue);
131 }
132 
133 /// Replace all uses of 'this' value with the new value, updating anything in
134 /// the IR that uses 'this' to use the other value instead except if the user is
135 /// listed in 'exceptions' .
136 void Value::replaceAllUsesExcept(
137     Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const {
138   for (auto &use : llvm::make_early_inc_range(getUses())) {
139     if (exceptions.count(use.getOwner()) == 0)
140       use.set(newValue);
141   }
142 }
143 
144 /// Replace all uses of 'this' value with 'newValue' if the given callback
145 /// returns true.
146 void Value::replaceUsesWithIf(Value newValue,
147                               function_ref<bool(OpOperand &)> shouldReplace) {
148   for (OpOperand &use : llvm::make_early_inc_range(getUses()))
149     if (shouldReplace(use))
150       use.set(newValue);
151 }
152 
153 /// Returns true if the value is used outside of the given block.
154 bool Value::isUsedOutsideOfBlock(Block *block) {
155   return llvm::any_of(getUsers(), [block](Operation *user) {
156     return user->getBlock() != block;
157   });
158 }
159 
160 //===--------------------------------------------------------------------===//
161 // Uses
162 
163 auto Value::use_begin() const -> use_iterator {
164   return getUseList()->use_begin();
165 }
166 
167 /// Returns true if this value has exactly one use.
168 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); }
169 
170 /// Returns true if this value has no uses.
171 bool Value::use_empty() const { return getUseList()->use_empty(); }
172 
173 //===----------------------------------------------------------------------===//
174 // OpResult
175 //===----------------------------------------------------------------------===//
176 
177 /// Returns the operation that owns this result.
178 Operation *OpResult::getOwner() const {
179   // If the result is in-place, the `owner` is the operation.
180   void *owner = ownerAndKind.getPointer();
181   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
182     return static_cast<Operation *>(owner);
183 
184   // Otherwise, query the trailing result for the owner.
185   return static_cast<TrailingOpResult *>(owner)->getOwner();
186 }
187 
188 /// Return the result number of this result.
189 unsigned OpResult::getResultNumber() const {
190   // If the result is in-place, we can use the kind directly.
191   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
192     return static_cast<unsigned>(ownerAndKind.getInt());
193   // Otherwise, query the trailing result.
194   auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer());
195   return result->getResultNumber();
196 }
197 
198 /// Given a number of operation results, returns the number that need to be
199 /// stored inline.
200 unsigned OpResult::getNumInline(unsigned numResults) {
201   return std::min(numResults, getMaxInlineResults());
202 }
203 
204 /// Given a number of operation results, returns the number that need to be
205 /// stored as trailing.
206 unsigned OpResult::getNumTrailing(unsigned numResults) {
207   // If we can pack all of the results, there is no need for additional storage.
208   unsigned maxInline = getMaxInlineResults();
209   return numResults <= maxInline ? 0 : numResults - maxInline;
210 }
211 
212 //===----------------------------------------------------------------------===//
213 // BlockOperand
214 //===----------------------------------------------------------------------===//
215 
216 /// Provide the use list that is attached to the given block.
217 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
218   return value;
219 }
220 
221 /// Return which operand this is in the operand list.
222 unsigned BlockOperand::getOperandNumber() {
223   return this - &getOwner()->getBlockOperands()[0];
224 }
225 
226 //===----------------------------------------------------------------------===//
227 // OpOperand
228 //===----------------------------------------------------------------------===//
229 
230 /// Provide the use list that is attached to the given value.
231 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
232   return value.getUseList();
233 }
234 
235 /// Return the current value being used by this operand.
236 Value OpOperand::get() const {
237   return IROperand<OpOperand, OpaqueValue>::get();
238 }
239 
240 /// Set the operand to the given value.
241 void OpOperand::set(Value value) {
242   IROperand<OpOperand, OpaqueValue>::set(value);
243 }
244 
245 /// Return which operand this is in the operand list.
246 unsigned OpOperand::getOperandNumber() {
247   return this - &getOwner()->getOpOperands()[0];
248 }
249 
250 //===----------------------------------------------------------------------===//
251 // OpaqueValue
252 //===----------------------------------------------------------------------===//
253 
254 /// Implicit conversion from 'Value'.
255 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {}
256 
257 /// Implicit conversion back to 'Value'.
258 OpaqueValue::operator Value() const {
259   return Value::getFromOpaquePointer(impl);
260 }
261