MLIR 22.0.0git
Value.cpp
Go to the documentation of this file.
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
13using namespace mlir;
14using namespace mlir::detail;
15
16/// If this value is the result of an Operation, return the operation that
17/// defines it.
19 if (auto result = llvm::dyn_cast<OpResult>(*this))
20 return result.getOwner();
21 return nullptr;
22}
23
25 if (auto *op = getDefiningOp())
26 return op->getLoc();
27
28 return llvm::cast<BlockArgument>(*this).getLoc();
29}
30
32 if (auto *op = getDefiningOp())
33 return op->setLoc(loc);
34
35 return llvm::cast<BlockArgument>(*this).setLoc(loc);
36}
37
38/// Return the Region in which this Value is defined.
40 if (auto *op = getDefiningOp())
41 return op->getParentRegion();
42 return llvm::cast<BlockArgument>(*this).getOwner()->getParent();
43}
44
45/// Return the Block in which this Value is defined.
47 if (Operation *op = getDefiningOp())
48 return op->getBlock();
49 return llvm::cast<BlockArgument>(*this).getOwner();
50}
51
52unsigned Value::getNumUses() const {
53 return (unsigned)std::distance(use_begin(), use_end());
54}
55
56bool Value::hasNUses(unsigned n) const {
57 return hasNItems(use_begin(), use_end(), n);
58}
59
60bool Value::hasNUsesOrMore(unsigned n) const {
61 return hasNItemsOrMore(use_begin(), use_end(), n);
62}
63
64//===----------------------------------------------------------------------===//
65// Value::UseLists
66//===----------------------------------------------------------------------===//
67
68/// Replace all uses of 'this' value with the new value, updating anything in
69/// the IR that uses 'this' to use the other value instead except if the user is
70/// listed in 'exceptions' .
72 Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) {
73 for (OpOperand &use : llvm::make_early_inc_range(getUses())) {
74 if (exceptions.count(use.getOwner()) == 0)
75 use.set(newValue);
76 }
77}
78
79/// Replace all uses of 'this' value with 'newValue', updating anything in the
80/// IR that uses 'this' to use the other value instead except if the user is
81/// 'exceptedUser'.
82void Value::replaceAllUsesExcept(Value newValue, Operation *exceptedUser) {
83 for (OpOperand &use : llvm::make_early_inc_range(getUses())) {
84 if (use.getOwner() != exceptedUser)
85 use.set(newValue);
86 }
87}
88
89/// Replace all uses of 'this' value with 'newValue' if the given callback
90/// returns true.
92 function_ref<bool(OpOperand &)> shouldReplace) {
93 for (OpOperand &use : llvm::make_early_inc_range(getUses()))
94 if (shouldReplace(use))
95 use.set(newValue);
96}
97
98/// Returns true if the value is used outside of the given block.
100 return llvm::any_of(getUsers(), [block](Operation *user) {
101 return user->getBlock() != block;
102 });
103}
104
105/// Shuffles the use-list order according to the provided indices.
109
110//===----------------------------------------------------------------------===//
111// OpResult
112//===----------------------------------------------------------------------===//
113
114/// Returns the parent operation of this trailing result.
116 // We need to do some arithmetic to get the operation pointer. Results are
117 // stored in reverse order before the operation, so move the trailing owner up
118 // to the start of the array. A rough diagram of the memory layout is:
119 //
120 // | Out-of-Line results | Inline results | Operation |
121 //
122 // Given that the results are reverse order we use the result number to know
123 // how far to jump to get to the operation. So if we are currently the 0th
124 // result, the layout would be:
125 //
126 // | Inline result 0 | Operation
127 //
128 // ^-- To get the base address of the operation, we add the result count + 1.
129 if (const auto *result = dyn_cast<InlineOpResult>(this)) {
130 result += result->getResultNumber() + 1;
131 return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(result));
132 }
133
134 // Out-of-line results are stored in an array just before the inline results.
135 const OutOfLineOpResult *outOfLineIt = (const OutOfLineOpResult *)(this);
136 outOfLineIt += (outOfLineIt->outOfLineIndex + 1);
137
138 // Move the owner past the inline results to get to the operation.
139 const auto *inlineIt = reinterpret_cast<const InlineOpResult *>(outOfLineIt);
140 inlineIt += getMaxInlineResults();
141 return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(inlineIt));
142}
143
145 if (offset == 0)
146 return this;
147 // We need to do some arithmetic to get the next result given that results are
148 // in reverse order, and that we need to account for the different types of
149 // results. As a reminder, the rough diagram of the memory layout is:
150 //
151 // | Out-of-Line results | Inline results | Operation |
152 //
153 // So an example operation with two results would look something like:
154 //
155 // | Inline result 1 | Inline result 0 | Operation |
156 //
157
158 // Handle the case where this result is an inline result.
159 OpResultImpl *result = this;
160 if (auto *inlineResult = dyn_cast<InlineOpResult>(this)) {
161 // Check to see how many results there are after this one before the start
162 // of the out-of-line results. If the desired offset is less than the number
163 // remaining, we can directly use the offset from the current result
164 // pointer. The following diagrams highlight the two situations.
165 //
166 // | Out-of-Line results | Inline results | Operation |
167 // ^- Say we are here.
168 // ^- If our destination is here, we can use the
169 // offset directly.
170 //
171 intptr_t leftBeforeTrailing =
172 getMaxInlineResults() - inlineResult->getResultNumber() - 1;
173 if (leftBeforeTrailing >= offset)
174 return inlineResult - offset;
175
176 // Otherwise, adjust the current result pointer to the end (start in memory)
177 // of the inline result array.
178 //
179 // | Out-of-Line results | Inline results | Operation |
180 // ^- Say we are here.
181 // ^- If our destination is here, we need to first jump to
182 // the end (start in memory) of the inline result array.
183 //
184 result = inlineResult - leftBeforeTrailing;
185 offset -= leftBeforeTrailing;
186 }
187
188 // If we land here, the current result is an out-of-line result and we can
189 // offset directly.
190 return reinterpret_cast<OutOfLineOpResult *>(result) - offset;
191}
192
193/// Given a number of operation results, returns the number that need to be
194/// stored inline.
195unsigned OpResult::getNumInline(unsigned numResults) {
196 return std::min(numResults, OpResultImpl::getMaxInlineResults());
197}
198
199/// Given a number of operation results, returns the number that need to be
200/// stored as trailing.
201unsigned OpResult::getNumTrailing(unsigned numResults) {
202 // If we can pack all of the results, there is no need for additional storage.
203 unsigned maxInline = OpResultImpl::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.
215
216/// Return which operand this is in the operand list.
218 return this - &getOwner()->getBlockOperands()[0];
219}
220
221//===----------------------------------------------------------------------===//
222// OpOperand
223//===----------------------------------------------------------------------===//
224
225/// Return which operand this is in the operand list.
227 return this - &getOwner()->getOpOperands()[0];
228}
unsigned getOperandNumber()
Return which operand this is in the BlockOperand list of the Operation.
Definition Value.cpp:217
static IRObjectWithUseList< BlockOperand > * getUseList(Block *value)
Provide the use list that is attached to the given block.
Definition Value.cpp:212
Block represents an ordered list of Operations.
Definition Block.h:33
This class represents a single IR object that contains a use list.
void shuffleUseList(ArrayRef< unsigned > indices)
Shuffle the use-list chain according to the provided indices vector, which need to represent a valid ...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class represents an operand of an operation.
Definition Value.h:257
unsigned getOperandNumber()
Return which operand this is in the OpOperand list of the Operation.
Definition Value.cpp:226
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
MutableArrayRef< BlockOperand > getBlockOperands()
Definition Operation.h:695
Block * getBlock()
Returns the operation block that contains this operation.
Definition Operation.h:213
MutableArrayRef< OpOperand > getOpOperands()
Definition Operation.h:383
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Region * getParentRegion()
Return the region containing this region or nullptr if the region is attached to a top-level operatio...
Definition Region.cpp:45
constexpr Value(detail::ValueImpl *impl=nullptr)
Definition Value.h:98
use_iterator use_end() const
Definition Value.h:185
void setLoc(Location loc)
Definition Value.cpp:31
bool hasNUsesOrMore(unsigned n) const
Return true if this value has n uses or more.
Definition Value.cpp:60
detail::ValueImpl * getImpl() const
Definition Value.h:237
void replaceUsesWithIf(Value newValue, function_ref< bool(OpOperand &)> shouldReplace)
Replace all uses of 'this' value with 'newValue' if the given callback returns true.
Definition Value.cpp:91
void shuffleUseList(ArrayRef< unsigned > indices)
Shuffle the use list order according to the provided indices.
Definition Value.cpp:106
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
Definition Value.h:188
Block * getParentBlock()
Return the Block in which this Value is defined.
Definition Value.cpp:46
void replaceAllUsesExcept(Value newValue, const SmallPtrSetImpl< Operation * > &exceptions)
Replace all uses of 'this' value with 'newValue', updating anything in the IR that uses 'this' to use...
Definition Value.cpp:71
unsigned getNumUses() const
This method computes the number of uses of this Value.
Definition Value.cpp:52
bool hasNUses(unsigned n) const
Return true if this Value has exactly n uses.
Definition Value.cpp:56
user_range getUsers() const
Definition Value.h:218
bool isUsedOutsideOfBlock(Block *block) const
Returns true if the value is used outside of the given block.
Definition Value.cpp:99
Location getLoc() const
Return the location of this value.
Definition Value.cpp:24
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
Region * getParentRegion()
Return the Region in which this Value is defined.
Definition Value.cpp:39
use_iterator use_begin() const
Definition Value.h:184
Operation * getOwner() const
Return the owner of this operand.
Definition UseDefLists.h:38
This class provides the implementation for an operation result.
Definition Value.h:358
OpResultImpl * getNextResultAtOffset(intptr_t offset)
Returns the next operation result at offset after this result.
Definition Value.cpp:144
Operation * getOwner() const
Returns the parent operation of this result.
Definition Value.cpp:115
static unsigned getMaxInlineResults()
Returns the maximum number of results that can be stored inline.
Definition Value.h:380
uint64_t outOfLineIndex
The trailing result number, or the offset from the beginning of the OutOfLineOpResult array.
Definition Value.h:421
@ OutOfLineOpResult
The next kind represents a 'out-of-line' operation result.
Definition Value.h:55
@ InlineOpResult
The first N kinds are all inline operation results.
Definition Value.h:50
AttrTypeReplacer.
Include the generated interface declarations.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152