blob: 77be1f480eacf4dab7174dd29f3d793db73e374d [file] [log] [blame] [edit]
//===-- mlir-c/Rewrite.h - Helpers for C API to Rewrites ----------*- C -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This header declares the registration and creation method for
// rewrite patterns.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_C_REWRITE_H
#define MLIR_C_REWRITE_H
#include "mlir-c/IR.h"
#include "mlir-c/Support.h"
#include "mlir/Config/mlir-config.h"
#ifdef __cplusplus
extern "C" {
#endif
//===----------------------------------------------------------------------===//
/// Opaque type declarations (see mlir-c/IR.h for more details).
//===----------------------------------------------------------------------===//
#define DEFINE_C_API_STRUCT(name, storage) \
struct name { \
storage *ptr; \
}; \
typedef struct name name
DEFINE_C_API_STRUCT(MlirRewriterBase, void);
DEFINE_C_API_STRUCT(MlirFrozenRewritePatternSet, void);
DEFINE_C_API_STRUCT(MlirGreedyRewriteDriverConfig, void);
DEFINE_C_API_STRUCT(MlirRewritePatternSet, void);
DEFINE_C_API_STRUCT(MlirPatternRewriter, void);
//===----------------------------------------------------------------------===//
/// RewriterBase API inherited from OpBuilder
//===----------------------------------------------------------------------===//
/// Get the MLIR context referenced by the rewriter.
MLIR_CAPI_EXPORTED MlirContext
mlirRewriterBaseGetContext(MlirRewriterBase rewriter);
//===----------------------------------------------------------------------===//
/// Insertion points methods
//===----------------------------------------------------------------------===//
// These do not include functions using Block::iterator or Region::iterator, as
// they are not exposed by the C API yet. Similarly for methods using
// `InsertPoint` directly.
/// Reset the insertion point to no location. Creating an operation without a
/// set insertion point is an error, but this can still be useful when the
/// current insertion point a builder refers to is being removed.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseClearInsertionPoint(MlirRewriterBase rewriter);
/// Sets the insertion point to the specified operation, which will cause
/// subsequent insertions to go right before it.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseSetInsertionPointBefore(MlirRewriterBase rewriter,
MlirOperation op);
/// Sets the insertion point to the node after the specified operation, which
/// will cause subsequent insertions to go right after it.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseSetInsertionPointAfter(MlirRewriterBase rewriter,
MlirOperation op);
/// Sets the insertion point to the node after the specified value. If value
/// has a defining operation, sets the insertion point to the node after such
/// defining operation. This will cause subsequent insertions to go right
/// after it. Otherwise, value is a BlockArgument. Sets the insertion point to
/// the start of its block.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseSetInsertionPointAfterValue(MlirRewriterBase rewriter,
MlirValue value);
/// Sets the insertion point to the start of the specified block.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseSetInsertionPointToStart(MlirRewriterBase rewriter,
MlirBlock block);
/// Sets the insertion point to the end of the specified block.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseSetInsertionPointToEnd(MlirRewriterBase rewriter,
MlirBlock block);
/// Return the block the current insertion point belongs to. Note that the
/// insertion point is not necessarily the end of the block.
MLIR_CAPI_EXPORTED MlirBlock
mlirRewriterBaseGetInsertionBlock(MlirRewriterBase rewriter);
/// Returns the current block of the rewriter.
MLIR_CAPI_EXPORTED MlirBlock
mlirRewriterBaseGetBlock(MlirRewriterBase rewriter);
//===----------------------------------------------------------------------===//
/// Block and operation creation/insertion/cloning
//===----------------------------------------------------------------------===//
// These functions do not include the IRMapper, as it is not yet exposed by the
// C API.
/// Add new block with 'argTypes' arguments and set the insertion point to the
/// end of it. The block is placed before 'insertBefore'. `locs` contains the
/// locations of the inserted arguments, and should match the size of
/// `argTypes`.
MLIR_CAPI_EXPORTED MlirBlock mlirRewriterBaseCreateBlockBefore(
MlirRewriterBase rewriter, MlirBlock insertBefore, intptr_t nArgTypes,
MlirType const *argTypes, MlirLocation const *locations);
/// Insert the given operation at the current insertion point and return it.
MLIR_CAPI_EXPORTED MlirOperation
mlirRewriterBaseInsert(MlirRewriterBase rewriter, MlirOperation op);
/// Creates a deep copy of the specified operation.
MLIR_CAPI_EXPORTED MlirOperation
mlirRewriterBaseClone(MlirRewriterBase rewriter, MlirOperation op);
/// Creates a deep copy of this operation but keep the operation regions
/// empty.
MLIR_CAPI_EXPORTED MlirOperation mlirRewriterBaseCloneWithoutRegions(
MlirRewriterBase rewriter, MlirOperation op);
/// Clone the blocks that belong to "region" before the given position in
/// another region "parent".
MLIR_CAPI_EXPORTED void
mlirRewriterBaseCloneRegionBefore(MlirRewriterBase rewriter, MlirRegion region,
MlirBlock before);
//===----------------------------------------------------------------------===//
/// RewriterBase API
//===----------------------------------------------------------------------===//
/// Move the blocks that belong to "region" before the given position in
/// another region "parent". The two regions must be different. The caller
/// is responsible for creating or updating the operation transferring flow
/// of control to the region and passing it the correct block arguments.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseInlineRegionBefore(MlirRewriterBase rewriter, MlirRegion region,
MlirBlock before);
/// Replace the results of the given (original) operation with the specified
/// list of values (replacements). The result types of the given op and the
/// replacements must match. The original op is erased.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseReplaceOpWithValues(MlirRewriterBase rewriter, MlirOperation op,
intptr_t nValues, MlirValue const *values);
/// Replace the results of the given (original) operation with the specified
/// new op (replacement). The result types of the two ops must match. The
/// original op is erased.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseReplaceOpWithOperation(MlirRewriterBase rewriter,
MlirOperation op, MlirOperation newOp);
/// Erases an operation that is known to have no uses.
MLIR_CAPI_EXPORTED void mlirRewriterBaseEraseOp(MlirRewriterBase rewriter,
MlirOperation op);
/// Erases a block along with all operations inside it.
MLIR_CAPI_EXPORTED void mlirRewriterBaseEraseBlock(MlirRewriterBase rewriter,
MlirBlock block);
/// Inline the operations of block 'source' before the operation 'op'. The
/// source block will be deleted and must have no uses. 'argValues' is used to
/// replace the block arguments of 'source'
///
/// The source block must have no successors. Otherwise, the resulting IR
/// would have unreachable operations.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseInlineBlockBefore(MlirRewriterBase rewriter, MlirBlock source,
MlirOperation op, intptr_t nArgValues,
MlirValue const *argValues);
/// Inline the operations of block 'source' into the end of block 'dest'. The
/// source block will be deleted and must have no uses. 'argValues' is used to
/// replace the block arguments of 'source'
///
/// The dest block must have no successors. Otherwise, the resulting IR would
/// have unreachable operation.
MLIR_CAPI_EXPORTED void mlirRewriterBaseMergeBlocks(MlirRewriterBase rewriter,
MlirBlock source,
MlirBlock dest,
intptr_t nArgValues,
MlirValue const *argValues);
/// 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.
MLIR_CAPI_EXPORTED void mlirRewriterBaseMoveOpBefore(MlirRewriterBase rewriter,
MlirOperation op,
MlirOperation existingOp);
/// 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.
MLIR_CAPI_EXPORTED void mlirRewriterBaseMoveOpAfter(MlirRewriterBase rewriter,
MlirOperation op,
MlirOperation existingOp);
/// Unlink this block and insert it right before `existingBlock`.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseMoveBlockBefore(MlirRewriterBase rewriter, MlirBlock block,
MlirBlock existingBlock);
/// This method is used to notify the rewriter that an in-place operation
/// modification is about to happen. A call to this function *must* be
/// followed by a call to either `finalizeOpModification` or
/// `cancelOpModification`. This is a minor efficiency win (it avoids creating
/// a new operation and removing the old one) but also often allows simpler
/// code in the client.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseStartOpModification(MlirRewriterBase rewriter,
MlirOperation op);
/// This method is used to signal the end of an in-place modification of the
/// given operation. This can only be called on operations that were provided
/// to a call to `startOpModification`.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseFinalizeOpModification(MlirRewriterBase rewriter,
MlirOperation op);
/// This method cancels a pending in-place modification. This can only be
/// called on operations that were provided to a call to
/// `startOpModification`.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseCancelOpModification(MlirRewriterBase rewriter,
MlirOperation op);
/// Find uses of `from` and replace them with `to`. Also notify the listener
/// about every in-place op modification (for every use that was replaced).
MLIR_CAPI_EXPORTED void
mlirRewriterBaseReplaceAllUsesWith(MlirRewriterBase rewriter, MlirValue from,
MlirValue to);
/// Find uses of `from` and replace them with `to`. Also notify the listener
/// about every in-place op modification (for every use that was replaced).
MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceAllValueRangeUsesWith(
MlirRewriterBase rewriter, intptr_t nValues, MlirValue const *from,
MlirValue const *to);
/// Find uses of `from` and replace them with `to`. Also notify the listener
/// about every in-place op modification (for every use that was replaced)
/// and that the `from` operation is about to be replaced.
MLIR_CAPI_EXPORTED void
mlirRewriterBaseReplaceAllOpUsesWithValueRange(MlirRewriterBase rewriter,
MlirOperation from, intptr_t nTo,
MlirValue const *to);
/// Find uses of `from` and replace them with `to`. Also notify the listener
/// about every in-place op modification (for every use that was replaced)
/// and that the `from` operation is about to be replaced.
MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceAllOpUsesWithOperation(
MlirRewriterBase rewriter, MlirOperation from, MlirOperation to);
/// Find uses of `from` within `block` and replace them with `to`. Also notify
/// the listener about every in-place op modification (for every use that was
/// replaced). The optional `allUsesReplaced` flag is set to "true" if all
/// uses were replaced.
MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceOpUsesWithinBlock(
MlirRewriterBase rewriter, MlirOperation op, intptr_t nNewValues,
MlirValue const *newValues, MlirBlock block);
/// Find uses of `from` and replace them with `to` except if the user is
/// `exceptedUser`. Also notify the listener about every in-place op
/// modification (for every use that was replaced).
MLIR_CAPI_EXPORTED void
mlirRewriterBaseReplaceAllUsesExcept(MlirRewriterBase rewriter, MlirValue from,
MlirValue to, MlirOperation exceptedUser);
//===----------------------------------------------------------------------===//
/// IRRewriter API
//===----------------------------------------------------------------------===//
/// Create an IRRewriter and transfer ownership to the caller.
MLIR_CAPI_EXPORTED MlirRewriterBase mlirIRRewriterCreate(MlirContext context);
/// Create an IRRewriter and transfer ownership to the caller. Additionally
/// set the insertion point before the operation.
MLIR_CAPI_EXPORTED MlirRewriterBase
mlirIRRewriterCreateFromOp(MlirOperation op);
/// Takes an IRRewriter owned by the caller and destroys it. It is the
/// responsibility of the user to only pass an IRRewriter class.
MLIR_CAPI_EXPORTED void mlirIRRewriterDestroy(MlirRewriterBase rewriter);
//===----------------------------------------------------------------------===//
/// FrozenRewritePatternSet API
//===----------------------------------------------------------------------===//
MLIR_CAPI_EXPORTED MlirFrozenRewritePatternSet
mlirFreezeRewritePattern(MlirRewritePatternSet op);
MLIR_CAPI_EXPORTED void
mlirFrozenRewritePatternSetDestroy(MlirFrozenRewritePatternSet op);
MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPatternsAndFoldGreedilyWithOp(
MlirOperation op, MlirFrozenRewritePatternSet patterns,
MlirGreedyRewriteDriverConfig);
MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPatternsAndFoldGreedily(
MlirModule op, MlirFrozenRewritePatternSet patterns,
MlirGreedyRewriteDriverConfig);
//===----------------------------------------------------------------------===//
/// PDLPatternModule API
//===----------------------------------------------------------------------===//
#if MLIR_ENABLE_PDL_IN_PATTERNMATCH
DEFINE_C_API_STRUCT(MlirPDLPatternModule, void);
DEFINE_C_API_STRUCT(MlirPDLValue, const void);
DEFINE_C_API_STRUCT(MlirPDLResultList, void);
MLIR_CAPI_EXPORTED MlirPDLPatternModule
mlirPDLPatternModuleFromModule(MlirModule op);
MLIR_CAPI_EXPORTED void mlirPDLPatternModuleDestroy(MlirPDLPatternModule op);
MLIR_CAPI_EXPORTED MlirRewritePatternSet
mlirRewritePatternSetFromPDLPatternModule(MlirPDLPatternModule op);
/// Cast the MlirPDLValue to an MlirValue.
/// Return a null value if the cast fails, just like llvm::dyn_cast.
MLIR_CAPI_EXPORTED MlirValue mlirPDLValueAsValue(MlirPDLValue value);
/// Cast the MlirPDLValue to an MlirType.
/// Return a null value if the cast fails, just like llvm::dyn_cast.
MLIR_CAPI_EXPORTED MlirType mlirPDLValueAsType(MlirPDLValue value);
/// Cast the MlirPDLValue to an MlirOperation.
/// Return a null value if the cast fails, just like llvm::dyn_cast.
MLIR_CAPI_EXPORTED MlirOperation mlirPDLValueAsOperation(MlirPDLValue value);
/// Cast the MlirPDLValue to an MlirAttribute.
/// Return a null value if the cast fails, just like llvm::dyn_cast.
MLIR_CAPI_EXPORTED MlirAttribute mlirPDLValueAsAttribute(MlirPDLValue value);
/// Push the MlirValue into the given MlirPDLResultList.
MLIR_CAPI_EXPORTED void
mlirPDLResultListPushBackValue(MlirPDLResultList results, MlirValue value);
/// Push the MlirType into the given MlirPDLResultList.
MLIR_CAPI_EXPORTED void mlirPDLResultListPushBackType(MlirPDLResultList results,
MlirType value);
/// Push the MlirOperation into the given MlirPDLResultList.
MLIR_CAPI_EXPORTED void
mlirPDLResultListPushBackOperation(MlirPDLResultList results,
MlirOperation value);
/// Push the MlirAttribute into the given MlirPDLResultList.
MLIR_CAPI_EXPORTED void
mlirPDLResultListPushBackAttribute(MlirPDLResultList results,
MlirAttribute value);
/// This function type is used as callbacks for PDL native rewrite functions.
/// Input values can be accessed by `values` with its size `nValues`;
/// output values can be added into `results` by `mlirPDLResultListPushBack*`
/// APIs. And the return value indicates whether the rewrite succeeds.
typedef MlirLogicalResult (*MlirPDLRewriteFunction)(
MlirPatternRewriter rewriter, MlirPDLResultList results, size_t nValues,
MlirPDLValue *values, void *userData);
/// Register a rewrite function into the given PDL pattern module.
/// `userData` will be provided as an argument to the rewrite function.
MLIR_CAPI_EXPORTED void mlirPDLPatternModuleRegisterRewriteFunction(
MlirPDLPatternModule pdlModule, MlirStringRef name,
MlirPDLRewriteFunction rewriteFn, void *userData);
/// This function type is used as callbacks for PDL native constraint functions.
/// Input values can be accessed by `values` with its size `nValues`;
/// output values can be added into `results` by `mlirPDLResultListPushBack*`
/// APIs. And the return value indicates whether the constraint holds.
typedef MlirLogicalResult (*MlirPDLConstraintFunction)(
MlirPatternRewriter rewriter, MlirPDLResultList results, size_t nValues,
MlirPDLValue *values, void *userData);
/// Register a constraint function into the given PDL pattern module.
/// `userData` will be provided as an argument to the constraint function.
MLIR_CAPI_EXPORTED void mlirPDLPatternModuleRegisterConstraintFunction(
MlirPDLPatternModule pdlModule, MlirStringRef name,
MlirPDLConstraintFunction constraintFn, void *userData);
#endif // MLIR_ENABLE_PDL_IN_PATTERNMATCH
#undef DEFINE_C_API_STRUCT
#ifdef __cplusplus
}
#endif
#endif // MLIR_C_REWRITE_H