/// Returns true if the result of this operation is a symbol for all its
/// uses in `region`.
bool isValidSymbol(Region *region);
+
+ /// Returns all dimension operands.
+ ValueRange getDimOperands() {
+ return OperandRange{getOperands().begin(),
+ getOperands().begin() + getMap().getNumDims()};
+ }
+
+ /// Returns all symbol operands.
+ ValueRange getSymbolOperands() {
+ return OperandRange{getOperands().begin() + getMap().getNumDims(),
+ getOperands().end()};
+ }
}];
let hasCanonicalizer = 1;
--- /dev/null
+//===- ValueBoundsOpInterfaceImpl.h - Impl. of ValueBoundsOpInterface -----===//
+//
+// 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_DIALECT_AFFINE_IR_VALUEBOUNDSOPINTERFACEIMPL_H
+#define MLIR_DIALECT_AFFINE_IR_VALUEBOUNDSOPINTERFACEIMPL_H
+
+namespace mlir {
+class DialectRegistry;
+
+namespace affine {
+void registerValueBoundsOpInterfaceExternalModels(DialectRegistry ®istry);
+} // namespace affine
+} // namespace mlir
+
+#endif // MLIR_DIALECT_AFFINE_IR_VALUEBOUNDSOPINTERFACEIMPL_H
#include "mlir/Dialect/AMDGPU/AMDGPUDialect.h"
#include "mlir/Dialect/AMX/AMXDialect.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
+#include "mlir/Dialect/Affine/IR/ValueBoundsOpInterfaceImpl.h"
#include "mlir/Dialect/Affine/TransformOps/AffineTransformOps.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.h"
vector::registerTransformDialectExtension(registry);
// Register all external models.
+ affine::registerValueBoundsOpInterfaceExternalModels(registry);
arith::registerBufferizableOpInterfaceExternalModels(registry);
bufferization::func_ext::registerBufferizableOpInterfaceExternalModels(
registry);
AffineMemoryOpInterfaces.cpp
AffineOps.cpp
AffineValueMap.cpp
+ ValueBoundsOpInterfaceImpl.cpp
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/Affine
MLIRMemRefDialect
MLIRShapedOpInterfaces
MLIRSideEffectInterfaces
+ MLIRValueBoundsOpInterface
)
--- /dev/null
+//===- ValueBoundsOpInterfaceImpl.cpp - Impl. of ValueBoundsOpInterface ---===//
+//
+// 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/Dialect/Affine/IR/ValueBoundsOpInterfaceImpl.h"
+
+#include "mlir/Dialect/Affine/IR/AffineOps.h"
+#include "mlir/Interfaces/ValueBoundsOpInterface.h"
+
+using namespace mlir;
+
+namespace mlir {
+namespace {
+
+struct AffineApplyOpInterface
+ : public ValueBoundsOpInterface::ExternalModel<AffineApplyOpInterface,
+ AffineApplyOp> {
+ void populateBoundsForIndexValue(Operation *op, Value value,
+ ValueBoundsConstraintSet &cstr) const {
+ auto applyOp = cast<AffineApplyOp>(op);
+ assert(value == applyOp.getResult() && "invalid value");
+ assert(applyOp.getAffineMap().getNumResults() == 1 &&
+ "expected single result");
+
+ // Align affine map result with dims/symbols in the constraint set.
+ AffineExpr expr = applyOp.getAffineMap().getResult(0);
+ SmallVector<AffineExpr> dimReplacements = llvm::to_vector(llvm::map_range(
+ applyOp.getDimOperands(), [&](Value v) { return cstr.getExpr(v); }));
+ SmallVector<AffineExpr> symReplacements = llvm::to_vector(llvm::map_range(
+ applyOp.getSymbolOperands(), [&](Value v) { return cstr.getExpr(v); }));
+ AffineExpr bound =
+ expr.replaceDimsAndSymbols(dimReplacements, symReplacements);
+ cstr.bound(value) == bound;
+ }
+};
+
+} // namespace
+} // namespace mlir
+
+void mlir::affine::registerValueBoundsOpInterfaceExternalModels(
+ DialectRegistry ®istry) {
+ registry.addExtension(+[](MLIRContext *ctx, AffineDialect *dialect) {
+ AffineApplyOp::attachInterface<AffineApplyOpInterface>(*ctx);
+ });
+}
--- /dev/null
+// RUN: mlir-opt %s -test-affine-reify-value-bounds -verify-diagnostics \
+// RUN: -split-input-file | FileCheck %s
+
+// CHECK: #[[$map:.*]] = affine_map<()[s0, s1] -> (s0 + s1)>
+// CHECK-LABEL: func @affine_apply(
+// CHECK-SAME: %[[a:.*]]: index, %[[b:.*]]: index
+// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]]
+// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]]
+// CHECL: return %[[apply]]
+func.func @affine_apply(%a: index, %b: index) -> index {
+ %0 = affine.apply affine_map<()[s0, s1] -> (s0 + s1)>()[%a, %b]
+ %1 = "test.reify_bound"(%0) : (index) -> (index)
+ return %1 : index
+}
":ShapedOpInterfaces",
":SideEffectInterfaces",
":Support",
+ ":ValueBoundsOpInterface",
"//llvm:Support",
],
)