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 /// If this value is the result of an Operation, return the operation that 19 /// defines it. 20 Operation *Value::getDefiningOp() const { 21 if (auto result = dyn_cast<OpResult>()) 22 return result.getOwner(); 23 return nullptr; 24 } 25 26 Location Value::getLoc() const { 27 if (auto *op = getDefiningOp()) 28 return op->getLoc(); 29 30 return cast<BlockArgument>().getLoc(); 31 } 32 33 void Value::setLoc(Location loc) { 34 if (auto *op = getDefiningOp()) 35 return op->setLoc(loc); 36 37 return cast<BlockArgument>().setLoc(loc); 38 } 39 40 /// Return the Region in which this Value is defined. 41 Region *Value::getParentRegion() { 42 if (auto *op = getDefiningOp()) 43 return op->getParentRegion(); 44 return cast<BlockArgument>().getOwner()->getParent(); 45 } 46 47 /// Return the Block in which this Value is defined. 48 Block *Value::getParentBlock() { 49 if (Operation *op = getDefiningOp()) 50 return op->getBlock(); 51 return cast<BlockArgument>().getOwner(); 52 } 53 54 //===----------------------------------------------------------------------===// 55 // Value::UseLists 56 //===----------------------------------------------------------------------===// 57 58 /// Replace all uses of 'this' value with the new value, updating anything in 59 /// the IR that uses 'this' to use the other value instead except if the user is 60 /// listed in 'exceptions' . 61 void Value::replaceAllUsesExcept( 62 Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const { 63 for (OpOperand &use : llvm::make_early_inc_range(getUses())) { 64 if (exceptions.count(use.getOwner()) == 0) 65 use.set(newValue); 66 } 67 } 68 69 /// Replace all uses of 'this' value with 'newValue', updating anything in the 70 /// IR that uses 'this' to use the other value instead except if the user is 71 /// 'exceptedUser'. 72 void Value::replaceAllUsesExcept(Value newValue, 73 Operation *exceptedUser) const { 74 for (OpOperand &use : llvm::make_early_inc_range(getUses())) { 75 if (use.getOwner() != exceptedUser) 76 use.set(newValue); 77 } 78 } 79 80 /// Replace all uses of 'this' value with 'newValue' if the given callback 81 /// returns true. 82 void Value::replaceUsesWithIf(Value newValue, 83 function_ref<bool(OpOperand &)> shouldReplace) { 84 for (OpOperand &use : llvm::make_early_inc_range(getUses())) 85 if (shouldReplace(use)) 86 use.set(newValue); 87 } 88 89 /// Returns true if the value is used outside of the given block. 90 bool Value::isUsedOutsideOfBlock(Block *block) { 91 return llvm::any_of(getUsers(), [block](Operation *user) { 92 return user->getBlock() != block; 93 }); 94 } 95 96 //===----------------------------------------------------------------------===// 97 // OpResult 98 //===----------------------------------------------------------------------===// 99 100 /// Returns the parent operation of this trailing result. 101 Operation *OpResultImpl::getOwner() const { 102 // We need to do some arithmetic to get the operation pointer. Results are 103 // stored in reverse order before the operation, so move the trailing owner up 104 // to the start of the array. A rough diagram of the memory layout is: 105 // 106 // | Out-of-Line results | Inline results | Operation | 107 // 108 // Given that the results are reverse order we use the result number to know 109 // how far to jump to get to the operation. So if we are currently the 0th 110 // result, the layout would be: 111 // 112 // | Inline result 0 | Operation 113 // 114 // ^-- To get the base address of the operation, we add the result count + 1. 115 if (const auto *result = dyn_cast<InlineOpResult>(this)) { 116 result += result->getResultNumber() + 1; 117 return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(result)); 118 } 119 120 // Out-of-line results are stored in an array just before the inline results. 121 const OutOfLineOpResult *outOfLineIt = (const OutOfLineOpResult *)(this); 122 outOfLineIt += (outOfLineIt->outOfLineIndex + 1); 123 124 // Move the owner past the inline results to get to the operation. 125 const auto *inlineIt = reinterpret_cast<const InlineOpResult *>(outOfLineIt); 126 inlineIt += getMaxInlineResults(); 127 return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(inlineIt)); 128 } 129 130 OpResultImpl *OpResultImpl::getNextResultAtOffset(intptr_t offset) { 131 if (offset == 0) 132 return this; 133 // We need to do some arithmetic to get the next result given that results are 134 // in reverse order, and that we need to account for the different types of 135 // results. As a reminder, the rough diagram of the memory layout is: 136 // 137 // | Out-of-Line results | Inline results | Operation | 138 // 139 // So an example operation with two results would look something like: 140 // 141 // | Inline result 1 | Inline result 0 | Operation | 142 // 143 144 // Handle the case where this result is an inline result. 145 OpResultImpl *result = this; 146 if (auto *inlineResult = dyn_cast<InlineOpResult>(this)) { 147 // Check to see how many results there are after this one before the start 148 // of the out-of-line results. If the desired offset is less than the number 149 // remaining, we can directly use the offset from the current result 150 // pointer. The following diagrams highlight the two situations. 151 // 152 // | Out-of-Line results | Inline results | Operation | 153 // ^- Say we are here. 154 // ^- If our destination is here, we can use the 155 // offset directly. 156 // 157 intptr_t leftBeforeTrailing = 158 getMaxInlineResults() - inlineResult->getResultNumber() - 1; 159 if (leftBeforeTrailing >= offset) 160 return inlineResult - offset; 161 162 // Otherwise, adjust the current result pointer to the end (start in memory) 163 // of the inline result array. 164 // 165 // | Out-of-Line results | Inline results | Operation | 166 // ^- Say we are here. 167 // ^- If our destination is here, we need to first jump to 168 // the end (start in memory) of the inline result array. 169 // 170 result = inlineResult - leftBeforeTrailing; 171 offset -= leftBeforeTrailing; 172 } 173 174 // If we land here, the current result is an out-of-line result and we can 175 // offset directly. 176 return reinterpret_cast<OutOfLineOpResult *>(result) - offset; 177 } 178 179 /// Given a number of operation results, returns the number that need to be 180 /// stored inline. 181 unsigned OpResult::getNumInline(unsigned numResults) { 182 return std::min(numResults, OpResultImpl::getMaxInlineResults()); 183 } 184 185 /// Given a number of operation results, returns the number that need to be 186 /// stored as trailing. 187 unsigned OpResult::getNumTrailing(unsigned numResults) { 188 // If we can pack all of the results, there is no need for additional storage. 189 unsigned maxInline = OpResultImpl::getMaxInlineResults(); 190 return numResults <= maxInline ? 0 : numResults - maxInline; 191 } 192 193 //===----------------------------------------------------------------------===// 194 // BlockOperand 195 //===----------------------------------------------------------------------===// 196 197 /// Provide the use list that is attached to the given block. 198 IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) { 199 return value; 200 } 201 202 /// Return which operand this is in the operand list. 203 unsigned BlockOperand::getOperandNumber() { 204 return this - &getOwner()->getBlockOperands()[0]; 205 } 206 207 //===----------------------------------------------------------------------===// 208 // OpOperand 209 //===----------------------------------------------------------------------===// 210 211 /// Return which operand this is in the operand list. 212 unsigned OpOperand::getOperandNumber() { 213 return this - &getOwner()->getOpOperands()[0]; 214 } 215 216