xref: /llvm-project/mlir/lib/IR/Value.cpp (revision 26a0b277369adc31b162b1cc38b1a712bc10c1a0)
14c05f8caSChris Lattner //===- Value.cpp - MLIR Value Classes -------------------------------------===//
24c05f8caSChris Lattner //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64c05f8caSChris Lattner //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
84c05f8caSChris Lattner 
94c05f8caSChris Lattner #include "mlir/IR/Value.h"
104beef47bSAlex Zinenko #include "mlir/IR/Block.h"
1109f7a55fSRiver Riddle #include "mlir/IR/BuiltinTypes.h"
129ffdc930SRiver Riddle #include "mlir/IR/Operation.h"
13ad9988f4SAlexander Belyaev #include "llvm/ADT/SmallPtrSet.h"
1448e9ef43SRiver Riddle 
154c05f8caSChris Lattner using namespace mlir;
1648e9ef43SRiver Riddle using namespace mlir::detail;
174c05f8caSChris Lattner 
18f9d91531SRiver Riddle /// If this value is the result of an Operation, return the operation that
19f9d91531SRiver Riddle /// defines it.
getDefiningOp() const20ab46543cSRiver Riddle Operation *Value::getDefiningOp() const {
2168f58812STres Popp   if (auto result = llvm::dyn_cast<OpResult>(*this))
222bdf33ccSRiver Riddle     return result.getOwner();
234c05f8caSChris Lattner   return nullptr;
244c05f8caSChris Lattner }
254c05f8caSChris Lattner 
getLoc() const262bdf33ccSRiver Riddle Location Value::getLoc() const {
27ce502af9SRiver Riddle   if (auto *op = getDefiningOp())
2851f6c0eaSMehdi Amini     return op->getLoc();
294589dd92SRiver Riddle 
3068f58812STres Popp   return llvm::cast<BlockArgument>(*this).getLoc();
3181467f50SChris Lattner }
3281467f50SChris Lattner 
setLoc(Location loc)3381467f50SChris Lattner void Value::setLoc(Location loc) {
3481467f50SChris Lattner   if (auto *op = getDefiningOp())
3581467f50SChris Lattner     return op->setLoc(loc);
3681467f50SChris Lattner 
3768f58812STres Popp   return llvm::cast<BlockArgument>(*this).setLoc(loc);
3851f6c0eaSMehdi Amini }
3951f6c0eaSMehdi Amini 
404beef47bSAlex Zinenko /// Return the Region in which this Value is defined.
getParentRegion()411e429540SRiver Riddle Region *Value::getParentRegion() {
42f29731d1SRiver Riddle   if (auto *op = getDefiningOp())
43f29731d1SRiver Riddle     return op->getParentRegion();
4468f58812STres Popp   return llvm::cast<BlockArgument>(*this).getOwner()->getParent();
454beef47bSAlex Zinenko }
464beef47bSAlex Zinenko 
47469c02d0SRiver Riddle /// Return the Block in which this Value is defined.
getParentBlock()48469c02d0SRiver Riddle Block *Value::getParentBlock() {
49469c02d0SRiver Riddle   if (Operation *op = getDefiningOp())
50469c02d0SRiver Riddle     return op->getBlock();
5168f58812STres Popp   return llvm::cast<BlockArgument>(*this).getOwner();
52469c02d0SRiver Riddle }
53469c02d0SRiver Riddle 
544c05f8caSChris Lattner //===----------------------------------------------------------------------===//
550d6ebb4fSRiver Riddle // Value::UseLists
560d6ebb4fSRiver Riddle //===----------------------------------------------------------------------===//
570d6ebb4fSRiver Riddle 
580d6ebb4fSRiver Riddle /// Replace all uses of 'this' value with the new value, updating anything in
59ad9988f4SAlexander Belyaev /// the IR that uses 'this' to use the other value instead except if the user is
60ad9988f4SAlexander Belyaev /// listed in 'exceptions' .
replaceAllUsesExcept(Value newValue,const SmallPtrSetImpl<Operation * > & exceptions)61ad9988f4SAlexander Belyaev void Value::replaceAllUsesExcept(
62*26a0b277SMehdi Amini     Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) {
6312874e93SSean Silva   for (OpOperand &use : llvm::make_early_inc_range(getUses())) {
64ad9988f4SAlexander Belyaev     if (exceptions.count(use.getOwner()) == 0)
65ad9988f4SAlexander Belyaev       use.set(newValue);
66ad9988f4SAlexander Belyaev   }
67ad9988f4SAlexander Belyaev }
68ad9988f4SAlexander Belyaev 
6912874e93SSean Silva /// Replace all uses of 'this' value with 'newValue', updating anything in the
7012874e93SSean Silva /// IR that uses 'this' to use the other value instead except if the user is
7112874e93SSean Silva /// 'exceptedUser'.
replaceAllUsesExcept(Value newValue,Operation * exceptedUser)72*26a0b277SMehdi Amini void Value::replaceAllUsesExcept(Value newValue, Operation *exceptedUser) {
7312874e93SSean Silva   for (OpOperand &use : llvm::make_early_inc_range(getUses())) {
7412874e93SSean Silva     if (use.getOwner() != exceptedUser)
7512874e93SSean Silva       use.set(newValue);
7612874e93SSean Silva   }
7712874e93SSean Silva }
7812874e93SSean Silva 
790816de16SRiver Riddle /// Replace all uses of 'this' value with 'newValue' if the given callback
800816de16SRiver Riddle /// returns true.
replaceUsesWithIf(Value newValue,function_ref<bool (OpOperand &)> shouldReplace)810816de16SRiver Riddle void Value::replaceUsesWithIf(Value newValue,
820816de16SRiver Riddle                               function_ref<bool(OpOperand &)> shouldReplace) {
830816de16SRiver Riddle   for (OpOperand &use : llvm::make_early_inc_range(getUses()))
840816de16SRiver Riddle     if (shouldReplace(use))
850816de16SRiver Riddle       use.set(newValue);
860816de16SRiver Riddle }
870816de16SRiver Riddle 
88469c02d0SRiver Riddle /// Returns true if the value is used outside of the given block.
isUsedOutsideOfBlock(Block * block) const89*26a0b277SMehdi Amini bool Value::isUsedOutsideOfBlock(Block *block) const {
90469c02d0SRiver Riddle   return llvm::any_of(getUsers(), [block](Operation *user) {
91469c02d0SRiver Riddle     return user->getBlock() != block;
92469c02d0SRiver Riddle   });
93469c02d0SRiver Riddle }
94469c02d0SRiver Riddle 
9561278191SMatteo Franciolini /// Shuffles the use-list order according to the provided indices.
shuffleUseList(ArrayRef<unsigned> indices)9661278191SMatteo Franciolini void Value::shuffleUseList(ArrayRef<unsigned> indices) {
9761278191SMatteo Franciolini   getImpl()->shuffleUseList(indices);
9861278191SMatteo Franciolini }
9961278191SMatteo Franciolini 
1000d6ebb4fSRiver Riddle //===----------------------------------------------------------------------===//
101fd01d862SRiver Riddle // OpResult
102fd01d862SRiver Riddle //===----------------------------------------------------------------------===//
103fd01d862SRiver Riddle 
1043dfa8614SRiver Riddle /// Returns the parent operation of this trailing result.
getOwner() const1053dfa8614SRiver Riddle Operation *OpResultImpl::getOwner() const {
1063dfa8614SRiver Riddle   // We need to do some arithmetic to get the operation pointer. Results are
1073dfa8614SRiver Riddle   // stored in reverse order before the operation, so move the trailing owner up
1083dfa8614SRiver Riddle   // to the start of the array. A rough diagram of the memory layout is:
1093dfa8614SRiver Riddle   //
1103dfa8614SRiver Riddle   // | Out-of-Line results | Inline results | Operation |
1113dfa8614SRiver Riddle   //
1123dfa8614SRiver Riddle   // Given that the results are reverse order we use the result number to know
1133dfa8614SRiver Riddle   // how far to jump to get to the operation. So if we are currently the 0th
1143dfa8614SRiver Riddle   // result, the layout would be:
1153dfa8614SRiver Riddle   //
1163dfa8614SRiver Riddle   // | Inline result 0 | Operation
1173dfa8614SRiver Riddle   //
1183dfa8614SRiver Riddle   // ^-- To get the base address of the operation, we add the result count + 1.
1193dfa8614SRiver Riddle   if (const auto *result = dyn_cast<InlineOpResult>(this)) {
1203dfa8614SRiver Riddle     result += result->getResultNumber() + 1;
1213dfa8614SRiver Riddle     return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(result));
122fd01d862SRiver Riddle   }
123fd01d862SRiver Riddle 
1243dfa8614SRiver Riddle   // Out-of-line results are stored in an array just before the inline results.
1253dfa8614SRiver Riddle   const OutOfLineOpResult *outOfLineIt = (const OutOfLineOpResult *)(this);
1263dfa8614SRiver Riddle   outOfLineIt += (outOfLineIt->outOfLineIndex + 1);
1273dfa8614SRiver Riddle 
1283dfa8614SRiver Riddle   // Move the owner past the inline results to get to the operation.
1293dfa8614SRiver Riddle   const auto *inlineIt = reinterpret_cast<const InlineOpResult *>(outOfLineIt);
1303dfa8614SRiver Riddle   inlineIt += getMaxInlineResults();
1313dfa8614SRiver Riddle   return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(inlineIt));
1323dfa8614SRiver Riddle }
1333dfa8614SRiver Riddle 
getNextResultAtOffset(intptr_t offset)1343dfa8614SRiver Riddle OpResultImpl *OpResultImpl::getNextResultAtOffset(intptr_t offset) {
1353dfa8614SRiver Riddle   if (offset == 0)
1363dfa8614SRiver Riddle     return this;
1373dfa8614SRiver Riddle   // We need to do some arithmetic to get the next result given that results are
1383dfa8614SRiver Riddle   // in reverse order, and that we need to account for the different types of
1393dfa8614SRiver Riddle   // results. As a reminder, the rough diagram of the memory layout is:
1403dfa8614SRiver Riddle   //
1413dfa8614SRiver Riddle   // | Out-of-Line results | Inline results | Operation |
1423dfa8614SRiver Riddle   //
1433dfa8614SRiver Riddle   // So an example operation with two results would look something like:
1443dfa8614SRiver Riddle   //
1453dfa8614SRiver Riddle   // | Inline result 1 | Inline result 0 | Operation |
1463dfa8614SRiver Riddle   //
1473dfa8614SRiver Riddle 
1483dfa8614SRiver Riddle   // Handle the case where this result is an inline result.
1493dfa8614SRiver Riddle   OpResultImpl *result = this;
1503dfa8614SRiver Riddle   if (auto *inlineResult = dyn_cast<InlineOpResult>(this)) {
1513dfa8614SRiver Riddle     // Check to see how many results there are after this one before the start
1523dfa8614SRiver Riddle     // of the out-of-line results. If the desired offset is less than the number
1533dfa8614SRiver Riddle     // remaining, we can directly use the offset from the current result
1543dfa8614SRiver Riddle     // pointer. The following diagrams highlight the two situations.
1553dfa8614SRiver Riddle     //
1563dfa8614SRiver Riddle     // | Out-of-Line results | Inline results | Operation |
1573dfa8614SRiver Riddle     //                                    ^- Say we are here.
1583dfa8614SRiver Riddle     //                           ^- If our destination is here, we can use the
1593dfa8614SRiver Riddle     //                              offset directly.
1603dfa8614SRiver Riddle     //
1613dfa8614SRiver Riddle     intptr_t leftBeforeTrailing =
1623dfa8614SRiver Riddle         getMaxInlineResults() - inlineResult->getResultNumber() - 1;
1633dfa8614SRiver Riddle     if (leftBeforeTrailing >= offset)
1643dfa8614SRiver Riddle       return inlineResult - offset;
1653dfa8614SRiver Riddle 
1663dfa8614SRiver Riddle     // Otherwise, adjust the current result pointer to the end (start in memory)
1673dfa8614SRiver Riddle     // of the inline result array.
1683dfa8614SRiver Riddle     //
1693dfa8614SRiver Riddle     // | Out-of-Line results | Inline results | Operation |
1703dfa8614SRiver Riddle     //                                    ^- Say we are here.
1713dfa8614SRiver Riddle     //                  ^- If our destination is here, we need to first jump to
1723dfa8614SRiver Riddle     //                     the end (start in memory) of the inline result array.
1733dfa8614SRiver Riddle     //
1743dfa8614SRiver Riddle     result = inlineResult - leftBeforeTrailing;
1753dfa8614SRiver Riddle     offset -= leftBeforeTrailing;
1763dfa8614SRiver Riddle   }
1773dfa8614SRiver Riddle 
1783dfa8614SRiver Riddle   // If we land here, the current result is an out-of-line result and we can
1793dfa8614SRiver Riddle   // offset directly.
1803dfa8614SRiver Riddle   return reinterpret_cast<OutOfLineOpResult *>(result) - offset;
18148e9ef43SRiver Riddle }
18248e9ef43SRiver Riddle 
18348e9ef43SRiver Riddle /// Given a number of operation results, returns the number that need to be
18448e9ef43SRiver Riddle /// stored inline.
getNumInline(unsigned numResults)18548e9ef43SRiver Riddle unsigned OpResult::getNumInline(unsigned numResults) {
1863dfa8614SRiver Riddle   return std::min(numResults, OpResultImpl::getMaxInlineResults());
187fd01d862SRiver Riddle }
188fd01d862SRiver Riddle 
189fd01d862SRiver Riddle /// Given a number of operation results, returns the number that need to be
190fd01d862SRiver Riddle /// stored as trailing.
getNumTrailing(unsigned numResults)191fd01d862SRiver Riddle unsigned OpResult::getNumTrailing(unsigned numResults) {
192fd01d862SRiver Riddle   // If we can pack all of the results, there is no need for additional storage.
1933dfa8614SRiver Riddle   unsigned maxInline = OpResultImpl::getMaxInlineResults();
19448e9ef43SRiver Riddle   return numResults <= maxInline ? 0 : numResults - maxInline;
195fd01d862SRiver Riddle }
196fd01d862SRiver Riddle 
197fd01d862SRiver Riddle //===----------------------------------------------------------------------===//
198f83a8efeSRiver Riddle // BlockOperand
199f83a8efeSRiver Riddle //===----------------------------------------------------------------------===//
200f83a8efeSRiver Riddle 
2010d6ebb4fSRiver Riddle /// Provide the use list that is attached to the given block.
getUseList(Block * value)2020d6ebb4fSRiver Riddle IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
2030d6ebb4fSRiver Riddle   return value;
2040d6ebb4fSRiver Riddle }
205f83a8efeSRiver Riddle 
206f83a8efeSRiver Riddle /// Return which operand this is in the operand list.
getOperandNumber()207f83a8efeSRiver Riddle unsigned BlockOperand::getOperandNumber() {
208f83a8efeSRiver Riddle   return this - &getOwner()->getBlockOperands()[0];
209f83a8efeSRiver Riddle }
210f83a8efeSRiver Riddle 
211f83a8efeSRiver Riddle //===----------------------------------------------------------------------===//
212f83a8efeSRiver Riddle // OpOperand
213f83a8efeSRiver Riddle //===----------------------------------------------------------------------===//
214f83a8efeSRiver Riddle 
215f83a8efeSRiver Riddle /// Return which operand this is in the operand list.
getOperandNumber()216f83a8efeSRiver Riddle unsigned OpOperand::getOperandNumber() {
217f83a8efeSRiver Riddle   return this - &getOwner()->getOpOperands()[0];
218f83a8efeSRiver Riddle }
219