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. 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 // Support a null Value so the asmprinter doesn't crash on invalid IR (e.g. 36 // operations that have dropAllReferences() called on them). 37 if (!*this) 38 return Type(); 39 40 if (BlockArgument arg = dyn_cast<BlockArgument>()) 41 return arg.getType(); 42 43 // If this is an operation result, query the parent operation. 44 OpResult result = cast<OpResult>(); 45 Operation *owner = result.getOwner(); 46 if (owner->hasSingleResult) 47 return owner->resultType; 48 return owner->resultType.cast<TupleType>().getType(result.getResultNumber()); 49 } 50 51 /// Mutate the type of this Value to be of the specified type. 52 void Value::setType(Type newType) { 53 if (BlockArgument arg = dyn_cast<BlockArgument>()) 54 return arg.setType(newType); 55 OpResult result = cast<OpResult>(); 56 57 // If the owner has a single result, simply update it directly. 58 Operation *owner = result.getOwner(); 59 if (owner->hasSingleResult) { 60 owner->resultType = newType; 61 return; 62 } 63 unsigned resultNo = result.getResultNumber(); 64 65 // Otherwise, rebuild the tuple if the new type is different from the current. 66 auto curTypes = owner->resultType.cast<TupleType>().getTypes(); 67 if (curTypes[resultNo] == newType) 68 return; 69 auto newTypes = llvm::to_vector<4>(curTypes); 70 newTypes[resultNo] = newType; 71 owner->resultType = TupleType::get(newType.getContext(), newTypes); 72 } 73 74 /// If this value is the result of an Operation, return the operation that 75 /// defines it. 76 Operation *Value::getDefiningOp() const { 77 if (auto result = dyn_cast<OpResult>()) 78 return result.getOwner(); 79 return nullptr; 80 } 81 82 Location Value::getLoc() const { 83 if (auto *op = getDefiningOp()) 84 return op->getLoc(); 85 86 // Use the location of the parent operation if this is a block argument. 87 // TODO: Should we just add locations to block arguments? 88 Operation *parentOp = cast<BlockArgument>().getOwner()->getParentOp(); 89 return parentOp ? parentOp->getLoc() : UnknownLoc::get(getContext()); 90 } 91 92 /// Return the Region in which this Value is defined. 93 Region *Value::getParentRegion() { 94 if (auto *op = getDefiningOp()) 95 return op->getParentRegion(); 96 return cast<BlockArgument>().getOwner()->getParent(); 97 } 98 99 /// Return the Block in which this Value is defined. 100 Block *Value::getParentBlock() { 101 if (Operation *op = getDefiningOp()) 102 return op->getBlock(); 103 return cast<BlockArgument>().getOwner(); 104 } 105 106 //===----------------------------------------------------------------------===// 107 // Value::UseLists 108 //===----------------------------------------------------------------------===// 109 110 /// Provide the use list that is attached to this value. 111 IRObjectWithUseList<OpOperand> *Value::getUseList() const { 112 if (BlockArgument arg = dyn_cast<BlockArgument>()) 113 return arg.getImpl(); 114 if (getKind() != Kind::TrailingOpResult) { 115 OpResult result = cast<OpResult>(); 116 return result.getOwner()->getInlineResult(result.getResultNumber()); 117 } 118 119 // Otherwise this is a trailing operation result, which contains a use list. 120 return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer()); 121 } 122 123 /// Drop all uses of this object from their respective owners. 124 void Value::dropAllUses() const { return getUseList()->dropAllUses(); } 125 126 /// Replace all uses of 'this' value with the new value, updating anything in 127 /// the IR that uses 'this' to use the other value instead. When this returns 128 /// there are zero uses of 'this'. 129 void Value::replaceAllUsesWith(Value newValue) const { 130 return getUseList()->replaceAllUsesWith(newValue); 131 } 132 133 /// Replace all uses of 'this' value with the new value, updating anything in 134 /// the IR that uses 'this' to use the other value instead except if the user is 135 /// listed in 'exceptions' . 136 void Value::replaceAllUsesExcept( 137 Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const { 138 for (auto &use : llvm::make_early_inc_range(getUses())) { 139 if (exceptions.count(use.getOwner()) == 0) 140 use.set(newValue); 141 } 142 } 143 144 /// Replace all uses of 'this' value with 'newValue' if the given callback 145 /// returns true. 146 void Value::replaceUsesWithIf(Value newValue, 147 function_ref<bool(OpOperand &)> shouldReplace) { 148 for (OpOperand &use : llvm::make_early_inc_range(getUses())) 149 if (shouldReplace(use)) 150 use.set(newValue); 151 } 152 153 /// Returns true if the value is used outside of the given block. 154 bool Value::isUsedOutsideOfBlock(Block *block) { 155 return llvm::any_of(getUsers(), [block](Operation *user) { 156 return user->getBlock() != block; 157 }); 158 } 159 160 //===--------------------------------------------------------------------===// 161 // Uses 162 163 auto Value::use_begin() const -> use_iterator { 164 return getUseList()->use_begin(); 165 } 166 167 /// Returns true if this value has exactly one use. 168 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); } 169 170 /// Returns true if this value has no uses. 171 bool Value::use_empty() const { return getUseList()->use_empty(); } 172 173 //===----------------------------------------------------------------------===// 174 // OpResult 175 //===----------------------------------------------------------------------===// 176 177 /// Returns the operation that owns this result. 178 Operation *OpResult::getOwner() const { 179 // If the result is in-place, the `owner` is the operation. 180 void *owner = ownerAndKind.getPointer(); 181 if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult)) 182 return static_cast<Operation *>(owner); 183 184 // Otherwise, query the trailing result for the owner. 185 return static_cast<TrailingOpResult *>(owner)->getOwner(); 186 } 187 188 /// Return the result number of this result. 189 unsigned OpResult::getResultNumber() const { 190 // If the result is in-place, we can use the kind directly. 191 if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult)) 192 return static_cast<unsigned>(ownerAndKind.getInt()); 193 // Otherwise, query the trailing result. 194 auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer()); 195 return result->getResultNumber(); 196 } 197 198 /// Given a number of operation results, returns the number that need to be 199 /// stored inline. 200 unsigned OpResult::getNumInline(unsigned numResults) { 201 return std::min(numResults, getMaxInlineResults()); 202 } 203 204 /// Given a number of operation results, returns the number that need to be 205 /// stored as trailing. 206 unsigned OpResult::getNumTrailing(unsigned numResults) { 207 // If we can pack all of the results, there is no need for additional storage. 208 unsigned maxInline = getMaxInlineResults(); 209 return numResults <= maxInline ? 0 : numResults - maxInline; 210 } 211 212 //===----------------------------------------------------------------------===// 213 // BlockOperand 214 //===----------------------------------------------------------------------===// 215 216 /// Provide the use list that is attached to the given block. 217 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) { 218 return value; 219 } 220 221 /// Return which operand this is in the operand list. 222 unsigned BlockOperand::getOperandNumber() { 223 return this - &getOwner()->getBlockOperands()[0]; 224 } 225 226 //===----------------------------------------------------------------------===// 227 // OpOperand 228 //===----------------------------------------------------------------------===// 229 230 /// Provide the use list that is attached to the given value. 231 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) { 232 return value.getUseList(); 233 } 234 235 /// Return the current value being used by this operand. 236 Value OpOperand::get() const { 237 return IROperand<OpOperand, OpaqueValue>::get(); 238 } 239 240 /// Set the operand to the given value. 241 void OpOperand::set(Value value) { 242 IROperand<OpOperand, OpaqueValue>::set(value); 243 } 244 245 /// Return which operand this is in the operand list. 246 unsigned OpOperand::getOperandNumber() { 247 return this - &getOwner()->getOpOperands()[0]; 248 } 249 250 //===----------------------------------------------------------------------===// 251 // OpaqueValue 252 //===----------------------------------------------------------------------===// 253 254 /// Implicit conversion from 'Value'. 255 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {} 256 257 /// Implicit conversion back to 'Value'. 258 OpaqueValue::operator Value() const { 259 return Value::getFromOpaquePointer(impl); 260 } 261