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 //===----------------------------------------------------------------------===// 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 if (getKind() != Kind::TrailingOpResult) { 99 OpResult result = cast<OpResult>(); 100 return result.getOwner()->getInlineResult(result.getResultNumber()); 101 } 102 103 // Otherwise this is a trailing operation result, which contains a use list. 104 return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer()); 105 } 106 107 /// Drop all uses of this object from their respective owners. 108 void Value::dropAllUses() const { return getUseList()->dropAllUses(); } 109 110 /// Replace all uses of 'this' value with the new value, updating anything in 111 /// the IR that uses 'this' to use the other value instead. When this returns 112 /// there are zero uses of 'this'. 113 void Value::replaceAllUsesWith(Value newValue) const { 114 return getUseList()->replaceAllUsesWith(newValue); 115 } 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 except if the user is 119 /// listed in 'exceptions' . 120 void Value::replaceAllUsesExcept( 121 Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const { 122 for (auto &use : llvm::make_early_inc_range(getUses())) { 123 if (exceptions.count(use.getOwner()) == 0) 124 use.set(newValue); 125 } 126 } 127 128 /// Replace all uses of 'this' value with 'newValue' if the given callback 129 /// returns true. 130 void Value::replaceUsesWithIf(Value newValue, 131 function_ref<bool(OpOperand &)> shouldReplace) { 132 for (OpOperand &use : llvm::make_early_inc_range(getUses())) 133 if (shouldReplace(use)) 134 use.set(newValue); 135 } 136 137 //===--------------------------------------------------------------------===// 138 // Uses 139 140 auto Value::use_begin() const -> use_iterator { 141 return getUseList()->use_begin(); 142 } 143 144 /// Returns true if this value has exactly one use. 145 bool Value::hasOneUse() const { return getUseList()->hasOneUse(); } 146 147 /// Returns true if this value has no uses. 148 bool Value::use_empty() const { return getUseList()->use_empty(); } 149 150 //===----------------------------------------------------------------------===// 151 // OpResult 152 //===----------------------------------------------------------------------===// 153 154 /// Returns the operation that owns this result. 155 Operation *OpResult::getOwner() const { 156 // If the result is in-place, the `owner` is the operation. 157 void *owner = ownerAndKind.getPointer(); 158 if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult)) 159 return static_cast<Operation *>(owner); 160 161 // Otherwise, query the trailing result for the owner. 162 return static_cast<TrailingOpResult *>(owner)->getOwner(); 163 } 164 165 /// Return the result number of this result. 166 unsigned OpResult::getResultNumber() const { 167 // If the result is in-place, we can use the kind directly. 168 if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult)) 169 return static_cast<unsigned>(ownerAndKind.getInt()); 170 // Otherwise, query the trailing result. 171 auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer()); 172 return result->getResultNumber(); 173 } 174 175 /// Given a number of operation results, returns the number that need to be 176 /// stored inline. 177 unsigned OpResult::getNumInline(unsigned numResults) { 178 return std::min(numResults, getMaxInlineResults()); 179 } 180 181 /// Given a number of operation results, returns the number that need to be 182 /// stored as trailing. 183 unsigned OpResult::getNumTrailing(unsigned numResults) { 184 // If we can pack all of the results, there is no need for additional storage. 185 unsigned maxInline = getMaxInlineResults(); 186 return numResults <= maxInline ? 0 : numResults - maxInline; 187 } 188 189 //===----------------------------------------------------------------------===// 190 // BlockOperand 191 //===----------------------------------------------------------------------===// 192 193 /// Provide the use list that is attached to the given block. 194 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) { 195 return value; 196 } 197 198 /// Return which operand this is in the operand list. 199 unsigned BlockOperand::getOperandNumber() { 200 return this - &getOwner()->getBlockOperands()[0]; 201 } 202 203 //===----------------------------------------------------------------------===// 204 // OpOperand 205 //===----------------------------------------------------------------------===// 206 207 /// Provide the use list that is attached to the given value. 208 IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) { 209 return value.getUseList(); 210 } 211 212 /// Return the current value being used by this operand. 213 Value OpOperand::get() const { 214 return IROperand<OpOperand, OpaqueValue>::get(); 215 } 216 217 /// Set the operand to the given value. 218 void OpOperand::set(Value value) { 219 IROperand<OpOperand, OpaqueValue>::set(value); 220 } 221 222 /// Return which operand this is in the operand list. 223 unsigned OpOperand::getOperandNumber() { 224 return this - &getOwner()->getOpOperands()[0]; 225 } 226 227 //===----------------------------------------------------------------------===// 228 // OpaqueValue 229 //===----------------------------------------------------------------------===// 230 231 /// Implicit conversion from 'Value'. 232 OpaqueValue::OpaqueValue(Value value) : impl(value.getAsOpaquePointer()) {} 233 234 /// Implicit conversion back to 'Value'. 235 OpaqueValue::operator Value() const { 236 return Value::getFromOpaquePointer(impl); 237 } 238