xref: /llvm-project-15.0.7/mlir/lib/IR/Value.cpp (revision a062a3ed)
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 using namespace mlir;
14 
15 /// Construct a value.
16 Value::Value(detail::BlockArgumentImpl *impl)
17     : ownerAndKind(impl, Kind::BlockArgument) {}
18 Value::Value(Operation *op, unsigned resultNo) {
19   assert(op->getNumResults() > resultNo && "invalid result number");
20   if (LLVM_LIKELY(canPackResultInline(resultNo))) {
21     ownerAndKind = {op, static_cast<Kind>(resultNo)};
22     return;
23   }
24 
25   // If we can't pack the result directly, we need to represent this as a
26   // trailing result.
27   unsigned trailingResultNo =
28       resultNo - static_cast<unsigned>(Kind::TrailingOpResult);
29   ownerAndKind = {op->getTrailingResult(trailingResultNo),
30                   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   return cast<OpResult>().getOwner();
99 }
100 
101 /// Drop all uses of this object from their respective owners.
102 void Value::dropAllUses() const {
103   if (BlockArgument arg = dyn_cast<BlockArgument>())
104     return arg.getImpl()->dropAllUses();
105   Operation *owner = cast<OpResult>().getOwner();
106   if (owner->hasSingleResult)
107     return owner->dropAllUses();
108   return owner->dropAllUses(*this);
109 }
110 
111 /// Replace all uses of 'this' value with the new value, updating anything in
112 /// the IR that uses 'this' to use the other value instead.  When this returns
113 /// there are zero uses of 'this'.
114 void Value::replaceAllUsesWith(Value newValue) const {
115   if (BlockArgument arg = dyn_cast<BlockArgument>())
116     return arg.getImpl()->replaceAllUsesWith(newValue);
117   Operation *owner = cast<OpResult>().getOwner();
118   IRMultiObjectWithUseList<OpOperand> *useList = owner;
119   if (owner->hasSingleResult)
120     return useList->replaceAllUsesWith(newValue);
121   useList->replaceAllUsesWith(*this, newValue);
122 }
123 
124 //===--------------------------------------------------------------------===//
125 // Uses
126 
127 auto Value::use_begin() const -> use_iterator {
128   if (BlockArgument arg = dyn_cast<BlockArgument>())
129     return arg.getImpl()->use_begin();
130   Operation *owner = cast<OpResult>().getOwner();
131   return owner->hasSingleResult ? use_iterator(owner->use_begin())
132                                 : owner->use_begin(*this);
133 }
134 
135 /// Returns true if this value has exactly one use.
136 bool Value::hasOneUse() const {
137   if (BlockArgument arg = dyn_cast<BlockArgument>())
138     return arg.getImpl()->hasOneUse();
139   Operation *owner = cast<OpResult>().getOwner();
140   return owner->hasSingleResult ? owner->hasOneUse() : owner->hasOneUse(*this);
141 }
142 
143 /// Returns true if this value has no uses.
144 bool Value::use_empty() const {
145   if (BlockArgument arg = dyn_cast<BlockArgument>())
146     return arg.getImpl()->use_empty();
147   Operation *owner = cast<OpResult>().getOwner();
148   return owner->hasSingleResult ? owner->use_empty() : owner->use_empty(*this);
149 }
150 
151 //===----------------------------------------------------------------------===//
152 // OpResult
153 //===----------------------------------------------------------------------===//
154 
155 /// Returns the operation that owns this result.
156 Operation *OpResult::getOwner() const {
157   // If the result is in-place, the `owner` is the operation.
158   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
159     return reinterpret_cast<Operation *>(ownerAndKind.getPointer());
160 
161   // Otherwise, we need to do some arithmetic to get the operation pointer.
162   // Move the trailing owner to the start of the array.
163   auto *trailingIt =
164       static_cast<detail::TrailingOpResult *>(ownerAndKind.getPointer());
165   trailingIt -= trailingIt->trailingResultNumber;
166 
167   // This point is the first trailing object after the operation. So all we need
168   // to do here is adjust for the operation size.
169   return reinterpret_cast<Operation *>(trailingIt) - 1;
170 }
171 
172 /// Return the result number of this result.
173 unsigned OpResult::getResultNumber() const {
174   // If the result is in-place, we can use the kind directly.
175   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
176     return static_cast<unsigned>(ownerAndKind.getInt());
177   // Otherwise, we add the number of inline results to the trailing owner.
178   auto *trailingIt =
179       static_cast<detail::TrailingOpResult *>(ownerAndKind.getPointer());
180   unsigned trailingNumber = trailingIt->trailingResultNumber;
181   return trailingNumber + static_cast<unsigned>(Kind::TrailingOpResult);
182 }
183 
184 /// Given a number of operation results, returns the number that need to be
185 /// stored as trailing.
186 unsigned OpResult::getNumTrailing(unsigned numResults) {
187   // If we can pack all of the results, there is no need for additional storage.
188   if (numResults <= static_cast<unsigned>(Kind::TrailingOpResult))
189     return 0;
190   return numResults - static_cast<unsigned>(Kind::TrailingOpResult);
191 }
192 
193 //===----------------------------------------------------------------------===//
194 // BlockOperand
195 //===----------------------------------------------------------------------===//
196 
197 /// Provide the use list that is attached to the given block.
198 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
199   return value;
200 }
201 
202 /// Return which operand this is in the operand list.
203 unsigned BlockOperand::getOperandNumber() {
204   return this - &getOwner()->getBlockOperands()[0];
205 }
206 
207 //===----------------------------------------------------------------------===//
208 // OpOperand
209 //===----------------------------------------------------------------------===//
210 
211 /// Provide the use list that is attached to the given value.
212 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
213   return value.getUseList();
214 }
215 
216 /// Return the current value being used by this operand.
217 Value OpOperand::get() const {
218   return IROperand<OpOperand, detail::OpaqueValue>::get();
219 }
220 
221 /// Set the operand to the given value.
222 void OpOperand::set(Value value) {
223   IROperand<OpOperand, detail::OpaqueValue>::set(value);
224 }
225 
226 /// Return which operand this is in the operand list.
227 unsigned OpOperand::getOperandNumber() {
228   return this - &getOwner()->getOpOperands()[0];
229 }
230 
231 //===----------------------------------------------------------------------===//
232 // detail::OpaqueValue
233 //===----------------------------------------------------------------------===//
234 
235 /// Implicit conversion from 'Value'.
236 detail::OpaqueValue::OpaqueValue(Value value)
237     : impl(value.getAsOpaquePointer()) {}
238 
239 /// Implicit conversion back to 'Value'.
240 detail::OpaqueValue::operator Value() const {
241   return Value::getFromOpaquePointer(impl);
242 }
243