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 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. 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. 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. 106 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. 119 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'. 124 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' . 131 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. 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. 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 158 auto Value::use_begin() const -> use_iterator { 159 return getUseList()->use_begin(); 160 } 161 162 /// Returns true if this value has exactly one use. 163 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); } 164 165 /// Returns true if this value has no uses. 166 bool Value::use_empty() const { return getUseList()->use_empty(); } 167 168 //===----------------------------------------------------------------------===// 169 // OpResult 170 //===----------------------------------------------------------------------===// 171 172 /// Returns the operation that owns this result. 173 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. 184 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. 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. 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. 212 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) { 213 return value; 214 } 215 216 /// Return which operand this is in the operand list. 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. 226 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) { 227 return value.getUseList(); 228 } 229 230 /// Return the current value being used by this operand. 231 Value OpOperand::get() const { 232 return IROperand<OpOperand, OpaqueValue>::get(); 233 } 234 235 /// Set the operand to the given 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. 241 unsigned OpOperand::getOperandNumber() { 242 return this - &getOwner()->getOpOperands()[0]; 243 } 244 245 //===----------------------------------------------------------------------===// 246 // OpaqueValue 247 //===----------------------------------------------------------------------===// 248 249 /// Implicit conversion from 'Value'. 250 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {} 251 252 /// Implicit conversion back to 'Value'. 253 OpaqueValue::operator Value() const { 254 return Value::getFromOpaquePointer(impl); 255 } 256