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