[Mlir-commits] [mlir] [mlir][ValueBounds] Skip analysis for identical slice components (PR #226894)
Ziliang Zhang
llvmlistbot at llvm.org
Mon Sep 28 23:07:08 PDT 2026
https://github.com/ziliangzl updated https://github.com/llvm/llvm-project/pull/226894
>From 4df93794112769d12db071e5ed00c31d2e56b60b Mon Sep 17 00:00:00 2001
From: Ziliang Zhang <zzl.coding at gmail.com>
Date: Mon, 28 Sep 2026 13:46:30 +0800
Subject: [PATCH 1/3] [mlir][ValueBounds] Skip analysis for identical slice
components
One-Shot Bufferize repeatedly compares subset slices whose offsets, sizes, and strides often reuse the same SSA values and attributes. Avoid constructing a ValueBounds constraint set when the two OpFoldResults are already identical, while preserving the existing solver fallback for distinct values.
---
.../lib/Interfaces/ValueBoundsOpInterface.cpp | 8 +++
mlir/unittests/Interfaces/CMakeLists.txt | 2 +
.../Interfaces/ValueBoundsOpInterfaceTest.cpp | 61 +++++++++++++++++++
3 files changed, 71 insertions(+)
create mode 100644 mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
index d6d3b4d43cb55..0d22b1d39c14e 100644
--- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
+++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
@@ -955,6 +955,10 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
// "failure".
for (auto [offset1, offset2] :
llvm::zip_equal(slice1.getMixedOffsets(), slice2.getMixedOffsets())) {
+ // Avoid constructing a constraint set for values/attributes that are
+ // already known to be identical.
+ if (offset1 == offset2)
+ continue;
FailureOr<bool> equal = areEqual(offset1, offset2);
if (failed(equal))
return failure();
@@ -963,6 +967,8 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
}
for (auto [size1, size2] :
llvm::zip_equal(slice1.getMixedSizes(), slice2.getMixedSizes())) {
+ if (size1 == size2)
+ continue;
FailureOr<bool> equal = areEqual(size1, size2);
if (failed(equal))
return failure();
@@ -971,6 +977,8 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
}
for (auto [stride1, stride2] :
llvm::zip_equal(slice1.getMixedStrides(), slice2.getMixedStrides())) {
+ if (stride1 == stride2)
+ continue;
FailureOr<bool> equal = areEqual(stride1, stride2);
if (failed(equal))
return failure();
diff --git a/mlir/unittests/Interfaces/CMakeLists.txt b/mlir/unittests/Interfaces/CMakeLists.txt
index 193edda6bf8d8..5cb2948c814cd 100644
--- a/mlir/unittests/Interfaces/CMakeLists.txt
+++ b/mlir/unittests/Interfaces/CMakeLists.txt
@@ -5,6 +5,7 @@ add_mlir_unittest(MLIRInterfacesTests
MemorySlotUtilsTest.cpp
SideEffectInterfacesTest.cpp
InferTypeOpInterfaceTest.cpp
+ ValueBoundsOpInterfaceTest.cpp
DEPENDS
MLIRTestInterfaceIncGen
@@ -23,5 +24,6 @@ mlir_target_link_libraries(MLIRInterfacesTests
MLIRMemorySlotUtils
MLIRParser
MLIRSideEffectInterfaces
+ MLIRValueBoundsOpInterface
)
target_link_libraries(MLIRInterfacesTests PRIVATE MLIRTestDialect)
diff --git a/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp b/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
new file mode 100644
index 0000000000000..1a7de44ecc7da
--- /dev/null
+++ b/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
@@ -0,0 +1,61 @@
+//===- ValueBoundsOpInterfaceTest.cpp - ValueBounds unit tests -----------===//
+//
+// 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/Func/IR/FuncOps.h"
+#include "mlir/Interfaces/ValueBoundsOpInterface.h"
+
+#include <gtest/gtest.h>
+
+using namespace mlir;
+
+namespace {
+
+TEST(ValueBoundsOpInterfaceTest, EquivalentSlices) {
+ MLIRContext context;
+ context.loadDialect<func::FuncDialect>();
+ OpBuilder builder(&context);
+
+ auto function = func::FuncOp::create(
+ builder.getUnknownLoc(), "test",
+ builder.getFunctionType({builder.getIndexType(), builder.getIndexType()},
+ {}));
+ Block *entryBlock = function.addEntryBlock();
+ Value dynamicValue = entryBlock->getArgument(0);
+ Value otherDynamicValue = entryBlock->getArgument(1);
+
+ OpFoldResult zero = builder.getIndexAttr(0);
+ OpFoldResult one = builder.getIndexAttr(1);
+ OpFoldResult four = builder.getIndexAttr(4);
+ OpFoldResult five = builder.getIndexAttr(5);
+
+ HyperrectangularSlice slice({zero, dynamicValue}, {four, dynamicValue},
+ {one, one});
+ HyperrectangularSlice identicalSlice({zero, dynamicValue},
+ {four, dynamicValue}, {one, one});
+ FailureOr<bool> equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
+ &context, slice, identicalSlice);
+ ASSERT_TRUE(succeeded(equivalent));
+ EXPECT_TRUE(*equivalent);
+
+ // Identical components must not hide a later non-equivalent component.
+ HyperrectangularSlice differentSlice({zero, dynamicValue},
+ {five, dynamicValue}, {one, one});
+ equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
+ &context, slice, differentSlice);
+ ASSERT_TRUE(succeeded(equivalent));
+ EXPECT_FALSE(*equivalent);
+
+ // Distinct dynamic values continue to use the ValueBounds fallback.
+ HyperrectangularSlice unknownSlice({zero, otherDynamicValue},
+ {four, dynamicValue}, {one, one});
+ equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
+ &context, slice, unknownSlice);
+ EXPECT_TRUE(failed(equivalent));
+}
+
+} // namespace
>From c3b2807b58c14cbfe8f0d2e92cb7b591314b0019 Mon Sep 17 00:00:00 2001
From: Ziliang Zhang <zzl.coding at gmail.com>
Date: Mon, 28 Sep 2026 14:07:02 +0800
Subject: [PATCH 2/3] [mlir][ValueBounds] Fix unit test formatting
---
.../Interfaces/ValueBoundsOpInterfaceTest.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp b/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
index 1a7de44ecc7da..1571ab924bf6f 100644
--- a/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
+++ b/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Interfaces/ValueBoundsOpInterface.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
#include <gtest/gtest.h>
@@ -45,16 +45,16 @@ TEST(ValueBoundsOpInterfaceTest, EquivalentSlices) {
// Identical components must not hide a later non-equivalent component.
HyperrectangularSlice differentSlice({zero, dynamicValue},
{five, dynamicValue}, {one, one});
- equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
- &context, slice, differentSlice);
+ equivalent = ValueBoundsConstraintSet::areEquivalentSlices(&context, slice,
+ differentSlice);
ASSERT_TRUE(succeeded(equivalent));
EXPECT_FALSE(*equivalent);
// Distinct dynamic values continue to use the ValueBounds fallback.
HyperrectangularSlice unknownSlice({zero, otherDynamicValue},
{four, dynamicValue}, {one, one});
- equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
- &context, slice, unknownSlice);
+ equivalent = ValueBoundsConstraintSet::areEquivalentSlices(&context, slice,
+ unknownSlice);
EXPECT_TRUE(failed(equivalent));
}
>From fd7fd5cce87e9168ccac4ff265d2d64d9e7b5797 Mon Sep 17 00:00:00 2001
From: Ziliang Zhang <zzl.coding at gmail.com>
Date: Tue, 29 Sep 2026 14:06:48 +0800
Subject: [PATCH 3/3] [mlir][ValueBounds] Address slice identity review
feedback
---
.../lib/Interfaces/ValueBoundsOpInterface.cpp | 12 ++--
.../one-shot-module-bufferize-analysis.mlir | 23 +++++++
mlir/unittests/Interfaces/CMakeLists.txt | 2 -
.../Interfaces/ValueBoundsOpInterfaceTest.cpp | 61 -------------------
4 files changed, 27 insertions(+), 71 deletions(-)
delete mode 100644 mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
index 0d22b1d39c14e..d998104e99f4a 100644
--- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
+++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
@@ -872,6 +872,10 @@ FailureOr<bool> ValueBoundsConstraintSet::strongCompare(const Variable &lhs,
FailureOr<bool> ValueBoundsConstraintSet::areEqual(const Variable &var1,
const Variable &var2) {
+ // Avoid constructing a constraint set for variables that are already known
+ // to be identical.
+ if (var1.map == var2.map && var1.mapOperands == var2.mapOperands)
+ return true;
return strongCompare(var1, ComparisonOperator::EQ, var2);
}
@@ -955,10 +959,6 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
// "failure".
for (auto [offset1, offset2] :
llvm::zip_equal(slice1.getMixedOffsets(), slice2.getMixedOffsets())) {
- // Avoid constructing a constraint set for values/attributes that are
- // already known to be identical.
- if (offset1 == offset2)
- continue;
FailureOr<bool> equal = areEqual(offset1, offset2);
if (failed(equal))
return failure();
@@ -967,8 +967,6 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
}
for (auto [size1, size2] :
llvm::zip_equal(slice1.getMixedSizes(), slice2.getMixedSizes())) {
- if (size1 == size2)
- continue;
FailureOr<bool> equal = areEqual(size1, size2);
if (failed(equal))
return failure();
@@ -977,8 +975,6 @@ FailureOr<bool> ValueBoundsConstraintSet::areEquivalentSlices(
}
for (auto [stride1, stride2] :
llvm::zip_equal(slice1.getMixedStrides(), slice2.getMixedStrides())) {
- if (stride1 == stride2)
- continue;
FailureOr<bool> equal = areEqual(stride1, stride2);
if (failed(equal))
return failure();
diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir
index c947407c63e74..4e64161aa8030 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir
@@ -250,6 +250,29 @@ func.func @extract_slice_matching_insert_slice(
// -----
+// CHECK-LABEL: func @extract_slice_matching_insert_slice_dynamic
+func.func @extract_slice_matching_insert_slice_dynamic(
+ %tensor: tensor<?xf32> {bufferization.writable = true},
+ %offset: index, %size: index) -> tensor<?xf32> {
+ // Identical dynamic offsets/sizes and static strides should be recognized
+ // without constructing a ValueBounds constraint set.
+ // CHECK: tensor.extract_slice
+ // CHECK-SAME: {__inplace_operands_attr__ = ["true", "none", "none"]}
+ %slice = tensor.extract_slice %tensor[%offset][%size][1]
+ : tensor<?xf32> to tensor<?xf32>
+
+ // CHECK: tensor.insert_slice
+ // CHECK-SAME: {__inplace_operands_attr__ = ["true", "true", "none", "none"]}
+ %result = tensor.insert_slice %slice into %tensor[%offset][%size][1]
+ : tensor<?xf32> into tensor<?xf32>
+
+ // CHECK: return
+ // CHECK-SAME: __equivalent_func_args__ = [0]
+ return %result : tensor<?xf32>
+}
+
+// -----
+
// CHECK-LABEL: @read_of_matching_insert_slice_source
func.func @read_of_matching_insert_slice_source(
%A : tensor<?xf32> {bufferization.writable = true},
diff --git a/mlir/unittests/Interfaces/CMakeLists.txt b/mlir/unittests/Interfaces/CMakeLists.txt
index 5cb2948c814cd..193edda6bf8d8 100644
--- a/mlir/unittests/Interfaces/CMakeLists.txt
+++ b/mlir/unittests/Interfaces/CMakeLists.txt
@@ -5,7 +5,6 @@ add_mlir_unittest(MLIRInterfacesTests
MemorySlotUtilsTest.cpp
SideEffectInterfacesTest.cpp
InferTypeOpInterfaceTest.cpp
- ValueBoundsOpInterfaceTest.cpp
DEPENDS
MLIRTestInterfaceIncGen
@@ -24,6 +23,5 @@ mlir_target_link_libraries(MLIRInterfacesTests
MLIRMemorySlotUtils
MLIRParser
MLIRSideEffectInterfaces
- MLIRValueBoundsOpInterface
)
target_link_libraries(MLIRInterfacesTests PRIVATE MLIRTestDialect)
diff --git a/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp b/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
deleted file mode 100644
index 1571ab924bf6f..0000000000000
--- a/mlir/unittests/Interfaces/ValueBoundsOpInterfaceTest.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- ValueBoundsOpInterfaceTest.cpp - ValueBounds unit tests -----------===//
-//
-// 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/Interfaces/ValueBoundsOpInterface.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-
-#include <gtest/gtest.h>
-
-using namespace mlir;
-
-namespace {
-
-TEST(ValueBoundsOpInterfaceTest, EquivalentSlices) {
- MLIRContext context;
- context.loadDialect<func::FuncDialect>();
- OpBuilder builder(&context);
-
- auto function = func::FuncOp::create(
- builder.getUnknownLoc(), "test",
- builder.getFunctionType({builder.getIndexType(), builder.getIndexType()},
- {}));
- Block *entryBlock = function.addEntryBlock();
- Value dynamicValue = entryBlock->getArgument(0);
- Value otherDynamicValue = entryBlock->getArgument(1);
-
- OpFoldResult zero = builder.getIndexAttr(0);
- OpFoldResult one = builder.getIndexAttr(1);
- OpFoldResult four = builder.getIndexAttr(4);
- OpFoldResult five = builder.getIndexAttr(5);
-
- HyperrectangularSlice slice({zero, dynamicValue}, {four, dynamicValue},
- {one, one});
- HyperrectangularSlice identicalSlice({zero, dynamicValue},
- {four, dynamicValue}, {one, one});
- FailureOr<bool> equivalent = ValueBoundsConstraintSet::areEquivalentSlices(
- &context, slice, identicalSlice);
- ASSERT_TRUE(succeeded(equivalent));
- EXPECT_TRUE(*equivalent);
-
- // Identical components must not hide a later non-equivalent component.
- HyperrectangularSlice differentSlice({zero, dynamicValue},
- {five, dynamicValue}, {one, one});
- equivalent = ValueBoundsConstraintSet::areEquivalentSlices(&context, slice,
- differentSlice);
- ASSERT_TRUE(succeeded(equivalent));
- EXPECT_FALSE(*equivalent);
-
- // Distinct dynamic values continue to use the ValueBounds fallback.
- HyperrectangularSlice unknownSlice({zero, otherDynamicValue},
- {four, dynamicValue}, {one, one});
- equivalent = ValueBoundsConstraintSet::areEquivalentSlices(&context, slice,
- unknownSlice);
- EXPECT_TRUE(failed(equivalent));
-}
-
-} // namespace
More information about the Mlir-commits
mailing list