llvm/mlir/lib/IR/Operation.cpp

//===- Operation.cpp - Operation support code -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "mlir/IR/Operation.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/OperationSupport.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeUtilities.h"
#include "mlir/Interfaces/FoldInterfaces.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include <numeric>
#include <optional>

usingnamespacemlir;

//===----------------------------------------------------------------------===//
// Operation
//===----------------------------------------------------------------------===//

/// Create a new Operation from operation state.
Operation *Operation::create(const OperationState &state) {}

/// Create a new Operation with the specific fields.
Operation *Operation::create(Location location, OperationName name,
                             TypeRange resultTypes, ValueRange operands,
                             NamedAttrList &&attributes,
                             OpaqueProperties properties, BlockRange successors,
                             RegionRange regions) {}

/// Create a new Operation with the specific fields.
Operation *Operation::create(Location location, OperationName name,
                             TypeRange resultTypes, ValueRange operands,
                             NamedAttrList &&attributes,
                             OpaqueProperties properties, BlockRange successors,
                             unsigned numRegions) {}

/// Overload of create that takes an existing DictionaryAttr to avoid
/// unnecessarily uniquing a list of attributes.
Operation *Operation::create(Location location, OperationName name,
                             TypeRange resultTypes, ValueRange operands,
                             DictionaryAttr attributes,
                             OpaqueProperties properties, BlockRange successors,
                             unsigned numRegions) {}

Operation::Operation(Location location, OperationName name, unsigned numResults,
                     unsigned numSuccessors, unsigned numRegions,
                     int fullPropertiesStorageSize, DictionaryAttr attributes,
                     OpaqueProperties properties, bool hasOperandStorage)
    :{}

// Operations are deleted through the destroy() member because they are
// allocated via malloc.
Operation::~Operation() {}

/// Destroy this operation or one of its subclasses.
void Operation::destroy() {}

/// Return true if this operation is a proper ancestor of the `other`
/// operation.
bool Operation::isProperAncestor(Operation *other) {}

/// Replace any uses of 'from' with 'to' within this operation.
void Operation::replaceUsesOfWith(Value from, Value to) {}

/// Replace the current operands of this operation with the ones provided in
/// 'operands'.
void Operation::setOperands(ValueRange operands) {}

/// Replace the operands beginning at 'start' and ending at 'start' + 'length'
/// with the ones provided in 'operands'. 'operands' may be smaller or larger
/// than the range pointed to by 'start'+'length'.
void Operation::setOperands(unsigned start, unsigned length,
                            ValueRange operands) {}

/// Insert the given operands into the operand list at the given 'index'.
void Operation::insertOperands(unsigned index, ValueRange operands) {}

//===----------------------------------------------------------------------===//
// Diagnostics
//===----------------------------------------------------------------------===//

/// Emit an error about fatal conditions with this operation, reporting up to
/// any diagnostic handlers that may be listening.
InFlightDiagnostic Operation::emitError(const Twine &message) {}

/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
InFlightDiagnostic Operation::emitWarning(const Twine &message) {}

/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
InFlightDiagnostic Operation::emitRemark(const Twine &message) {}

DictionaryAttr Operation::getAttrDictionary() {}

void Operation::setAttrs(DictionaryAttr newAttrs) {}
void Operation::setAttrs(ArrayRef<NamedAttribute> newAttrs) {}

std::optional<Attribute> Operation::getInherentAttr(StringRef name) {}

void Operation::setInherentAttr(StringAttr name, Attribute value) {}

Attribute Operation::getPropertiesAsAttribute() {}
LogicalResult Operation::setPropertiesFromAttribute(
    Attribute attr, function_ref<InFlightDiagnostic()> emitError) {}

void Operation::copyProperties(OpaqueProperties rhs) {}

llvm::hash_code Operation::hashProperties() {}

//===----------------------------------------------------------------------===//
// Operation Ordering
//===----------------------------------------------------------------------===//

constexpr unsigned Operation::kInvalidOrderIdx;
constexpr unsigned Operation::kOrderStride;

/// Given an operation 'other' that is within the same parent block, return
/// whether the current operation is before 'other' in the operation list
/// of the parent block.
/// Note: This function has an average complexity of O(1), but worst case may
/// take O(N) where N is the number of operations within the parent block.
bool Operation::isBeforeInBlock(Operation *other) {}

