xref: /llvm-project-15.0.7/mlir/lib/IR/Value.cpp (revision 8f5beb4c)
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 //===----------------------------------------------------------------------===//
91 // Value::UseLists
92 //===----------------------------------------------------------------------===//
93 
94 /// Provide the use list that is attached to this value.
95 IRObjectWithUseList<OpOperand> *Value::getUseList() const {
96   if (BlockArgument arg = dyn_cast<BlockArgument>())
97     return arg.getImpl();
98   if (getKind() != Kind::TrailingOpResult) {
99     OpResult result = cast<OpResult>();
100     return result.getOwner()->getInlineResult(result.getResultNumber());
101   }
102 
103   // Otherwise this is a trailing operation result, which contains a use list.
104   return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer());
105 }
106 
107 /// Drop all uses of this object from their respective owners.
108 void Value::dropAllUses() const { return getUseList()->dropAllUses(); }
109 
110 /// Replace all uses of 'this' value with the new value, updating anything in
111 /// the IR that uses 'this' to use the other value instead.  When this returns
112 /// there are zero uses of 'this'.
113 void Value::replaceAllUsesWith(Value newValue) const {
114   return getUseList()->replaceAllUsesWith(newValue);
115 }
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 except if the user is
119 /// listed in 'exceptions' .
120 void Value::replaceAllUsesExcept(
121     Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const {
122   for (auto &use : llvm::make_early_inc_range(getUses())) {
123     if (exceptions.count(use.getOwner()) == 0)
124       use.set(newValue);
125   }
126 }
127 
128 /// Replace all uses of 'this' value with 'newValue' if the given callback
129 /// returns true.
130 void Value::replaceUsesWithIf(Value newValue,
131                               function_ref<bool(OpOperand &)> shouldReplace) {
132   for (OpOperand &use : llvm::make_early_inc_range(getUses()))
133     if (shouldReplace(use))
134       use.set(newValue);
135 }
136 
137 //===--------------------------------------------------------------------===//
138 // Uses
139 
140 auto Value::use_begin() const -> use_iterator {
141   return getUseList()->use_begin();
142 }
143 
144 /// Returns true if this value has exactly one use.
145 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); }
146 
147 /// Returns true if this value has no uses.
148 bool Value::use_empty() const { return getUseList()->use_empty(); }
149 
150 //===----------------------------------------------------------------------===//
151 // OpResult
152 //===----------------------------------------------------------------------===//
153 
154 /// Returns the operation that owns this result.
155 Operation *OpResult::getOwner() const {
156   // If the result is in-place, the `owner` is the operation.
157   void *owner = ownerAndKind.getPointer();
158   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
159     return static_cast<Operation *>(owner);
160 
161   // Otherwise, query the trailing result for the owner.
162   return static_cast<TrailingOpResult *>(owner)->getOwner();
163 }
164 
165 /// Return the result number of this result.
166 unsigned OpResult::getResultNumber() const {
167   // If the result is in-place, we can use the kind directly.
168   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
169     return static_cast<unsigned>(ownerAndKind.getInt());
170   // Otherwise, query the trailing result.
171   auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer());
172   return result->getResultNumber();
173 }
174 
175 /// Given a number of operation results, returns the number that need to be
176 /// stored inline.
177 unsigned OpResult::getNumInline(unsigned numResults) {
178   return std::min(numResults, getMaxInlineResults());
179 }
180 
181 /// Given a number of operation results, returns the number that need to be
182 /// stored as trailing.
183 unsigned OpResult::getNumTrailing(unsigned numResults) {
184   // If we can pack all of the results, there is no need for additional storage.
185   unsigned maxInline = getMaxInlineResults();
186   return numResults <= maxInline ? 0 : numResults - maxInline;
187 }
188 
189 //===----------------------------------------------------------------------===//
190 // BlockOperand
191 //===----------------------------------------------------------------------===//
192 
193 /// Provide the use list that is attached to the given block.
194 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
195   return value;
196 }
197 
198 /// Return which operand this is in the operand list.
199 unsigned BlockOperand::getOperandNumber() {
200   return this - &getOwner()->getBlockOperands()[0];
201 }
202 
203 //===----------------------------------------------------------------------===//
204 // OpOperand
205 //===----------------------------------------------------------------------===//
206 
207 /// Provide the use list that is attached to the given value.
208 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
209   return value.getUseList();
210 }
211 
212 /// Return the current value being used by this operand.
213 Value OpOperand::get() const {
214   return IROperand<OpOperand, OpaqueValue>::get();
215 }
216 
217 /// Set the operand to the given value.
218 void OpOperand::set(Value value) {
219   IROperand<OpOperand, OpaqueValue>::set(value);
220 }
221 
222 /// Return which operand this is in the operand list.
223 unsigned OpOperand::getOperandNumber() {
224   return this - &getOwner()->getOpOperands()[0];
225 }
226 
227 //===----------------------------------------------------------------------===//
228 // OpaqueValue
229 //===----------------------------------------------------------------------===//
230 
231 /// Implicit conversion from 'Value'.
232 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {}
233 
234 /// Implicit conversion back to 'Value'.
235 OpaqueValue::operator Value() const {
236   return Value::getFromOpaquePointer(impl);
237 }
238