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.
Value(BlockArgumentImpl * impl)19 Value::Value(BlockArgumentImpl *impl)
20     : ownerAndKind(impl, Kind::BlockArgument) {}
Value(Operation * op,unsigned resultNo)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.
getType() const34 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.
setType(Type newType)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.
getDefiningOp() const71 Operation *Value::getDefiningOp() const {
72   if (auto result = dyn_cast<OpResult>())
73     return result.getOwner();
74   return nullptr;
75 }
76 
getLoc() const77 Location Value::getLoc() const {
78   if (auto *op = getDefiningOp())
79     return op->getLoc();
80 
81   // Use the location of the parent operation if this is a block argument.
82   // TODO: Should we just add locations to block arguments?
83   Operation *parentOp = cast<BlockArgument>().getOwner()->getParentOp();
84   return parentOp ? parentOp->getLoc() : UnknownLoc::get(getContext());
85 }
86 
87 /// Return the Region in which this Value is defined.
getParentRegion()88 Region *Value::getParentRegion() {
89   if (auto *op = getDefiningOp())
90     return op->getParentRegion();
91   return cast<BlockArgument>().getOwner()->getParent();
92 }
93 
94 /// Return the Block in which this Value is defined.
getParentBlock()95 Block *Value::getParentBlock() {
96   if (Operation *op = getDefiningOp())
97     return op->getBlock();
98   return cast<BlockArgument>().getOwner();
99 }
100 
101 //===----------------------------------------------------------------------===//
102 // Value::UseLists
103 //===----------------------------------------------------------------------===//
104 
105 /// Provide the use list that is attached to this value.
getUseList() const106 IRObjectWithUseList<OpOperand> *Value::getUseList() const {
107   if (BlockArgument arg = dyn_cast<BlockArgument>())
108     return arg.getImpl();
109   if (getKind() != Kind::TrailingOpResult) {
110     OpResult result = cast<OpResult>();
111     return result.getOwner()->getInlineResult(result.getResultNumber());
112   }
113 
114   // Otherwise this is a trailing operation result, which contains a use list.
115   return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer());
116 }
117 
118 /// Drop all uses of this object from their respective owners.
dropAllUses() const119 void Value::dropAllUses() const { return getUseList()->dropAllUses(); }
120 
121 /// Replace all uses of 'this' value with the new value, updating anything in
122 /// the IR that uses 'this' to use the other value instead.  When this returns
123 /// there are zero uses of 'this'.
replaceAllUsesWith(Value newValue) const124 void Value::replaceAllUsesWith(Value newValue) const {
125   return getUseList()->replaceAllUsesWith(newValue);
126 }
127 
128 /// Replace all uses of 'this' value with the new value, updating anything in
129 /// the IR that uses 'this' to use the other value instead except if the user is
130 /// listed in 'exceptions' .
replaceAllUsesExcept(Value newValue,const SmallPtrSetImpl<Operation * > & exceptions) const131 void Value::replaceAllUsesExcept(
132     Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const {
133   for (auto &use : llvm::make_early_inc_range(getUses())) {
134     if (exceptions.count(use.getOwner()) == 0)
135       use.set(newValue);
136   }
137 }
138 
139 /// Replace all uses of 'this' value with 'newValue' if the given callback
140 /// returns true.
replaceUsesWithIf(Value newValue,function_ref<bool (OpOperand &)> shouldReplace)141 void Value::replaceUsesWithIf(Value newValue,
142                               function_ref<bool(OpOperand &)> shouldReplace) {
143   for (OpOperand &use : llvm::make_early_inc_range(getUses()))
144     if (shouldReplace(use))
145       use.set(newValue);
146 }
147 
148 /// Returns true if the value is used outside of the given block.
isUsedOutsideOfBlock(Block * block)149 bool Value::isUsedOutsideOfBlock(Block *block) {
150   return llvm::any_of(getUsers(), [block](Operation *user) {
151     return user->getBlock() != block;
152   });
153 }
154 
155 //===--------------------------------------------------------------------===//
156 // Uses
157 
use_begin() const158 auto Value::use_begin() const -> use_iterator {
159   return getUseList()->use_begin();
160 }
161 
162 /// Returns true if this value has exactly one use.
hasOneUse() const163 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); }
164 
165 /// Returns true if this value has no uses.
use_empty() const166 bool Value::use_empty() const { return getUseList()->use_empty(); }
167 
168 //===----------------------------------------------------------------------===//
169 // OpResult
170 //===----------------------------------------------------------------------===//
171 
172 /// Returns the operation that owns this result.
getOwner() const173 Operation *OpResult::getOwner() const {
174   // If the result is in-place, the `owner` is the operation.
175   void *owner = ownerAndKind.getPointer();
176   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
177     return static_cast<Operation *>(owner);
178 
179   // Otherwise, query the trailing result for the owner.
180   return static_cast<TrailingOpResult *>(owner)->getOwner();
181 }
182 
183 /// Return the result number of this result.
getResultNumber() const184 unsigned OpResult::getResultNumber() const {
185   // If the result is in-place, we can use the kind directly.
186   if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
187     return static_cast<unsigned>(ownerAndKind.getInt());
188   // Otherwise, query the trailing result.
189   auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer());
190   return result->getResultNumber();
191 }
192 
193 /// Given a number of operation results, returns the number that need to be
194 /// stored inline.
getNumInline(unsigned numResults)195 unsigned OpResult::getNumInline(unsigned numResults) {
196   return std::min(numResults, getMaxInlineResults());
197 }
198 
199 /// Given a number of operation results, returns the number that need to be
200 /// stored as trailing.
getNumTrailing(unsigned numResults)201 unsigned OpResult::getNumTrailing(unsigned numResults) {
202   // If we can pack all of the results, there is no need for additional storage.
203   unsigned maxInline = getMaxInlineResults();
204   return numResults <= maxInline ? 0 : numResults - maxInline;
205 }
206 
207 //===----------------------------------------------------------------------===//
208 // BlockOperand
209 //===----------------------------------------------------------------------===//
210 
211 /// Provide the use list that is attached to the given block.
getUseList(Block * value)212 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
213   return value;
214 }
215 
216 /// Return which operand this is in the operand list.
getOperandNumber()217 unsigned BlockOperand::getOperandNumber() {
218   return this - &getOwner()->getBlockOperands()[0];
219 }
220 
221 //===----------------------------------------------------------------------===//
222 // OpOperand
223 //===----------------------------------------------------------------------===//
224 
225 /// Provide the use list that is attached to the given value.
getUseList(Value value)226 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
227   return value.getUseList();
228 }
229 
230 /// Return the current value being used by this operand.
get() const231 Value OpOperand::get() const {
232   return IROperand<OpOperand, OpaqueValue>::get();
233 }
234 
235 /// Set the operand to the given value.
set(Value value)236 void OpOperand::set(Value value) {
237   IROperand<OpOperand, OpaqueValue>::set(value);
238 }
239 
240 /// Return which operand this is in the operand list.
getOperandNumber()241 unsigned OpOperand::getOperandNumber() {
242   return this - &getOwner()->getOpOperands()[0];
243 }
244 
245 //===----------------------------------------------------------------------===//
246 // OpaqueValue
247 //===----------------------------------------------------------------------===//
248 
249 /// Implicit conversion from 'Value'.
OpaqueValue(Value value)250 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {}
251 
252 /// Implicit conversion back to 'Value'.
operator Value() const253 OpaqueValue::operator Value() const {
254   return Value::getFromOpaquePointer(impl);
255 }
256