/// Update the order index of this operation of this operation if necessary,
/// potentially recomputing the order of the parent block.
void Operation::updateOrderIfNecessary() {}

//===----------------------------------------------------------------------===//
// ilist_traits for Operation
//===----------------------------------------------------------------------===//

auto llvm::ilist_detail::SpecificNodeAccess<
    typename llvm::ilist_detail::compute_node_options<
        ::mlir::Operation>::type>::getNodePtr(pointer n) -> node_type * {}

auto llvm::ilist_detail::SpecificNodeAccess<
    typename llvm::ilist_detail::compute_node_options<
        ::mlir::Operation>::type>::getNodePtr(const_pointer n)
    -> const node_type * {}

auto llvm::ilist_detail::SpecificNodeAccess<
    typename llvm::ilist_detail::compute_node_options<
        ::mlir::Operation>::type>::getValuePtr(node_type *n) -> pointer {}

auto llvm::ilist_detail::SpecificNodeAccess<
    typename llvm::ilist_detail::compute_node_options<
        ::mlir::Operation>::type>::getValuePtr(const node_type *n)
    -> const_pointer {}

void llvm::ilist_traits<::mlir::Operation>::deleteNode(Operation *op) {}

Block *llvm::ilist_traits<::mlir::Operation>::getContainingBlock() {}

/// This is a trait method invoked when an operation is added to a block.  We
/// keep the block pointer up to date.
void llvm::ilist_traits<::mlir::Operation>::addNodeToList(Operation *op) {}

/// This is a trait method invoked when an operation is removed from a block.
/// We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::Operation>::removeNodeFromList(Operation *op) {}

/// This is a trait method invoked when an operation is moved from one block
/// to another.  We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::Operation>::transferNodesFromList(
    ilist_traits<Operation> &otherList, op_iterator first, op_iterator last) {}

/// Remove this operation (and its descendants) from its Block and delete
/// all of them.
void Operation::erase() {}

/// Remove the operation from its parent block, but don't delete it.
void Operation::remove() {}

/// Unlink this operation from its current block and insert it right before
/// `existingOp` which may be in the same or another block in the same
/// function.
void Operation::moveBefore(Operation *existingOp) {}

/// Unlink this operation from its current basic block and insert it right
/// before `iterator` in the specified basic block.
void Operation::moveBefore(Block *block,
                           llvm::iplist<Operation>::iterator iterator) {}

/// Unlink this operation from its current block and insert it right after
/// `existingOp` which may be in the same or another block in the same function.
void Operation::moveAfter(Operation *existingOp) {}

/// Unlink this operation from its current block and insert it right after
/// `iterator` in the specified block.
void Operation::moveAfter(Block *block,
                          llvm::iplist<Operation>::iterator iterator) {}

/// This drops all operand uses from this operation, which is an essential
/// step in breaking cyclic dependences between references when they are to
/// be deleted.
void Operation::dropAllReferences() {}

/// This drops all uses of any values defined by this operation or its nested
/// regions, wherever they are located.
void Operation::dropAllDefinedValueUses() {}

void Operation::setSuccessor(Block *block, unsigned index) {}

#ifndef NDEBUG
/// Assert that the folded results (in case of values) have the same type as
/// the results of the given op.
static void checkFoldResultTypes(Operation *op,
                                 SmallVectorImpl<OpFoldResult> &results) {
  if (results.empty())
    return;

  for (auto [ofr, opResult] : llvm::zip_equal(results, op->getResults())) {
    if (auto value = dyn_cast<Value>(ofr)) {
      if (value.getType() != opResult.getType()) {
        op->emitOpError() << "folder produced a value of incorrect type: "
                          << value.getType()
                          << ", expected: " << opResult.getType();
        assert(false && "incorrect fold result type");
      }
    }
  }
}
#endif // NDEBUG

/// Attempt to fold this operation using the Op's registered foldHook.
LogicalResult Operation::fold(ArrayRef<Attribute> operands,
                              SmallVectorImpl<OpFoldResult> &results) {}

LogicalResult Operation::fold(SmallVectorImpl<OpFoldResult> &results) {}

