diff --git a/mlir/include/mlir-c/AffineExpr.h b/mlir/include/mlir-c/AffineExpr.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir-c/AffineExpr.h @@ -0,0 +1,150 @@ +/*===-- mlir-c/AffineExpr.h - C API for MLIR Affine Expressions ---*- 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 *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef MLIR_C_AFFINEEXPR_H +#define MLIR_C_AFFINEEXPR_H + +#include "mlir-c/AffineMap.h" +#include "mlir-c/IR.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DEFINE_C_API_STRUCT(MlirAffineExpr, const void); + +/** Gets the context that owns the affine expression. */ +MlirContext mlirAffineExprGetContext(MlirAffineExpr affineExpr); + +/** Prints an affine expression by sending chunks of the string representation + * and forwarding `userData to `callback`. Note that the callback may be called + * several times with consecutive chunks of the string. */ +void mlirAffineExprPrint(MlirAffineExpr affineExpr, MlirStringCallback callback, + void *userData); + +/** Prints the affine expression to the standard error stream. */ +void mlirAffineExprDump(MlirAffineExpr affineExpr); + +/** Checks whether the given affine expression is made out of only symbols and + * constants. */ +int mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr); + +/** Checks whether the given affine expression is a pure affine expression, i.e. + * mul, floordiv, ceildic, and mod is only allowed w.r.t constants. */ +int mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr); + +/** Returns the greatest known integral divisor of this affine expression. The + * result is always positive. */ +int64_t mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr); + +/** Checks whether the given affine expression is a multiple of 'factor'. */ +int mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr, int64_t factor); + +/** Checks whether the given affine expression involves AffineDimExpr + * 'position'. */ +int mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, intptr_t position); + +/*============================================================================*/ +/* Affine Dimension Expression. */ +/*============================================================================*/ + +/** Creates an affine dimension expression with 'position' in the context. */ +MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx, intptr_t position); + +/** Returns the position of the given affine dimension expression. */ +intptr_t mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr); + +/*============================================================================*/ +/* Affine Symbol Expression. */ +/*============================================================================*/ + +/** Creates an affine symbol expression with 'position' in the context. */ +MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx, intptr_t position); + +/** Returns the position of the given affine symbol expression. */ +intptr_t mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr); + +/*============================================================================*/ +/* Affine Constant Expression. */ +/*============================================================================*/ + +/** Creates an affine constant expression with 'constant' in the context. */ +MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx, int64_t constant); + +/** Returns the value of the given affine constant expression. */ +int64_t mlirAffineConstantExprGetValue(MlirAffineExpr affineExpr); + +/*============================================================================*/ +/* Affine Add Expression. */ +/*============================================================================*/ + +/** Checks whether the given affine expression is an add expression. */ +int mlirAffineExprIsAAdd(MlirAffineExpr affineExpr); + +/** Creates an affine add expression with 'lhs' and 'rhs'. */ +MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs); + +/*============================================================================*/ +/* Affine Mul Expression. */ +/*============================================================================*/ + +/** Checks whether the given affine expression is an mul expression. */ +int mlirAffineExprIsAMul(MlirAffineExpr affineExpr); + +/** Creates an affine mul expression with 'lhs' and 'rhs'. */ +MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs); + +/*============================================================================*/ +/* Affine Mod Expression. */ +/*============================================================================*/ + +/** Checks whether the given affine expression is an mod expression. */ +int mlirAffineExprIsAMod(MlirAffineExpr affineExpr); + +/** Creates an affine mod expression with 'lhs' and 'rhs'. */ +MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs); + +/*============================================================================*/ +/* Affine FloorDiv Expression. */ +/*============================================================================*/ + +/** Checks whether the given affine expression is an floordiv expression. */ +int mlirAffineExprIsAFloorDiv(MlirAffineExpr affineExpr); + +/** Creates an affine floordiv expression with 'lhs' and 'rhs'. */ +MlirAffineExpr mlirAffineFloorDivExprGet(MlirAffineExpr lhs, + MlirAffineExpr rhs); + +/*============================================================================*/ +/* Affine CeilDiv Expression. */ +/*============================================================================*/ + +/** Checks whether the given affine expression is an ceildiv expression. */ +int mlirAffineExprIsACeilDiv(MlirAffineExpr affineExpr); + +/** Creates an affine ceildiv expression with 'lhs' and 'rhs'. */ +MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs); + +/*============================================================================*/ +/* Affine Binary Operation Expression. */ +/*============================================================================*/ + +/** Returns the left hand side affine expression of the given affine binary + * operation expression. */ +MlirAffineExpr mlirAffineBinaryOpExprGetLHS(MlirAffineExpr affineExpr); + +/** Returns the right hand side affine expression of the given affine binary + * operation expression. */ +MlirAffineExpr mlirAffineBinaryOpExprGetRHS(MlirAffineExpr affineExpr); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_AFFINEEXPR_H diff --git a/mlir/include/mlir/CAPI/AffineExpr.h b/mlir/include/mlir/CAPI/AffineExpr.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/CAPI/AffineExpr.h @@ -0,0 +1,24 @@ +//===- AffineExpr.h - C API Utils for Affine Expressions --------*- 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 file contains declarations of implementation details of the C API for +// MLIR Affine Expression. This file should not be included from C++ code other +// than C API implementation nor from C code. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CAPI_AFFINEEXPR_H +#define MLIR_CAPI_AFFINEEXPR_H + +#include "mlir-c/AffineExpr.h" +#include "mlir/CAPI/Wrap.h" +#include "mlir/IR/AffineExpr.h" + +DEFINE_C_API_METHODS(MlirAffineExpr, mlir::AffineExpr) + +#endif // MLIR_CAPI_AFFINEEXPR_H diff --git a/mlir/include/mlir/IR/AffineExpr.h b/mlir/include/mlir/IR/AffineExpr.h --- a/mlir/include/mlir/IR/AffineExpr.h +++ b/mlir/include/mlir/IR/AffineExpr.h @@ -164,6 +164,15 @@ friend ::llvm::hash_code hash_value(AffineExpr arg); + /// Methods supporting C API. + const void *getAsOpaquePointer() const { + return static_cast(expr); + } + static AffineExpr getFromOpaquePointer(const void *pointer) { + return AffineExpr( + reinterpret_cast(const_cast(pointer))); + } + protected: ImplType *expr; }; diff --git a/mlir/lib/CAPI/IR/AffineExpr.cpp b/mlir/lib/CAPI/IR/AffineExpr.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/CAPI/IR/AffineExpr.cpp @@ -0,0 +1,169 @@ +//===- AffineExpr.cpp - C API for MLIR Affine Expressions -----------------===// +// +// 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-c/AffineExpr.h" +#include "mlir-c/AffineMap.h" +#include "mlir-c/IR.h" +#include "mlir/CAPI/AffineExpr.h" +#include "mlir/CAPI/AffineMap.h" +#include "mlir/CAPI/IR.h" +#include "mlir/CAPI/Utils.h" +#include "mlir/IR/AffineExpr.h" + +using namespace mlir; + +MlirContext mlirAffineExprGetContext(MlirAffineExpr affineExpr) { + return wrap(unwrap(affineExpr).getContext()); +} + +void mlirAffineExprPrint(MlirAffineExpr affineExpr, MlirStringCallback callback, + void *userData) { + mlir::detail::CallbackOstream stream(callback, userData); + unwrap(affineExpr).print(stream); + stream.flush(); +} + +void mlirAffineExprDump(MlirAffineExpr affineExpr) { + unwrap(affineExpr).dump(); +} + +int mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isSymbolicOrConstant(); +} + +int mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isPureAffine(); +} + +int64_t mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getLargestKnownDivisor(); +} + +int mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr, int64_t factor) { + return unwrap(affineExpr).isMultipleOf(factor); +} + +int mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, + intptr_t position) { + return unwrap(affineExpr).isFunctionOfDim(position); +} + +/*============================================================================*/ +/* Affine Dimension Expression. */ +/*============================================================================*/ + +MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx, intptr_t position) { + return wrap(getAffineDimExpr(position, unwrap(ctx))); +} + +intptr_t mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).cast().getPosition(); +} + +/*============================================================================*/ +/* Affine Symbol Expression. */ +/*============================================================================*/ + +MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx, intptr_t position) { + return wrap(getAffineSymbolExpr(position, unwrap(ctx))); +} + +intptr_t mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).cast().getPosition(); +} + +/*============================================================================*/ +/* Affine Constant Expression. */ +/*============================================================================*/ + +MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx, int64_t constant) { + return wrap(getAffineConstantExpr(constant, unwrap(ctx))); +} + +int64_t mlirAffineConstantExprGetValue(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).cast().getValue(); +} + +/*============================================================================*/ +/* Affine Add Expression. */ +/*============================================================================*/ + +int mlirAffineExprIsAAdd(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getKind() == mlir::AffineExprKind::Add; +} + +MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs) { + return wrap(getAffineBinaryOpExpr(mlir::AffineExprKind::Add, unwrap(lhs), + unwrap(rhs))); +} + +/*============================================================================*/ +/* Affine Mul Expression. */ +/*============================================================================*/ + +int mlirAffineExprIsAMul(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getKind() == mlir::AffineExprKind::Mul; +} + +MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs) { + return wrap(getAffineBinaryOpExpr(mlir::AffineExprKind::Mul, unwrap(lhs), + unwrap(rhs))); +} + +/*============================================================================*/ +/* Affine Mod Expression. */ +/*============================================================================*/ + +int mlirAffineExprIsAMod(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getKind() == mlir::AffineExprKind::Mod; +} + +MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs) { + return wrap(getAffineBinaryOpExpr(mlir::AffineExprKind::Mod, unwrap(lhs), + unwrap(rhs))); +} + +/*============================================================================*/ +/* Affine FloorDiv Expression. */ +/*============================================================================*/ + +int mlirAffineExprIsAFloorDiv(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getKind() == mlir::AffineExprKind::FloorDiv; +} + +MlirAffineExpr mlirAffineFloorDivExprGet(MlirAffineExpr lhs, + MlirAffineExpr rhs) { + return wrap(getAffineBinaryOpExpr(mlir::AffineExprKind::FloorDiv, unwrap(lhs), + unwrap(rhs))); +} + +/*============================================================================*/ +/* Affine CeilDiv Expression. */ +/*============================================================================*/ + +int mlirAffineExprIsACeilDiv(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).getKind() == mlir::AffineExprKind::CeilDiv; +} + +MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, + MlirAffineExpr rhs) { + return wrap(getAffineBinaryOpExpr(mlir::AffineExprKind::CeilDiv, unwrap(lhs), + unwrap(rhs))); +} + +/*============================================================================*/ +/* Affine Binary Operation Expression. */ +/*============================================================================*/ + +MlirAffineExpr mlirAffineBinaryOpExprGetLHS(MlirAffineExpr affineExpr) { + return wrap(unwrap(affineExpr).cast().getLHS()); +} + +MlirAffineExpr mlirAffineBinaryOpExprGetRHS(MlirAffineExpr affineExpr) { + return wrap(unwrap(affineExpr).cast().getRHS()); +} diff --git a/mlir/lib/CAPI/IR/CMakeLists.txt b/mlir/lib/CAPI/IR/CMakeLists.txt --- a/mlir/lib/CAPI/IR/CMakeLists.txt +++ b/mlir/lib/CAPI/IR/CMakeLists.txt @@ -1,5 +1,6 @@ # Main API. add_mlir_library(MLIRCAPIIR + AffineExpr.cpp AffineMap.cpp Diagnostics.cpp IR.cpp diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c --- a/mlir/test/CAPI/ir.c +++ b/mlir/test/CAPI/ir.c @@ -11,6 +11,7 @@ */ #include "mlir-c/IR.h" +#include "mlir-c/AffineExpr.h" #include "mlir-c/AffineMap.h" #include "mlir-c/Diagnostics.h" #include "mlir-c/Registration.h" @@ -889,6 +890,118 @@ return 0; } +int printAffineExpr(MlirContext ctx) { + MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 5); + MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 5); + MlirAffineExpr affineConstantExpr = mlirAffineConstantExprGet(ctx, 5); + MlirAffineExpr affineAddExpr = + mlirAffineAddExprGet(affineDimExpr, affineSymbolExpr); + MlirAffineExpr affineMulExpr = + mlirAffineMulExprGet(affineDimExpr, affineSymbolExpr); + MlirAffineExpr affineModExpr = + mlirAffineModExprGet(affineDimExpr, affineSymbolExpr); + MlirAffineExpr affineFloorDivExpr = + mlirAffineFloorDivExprGet(affineDimExpr, affineSymbolExpr); + MlirAffineExpr affineCeilDivExpr = + mlirAffineCeilDivExprGet(affineDimExpr, affineSymbolExpr); + + // Tests mlirAffineExprDump. + mlirAffineExprDump(affineDimExpr); + mlirAffineExprDump(affineSymbolExpr); + mlirAffineExprDump(affineConstantExpr); + mlirAffineExprDump(affineAddExpr); + mlirAffineExprDump(affineMulExpr); + mlirAffineExprDump(affineModExpr); + mlirAffineExprDump(affineFloorDivExpr); + mlirAffineExprDump(affineCeilDivExpr); + + // Tests methods of affine binary operation expression, takes add expression + // as an example. + mlirAffineExprDump(mlirAffineBinaryOpExprGetLHS(affineAddExpr)); + mlirAffineExprDump(mlirAffineBinaryOpExprGetRHS(affineAddExpr)); + + // Tests methods of affine dimension expression. + if (mlirAffineDimExprGetPosition(affineDimExpr) != 5) + return 1; + + // Tests methods of affine symbol expression. + if (mlirAffineSymbolExprGetPosition(affineSymbolExpr) != 5) + return 2; + + // Tests methods of affine constant expression. + if (mlirAffineConstantExprGetValue(affineConstantExpr) != 5) + return 3; + + // Tests methods of affine expression. + if (mlirAffineExprIsSymbolicOrConstant(affineDimExpr) || + !mlirAffineExprIsSymbolicOrConstant(affineSymbolExpr) || + !mlirAffineExprIsSymbolicOrConstant(affineConstantExpr) || + mlirAffineExprIsSymbolicOrConstant(affineAddExpr) || + mlirAffineExprIsSymbolicOrConstant(affineMulExpr) || + mlirAffineExprIsSymbolicOrConstant(affineModExpr) || + mlirAffineExprIsSymbolicOrConstant(affineFloorDivExpr) || + mlirAffineExprIsSymbolicOrConstant(affineCeilDivExpr)) + return 4; + + if (!mlirAffineExprIsPureAffine(affineDimExpr) || + !mlirAffineExprIsPureAffine(affineSymbolExpr) || + !mlirAffineExprIsPureAffine(affineConstantExpr) || + !mlirAffineExprIsPureAffine(affineAddExpr) || + mlirAffineExprIsPureAffine(affineMulExpr) || + mlirAffineExprIsPureAffine(affineModExpr) || + mlirAffineExprIsPureAffine(affineFloorDivExpr) || + mlirAffineExprIsPureAffine(affineCeilDivExpr)) + return 5; + + if (mlirAffineExprGetLargestKnownDivisor(affineDimExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineSymbolExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineConstantExpr) != 5 || + mlirAffineExprGetLargestKnownDivisor(affineAddExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineMulExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineModExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineFloorDivExpr) != 1 || + mlirAffineExprGetLargestKnownDivisor(affineCeilDivExpr) != 1) + return 6; + + if (!mlirAffineExprIsMultipleOf(affineDimExpr, 1) || + !mlirAffineExprIsMultipleOf(affineSymbolExpr, 1) || + !mlirAffineExprIsMultipleOf(affineConstantExpr, 5) || + !mlirAffineExprIsMultipleOf(affineAddExpr, 1) || + !mlirAffineExprIsMultipleOf(affineMulExpr, 1) || + !mlirAffineExprIsMultipleOf(affineModExpr, 1) || + !mlirAffineExprIsMultipleOf(affineFloorDivExpr, 1) || + !mlirAffineExprIsMultipleOf(affineCeilDivExpr, 1)) + return 7; + + if (!mlirAffineExprIsFunctionOfDim(affineDimExpr, 5) || + mlirAffineExprIsFunctionOfDim(affineSymbolExpr, 5) || + mlirAffineExprIsFunctionOfDim(affineConstantExpr, 5) || + !mlirAffineExprIsFunctionOfDim(affineAddExpr, 5) || + !mlirAffineExprIsFunctionOfDim(affineMulExpr, 5) || + !mlirAffineExprIsFunctionOfDim(affineModExpr, 5) || + !mlirAffineExprIsFunctionOfDim(affineFloorDivExpr, 5) || + !mlirAffineExprIsFunctionOfDim(affineCeilDivExpr, 5)) + return 8; + + // Tests 'IsA' methods of affine binary operaion expression. + if (!mlirAffineExprIsAAdd(affineAddExpr)) + return 9; + + if (!mlirAffineExprIsAMul(affineMulExpr)) + return 10; + + if (!mlirAffineExprIsAMod(affineModExpr)) + return 11; + + if (!mlirAffineExprIsAFloorDiv(affineFloorDivExpr)) + return 12; + + if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr)) + return 13; + + return 0; +} + int registerOnlyStd() { MlirContext ctx = mlirContextCreate(); // The built-in dialect is always loaded. @@ -1107,6 +1220,23 @@ errcode = printAffineMap(ctx); fprintf(stderr, "%d\n", errcode); + // clang-format off + // CHECK: d5 + // CHECK: s5 + // CHECK: 5 + // CHECK: d5 + s5 + // CHECK: d5 * s5 + // CHECK: d5 mod s5 + // CHECK: d5 floordiv s5 + // CHECK: d5 ceildiv s5 + // CHECK: d5 + // CHECK: s5 + // CHECK: 0 + // clang-format on + fprintf(stderr, "@affineExpr\n"); + errcode = printAffineExpr(ctx); + fprintf(stderr, "%d\n", errcode); + fprintf(stderr, "@registration\n"); errcode = registerOnlyStd(); fprintf(stderr, "%d\n", errcode);