brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · fa550e4 Raw
229 lines · cpp
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-exception6//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 that17/// defines it.18Operation *Value::getDefiningOp() const {19  if (auto result = llvm::dyn_cast<OpResult>(*this))20    return result.getOwner();21  return nullptr;22}23 24Location Value::getLoc() const {25  if (auto *op = getDefiningOp())26    return op->getLoc();27 28  return llvm::cast<BlockArgument>(*this).getLoc();29}30 31void Value::setLoc(Location loc) {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.39Region *Value::getParentRegion() {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.46Block *Value::getParentBlock() {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::UseLists66//===----------------------------------------------------------------------===//67 68/// Replace all uses of 'this' value with the new value, updating anything in69/// the IR that uses 'this' to use the other value instead except if the user is70/// listed in 'exceptions' .71void Value::replaceAllUsesExcept(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 the80/// IR that uses 'this' to use the other value instead except if the user is81/// '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 callback90/// returns true.91void Value::replaceUsesWithIf(Value newValue,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.99bool Value::isUsedOutsideOfBlock(Block *block) const {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.106void Value::shuffleUseList(ArrayRef<unsigned> indices) {107  getImpl()->shuffleUseList(indices);108}109 110//===----------------------------------------------------------------------===//111// OpResult112//===----------------------------------------------------------------------===//113 114/// Returns the parent operation of this trailing result.115Operation *OpResultImpl::getOwner() const {116  // We need to do some arithmetic to get the operation pointer. Results are117  // stored in reverse order before the operation, so move the trailing owner up118  // 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 know123  // how far to jump to get to the operation. So if we are currently the 0th124  // result, the layout would be:125  //126  // | Inline result 0 | Operation127  //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 144OpResultImpl *OpResultImpl::getNextResultAtOffset(intptr_t offset) {145  if (offset == 0)146    return this;147  // We need to do some arithmetic to get the next result given that results are148  // in reverse order, and that we need to account for the different types of149  // 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 start162    // of the out-of-line results. If the desired offset is less than the number163    // remaining, we can directly use the offset from the current result164    // 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 the169    //                              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 to182    //                     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 can189  // offset directly.190  return reinterpret_cast<OutOfLineOpResult *>(result) - offset;191}192 193/// Given a number of operation results, returns the number that need to be194/// 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 be200/// 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// BlockOperand209//===----------------------------------------------------------------------===//210 211/// Provide the use list that is attached to the given block.212IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {213  return value;214}215 216/// Return which operand this is in the operand list.217unsigned BlockOperand::getOperandNumber() {218  return this - &getOwner()->getBlockOperands()[0];219}220 221//===----------------------------------------------------------------------===//222// OpOperand223//===----------------------------------------------------------------------===//224 225/// Return which operand this is in the operand list.226unsigned OpOperand::getOperandNumber() {227  return this - &getOwner()->getOpOperands()[0];228}229