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