/// Emit an error with the op name prefixed, like "'dim' op " which is
/// convenient for verifiers.
InFlightDiagnostic Operation::emitOpError(const Twine &message) {}

//===----------------------------------------------------------------------===//
// Operation Cloning
//===----------------------------------------------------------------------===//

Operation::CloneOptions::CloneOptions()
    :{}

Operation::CloneOptions::CloneOptions(bool cloneRegions, bool cloneOperands)
    :{}

Operation::CloneOptions Operation::CloneOptions::all() {}

Operation::CloneOptions &Operation::CloneOptions::cloneRegions(bool enable) {}

Operation::CloneOptions &Operation::CloneOptions::cloneOperands(bool enable) {}

/// Create a deep copy of this operation but keep the operation regions empty.
/// Operands are remapped using `mapper` (if present), and `mapper` is updated
/// to contain the results. The `mapResults` flag specifies whether the results
/// of the cloned operation should be added to the map.
Operation *Operation::cloneWithoutRegions(IRMapping &mapper) {}

Operation *Operation::cloneWithoutRegions() {}

/// Create a deep copy of this operation, remapping any operands that use
/// values outside of the operation using the map that is provided (leaving
/// them alone if no entry is present).  Replaces references to cloned
/// sub-operations to the corresponding operation that is copied, and adds
/// those mappings to the map.
Operation *Operation::clone(IRMapping &mapper, CloneOptions options) {}

Operation *Operation::clone(CloneOptions options) {}

//===----------------------------------------------------------------------===//
// OpState trait class.
//===----------------------------------------------------------------------===//

// The fallback for the parser is to try for a dialect operation parser.
// Otherwise, reject the custom assembly form.
ParseResult OpState::parse(OpAsmParser &parser, OperationState &result) {}

// The fallback for the printer is to try for a dialect operation printer.
// Otherwise, it prints the generic form.
void OpState::print(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) {}

/// Print an operation name, eliding the dialect prefix if necessary and doesn't
/// lead to ambiguities.
void OpState::printOpName(Operation *op, OpAsmPrinter &p,
                          StringRef defaultDialect) {}

/// Parse properties as a Attribute.
ParseResult OpState::genericParseProperties(OpAsmParser &parser,
                                            Attribute &result) {}

/// Print the properties as a Attribute with names not included within
/// 'elidedProps'
void OpState::genericPrintProperties(OpAsmPrinter &p, Attribute properties,
                                     ArrayRef<StringRef> elidedProps) {}

/// Emit an error about fatal conditions with this operation, reporting up to
/// any diagnostic handlers that may be listening.
InFlightDiagnostic OpState::emitError(const Twine &message) {}

/// Emit an error with the op name prefixed, like "'dim' op " which is
/// convenient for verifiers.
InFlightDiagnostic OpState::emitOpError(const Twine &message) {}

/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
InFlightDiagnostic OpState::emitWarning(const Twine &message) {}

/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
InFlightDiagnostic OpState::emitRemark(const Twine &message) {}

//===----------------------------------------------------------------------===//
// Op Trait implementations
//===----------------------------------------------------------------------===//

LogicalResult
OpTrait::impl::foldCommutative(Operation *op, ArrayRef<Attribute> operands,
                               SmallVectorImpl<OpFoldResult> &results) {}

OpFoldResult OpTrait::impl::foldIdempotent(Operation *op) {}

OpFoldResult OpTrait::impl::foldInvolution(Operation *op) {}

LogicalResult OpTrait::impl::verifyZeroOperands(Operation *op) {}

LogicalResult OpTrait::impl::verifyOneOperand(Operation *op) {}

LogicalResult OpTrait::impl::verifyNOperands(Operation *op,
                                             unsigned numOperands) {}

LogicalResult OpTrait::impl::verifyAtLeastNOperands(Operation *op,
                                                    unsigned numOperands) {}

/// If this is a vector type, or a tensor type, return the scalar element type
/// that it is built around, otherwise return the type unmodified.
static Type getTensorOrVectorElementType(Type type) {}

LogicalResult OpTrait::impl::verifyIsIdempotent(Operation *op) {}

LogicalResult OpTrait::impl::verifyIsInvolution(Operation *op) {}

LogicalResult
OpTrait::impl::verifyOperandsAreSignlessIntegerLike(Operation *op) {}

LogicalResult OpTrait::impl::verifyOperandsAreFloatLike(Operation *op) {}

LogicalResult OpTrait::impl::verifySameTypeOperands(Operation *op) {}

LogicalResult OpTrait::impl::verifyZeroRegions(Operation *op) {}

LogicalResult OpTrait::impl::verifyOneRegion(Operation *op) {}

LogicalResult OpTrait::impl::verifyNRegions(Operation *op,
                                            unsigned numRegions) {}

LogicalResult OpTrait::impl::verifyAtLeastNRegions(Operation *op,
                                                   unsigned numRegions) {}

LogicalResult OpTrait::impl::verifyZeroResults(Operation *op) {}

LogicalResult OpTrait::impl::verifyOneResult(Operation *op) {}

LogicalResult OpTrait::impl::verifyNResults(Operation *op,
                                            unsigned numOperands) {}

LogicalResult OpTrait::impl::verifyAtLeastNResults(Operation *op,
                                                   unsigned numOperands) {}

LogicalResult OpTrait::impl::verifySameOperandsShape(Operation *op) {}

LogicalResult OpTrait::impl::verifySameOperandsAndResultShape(Operation *op) {}

LogicalResult OpTrait::impl::verifySameOperandsElementType(Operation *op) {}

LogicalResult
OpTrait::impl::verifySameOperandsAndResultElementType(Operation *op) {}

LogicalResult OpTrait::impl::verifySameOperandsAndResultType(Operation *op) {}

LogicalResult OpTrait::impl::verifySameOperandsAndResultRank(Operation *op) {}

LogicalResult OpTrait::impl::verifyIsTerminator(Operation *op) {}

static LogicalResult verifyTerminatorSuccessors(Operation *op) {}

LogicalResult OpTrait::impl::verifyZeroSuccessors(Operation *op) {}

LogicalResult OpTrait::impl::verifyOneSuccessor(Operation *op) {}
LogicalResult OpTrait::impl::verifyNSuccessors(Operation *op,
                                               unsigned numSuccessors) {}
LogicalResult OpTrait::impl::verifyAtLeastNSuccessors(Operation *op,
                                                      unsigned numSuccessors) {}

LogicalResult OpTrait::impl::verifyResultsAreBoolLike(Operation *op) {}

LogicalResult OpTrait::impl::verifyResultsAreFloatLike(Operation *op) {}

LogicalResult
OpTrait::impl::verifyResultsAreSignlessIntegerLike(Operation *op) {}

LogicalResult OpTrait::impl::verifyValueSizeAttr(Operation *op,
                                                 StringRef attrName,
                                                 StringRef valueGroupName,
                                                 size_t expectedCount) {}

LogicalResult OpTrait::impl::verifyOperandSizeAttr(Operation *op,
                                                   StringRef attrName) {}

LogicalResult OpTrait::impl::verifyResultSizeAttr(Operation *op,
                                                  StringRef attrName) {}

LogicalResult OpTrait::impl::verifyNoRegionArguments(Operation *op) {}

LogicalResult OpTrait::impl::verifyElementwise(Operation *op) {}

/// Check for any values used by operations regions attached to the
/// specified "IsIsolatedFromAbove" operation defined outside of it.
LogicalResult OpTrait::impl::verifyIsIsolatedFromAbove(Operation *isolatedOp) {}

bool OpTrait::hasElementwiseMappableTraits(Operation *op) {}

//===----------------------------------------------------------------------===//
// Misc. utils
//===----------------------------------------------------------------------===//

/// Insert an operation, generated by `buildTerminatorOp`, at the end of the
/// region's only block if it does not have a terminator already. If the region
/// is empty, insert a new block first. `buildTerminatorOp` should return the
/// terminator operation to insert.
void impl::ensureRegionTerminator(
    Region &region, OpBuilder &builder, Location loc,
    function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp) {}

/// Create a simple OpBuilder and forward to the OpBuilder version of this
/// function.
void impl::ensureRegionTerminator(
    Region &region, Builder &builder, Location loc,
    function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp) {}