[Mlir-commits] [mlir] [mlir] Fix arith tensor constants (PR #206249)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jul 10 06:52:07 PDT 2026
https://github.com/mygitljf updated https://github.com/llvm/llvm-project/pull/206249
>From 3663396b2155970b6a4982ec42a0108c749df095 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Sat, 27 Jun 2026 20:57:43 +0000
Subject: [PATCH 1/4] [mlir] Fix arith tensor constants
---
mlir/include/mlir/Conversion/Passes.td | 2 +-
.../mlir/Dialect/Arith/Transforms/Passes.td | 2 +-
.../Conversion/ArithToLLVM/ArithToLLVM.cpp | 3 +-
.../lib/Conversion/ArithToLLVM/CMakeLists.txt | 1 +
.../Dialect/Arith/Transforms/ExpandOps.cpp | 29 +++++++--
.../ArithToLLVM/ceil-floor-div-tensor.mlir | 10 +++
.../test/Conversion/ConvertToSPIRV/arith.mlir | 8 +++
mlir/test/Dialect/Arith/expand-ops.mlir | 63 +++++++++++++++++++
mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp | 2 +
9 files changed, 111 insertions(+), 9 deletions(-)
create mode 100644 mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 550e6b853057d..23463342314b0 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -180,7 +180,7 @@ def ArithToLLVMConversionPass : Pass<"convert-arith-to-llvm"> {
let description = [{
This pass converts supported Arith ops to LLVM dialect instructions.
}];
- let dependentDialects = ["LLVM::LLVMDialect"];
+ let dependentDialects = ["LLVM::LLVMDialect", "tensor::TensorDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
diff --git a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.td b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.td
index 27e9146ec3606..2cee05914d6b5 100644
--- a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.td
@@ -13,7 +13,7 @@ include "mlir/Pass/PassBase.td"
def ArithExpandOpsPass : Pass<"arith-expand"> {
let summary = "Legalize Arith ops to be convertible to LLVM.";
- let dependentDialects = ["vector::VectorDialect"];
+ let dependentDialects = ["tensor::TensorDialect", "vector::VectorDialect"];
let options =
[Option<"includeBf16", "include-bf16", "bool", /*default=*/"false",
"Enable the BF16 expansion patterns">,
diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index 6bf0fe85bb62f..77e36b45a84af 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -17,6 +17,7 @@
#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/IR/TypeUtilities.h"
#include <type_traits>
@@ -736,7 +737,7 @@ struct ArithToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
: ConvertToLLVMPatternInterface(dialect) {}
void loadDependentDialects(MLIRContext *context) const final {
- context->loadDialect<LLVM::LLVMDialect>();
+ context->loadDialect<LLVM::LLVMDialect, tensor::TensorDialect>();
}
/// Hook for derived dialect interface to provide conversion patterns
diff --git a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
index 0a0e25e18b47a..955fcc397dd37 100644
--- a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
@@ -16,4 +16,5 @@ add_mlir_conversion_library(MLIRArithToLLVM
MLIRArithTransforms
MLIRLLVMCommonConversion
MLIRLLVMDialect
+ MLIRTensorDialect
)
diff --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
index c9217c57a5f25..d9cfa6bc78dc6 100644
--- a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
@@ -8,6 +8,7 @@
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Arith/Transforms/Passes.h"
+#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/IR/BuiltinTypeInterfaces.h"
#include "mlir/IR/Location.h"
@@ -34,6 +35,21 @@ static Value createConst(Location loc, Type type, int value,
return arith::ConstantOp::create(rewriter, loc, attr);
}
+/// Create an integer or index constant, using source as the dynamic shape
+/// source for ranked tensors whose splat cannot be represented as a dense
+/// attribute.
+static Value createConst(Location loc, Type type, int value,
+ PatternRewriter &rewriter, Value source) {
+ auto rankedTensorTy = dyn_cast<RankedTensorType>(type);
+ if (!rankedTensorTy || rankedTensorTy.hasStaticShape())
+ return createConst(loc, type, value, rewriter);
+
+ Value scalar =
+ createConst(loc, rankedTensorTy.getElementType(), value, rewriter);
+ return tensor::SplatOp::create(rewriter, loc, scalar,
+ tensor::getMixedSizes(rewriter, loc, source));
+}
+
/// Create an integer constant from an APInt.
static Value createAPIntConst(Location loc, Type type, const APInt &value,
PatternRewriter &rewriter) {
@@ -76,10 +92,10 @@ struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
Location loc = op.getLoc();
Value a = op.getLhs();
Value b = op.getRhs();
- Value zero = createConst(loc, a.getType(), 0, rewriter);
+ Value zero = createConst(loc, a.getType(), 0, rewriter, a);
Value compare =
arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
- Value one = createConst(loc, a.getType(), 1, rewriter);
+ Value one = createConst(loc, a.getType(), 1, rewriter, a);
Value minusOne = arith::SubIOp::create(rewriter, loc, a, one);
Value quotient = arith::DivUIOp::create(rewriter, loc, minusOne, b);
Value plusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
@@ -104,8 +120,8 @@ struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
Value a = op.getLhs();
Value b = op.getRhs();
- Value zero = createConst(loc, type, 0, rewriter);
- Value one = createConst(loc, type, 1, rewriter);
+ Value zero = createConst(loc, type, 0, rewriter, a);
+ Value one = createConst(loc, type, 1, rewriter, a);
Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
@@ -150,7 +166,7 @@ struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
Value notEqualDivisor = arith::CmpIOp::create(
rewriter, loc, arith::CmpIPredicate::ne, a, product);
- Value zero = createConst(loc, type, 0, rewriter);
+ Value zero = createConst(loc, type, 0, rewriter, a);
Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
a, zero);
@@ -162,7 +178,7 @@ struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
Value cond =
arith::AndIOp::create(rewriter, loc, notEqualDivisor, signOpposite);
- Value minusOne = createConst(loc, type, -1, rewriter);
+ Value minusOne = createConst(loc, type, -1, rewriter, a);
Value quotientMinusOne =
arith::AddIOp::create(rewriter, loc, quotient, minusOne);
@@ -826,6 +842,7 @@ struct ArithExpandOpsPass
arith::populateArithExpandOpsPatterns(patterns);
target.addLegalDialect<arith::ArithDialect>();
+ target.addLegalDialect<tensor::TensorDialect>();
target.addLegalDialect<vector::VectorDialect>();
// clang-format off
diff --git a/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir b/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
new file mode 100644
index 0000000000000..9d169bc60cade
--- /dev/null
+++ b/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
@@ -0,0 +1,10 @@
+// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm))" %s -split-input-file | FileCheck %s
+// RUN: mlir-opt --convert-to-llvm="filter-dialects=arith" --split-input-file %s | FileCheck %s
+
+// CHECK-LABEL: @ceildivui_dynamic_tensor
+// CHECK-SAME: %[[ARG0:.*]]: tensor<8x4x?xi64>) -> tensor<8x4x?xi64>
+func.func @ceildivui_dynamic_tensor(%arg0 : tensor<8x4x?xi64>) -> tensor<8x4x?xi64> {
+// CHECK: arith.ceildivui %[[ARG0]], %[[ARG0]] : tensor<8x4x?xi64>
+ %0 = arith.ceildivui %arg0, %arg0 : tensor<8x4x?xi64>
+ return %0: tensor<8x4x?xi64>
+}
diff --git a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
index fa204c4df8ace..343c34c9f0ba8 100644
--- a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
+++ b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
@@ -89,6 +89,14 @@ func.func @vector_ceildivsi(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> vector<
return %0 : vector<4xi32>
}
+// CHECK-LABEL: @dynamic_tensor_ceildivui
+// CHECK-SAME: (%[[LHS:.+]]: tensor<8x4x?xi32>, %[[RHS:.+]]: tensor<8x4x?xi32>)
+func.func @dynamic_tensor_ceildivui(%lhs: tensor<8x4x?xi32>, %rhs: tensor<8x4x?xi32>) -> tensor<8x4x?xi32> {
+ // CHECK: arith.ceildivui %[[LHS]], %[[RHS]] : tensor<8x4x?xi32>
+ %0 = arith.ceildivui %lhs, %rhs : tensor<8x4x?xi32>
+ return %0 : tensor<8x4x?xi32>
+}
+
// -----
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/Arith/expand-ops.mlir b/mlir/test/Dialect/Arith/expand-ops.mlir
index 75c4de2168761..80b6592417cc2 100644
--- a/mlir/test/Dialect/Arith/expand-ops.mlir
+++ b/mlir/test/Dialect/Arith/expand-ops.mlir
@@ -144,6 +144,69 @@ func.func @ceildivui_index(%arg0: index, %arg1: index) -> (index) {
// -----
+// CHECK-LABEL: func.func @ceildivui_dynamic_tensor(
+// CHECK-SAME: %[[ARG0:.*]]: tensor<8x4x?xi64>,
+// CHECK-SAME: %[[ARG1:.*]]: tensor<8x4x?xi64>) -> tensor<8x4x?xi64> {
+func.func @ceildivui_dynamic_tensor(%arg0: tensor<8x4x?xi64>, %arg1: tensor<8x4x?xi64>) -> tensor<8x4x?xi64> {
+ %res = arith.ceildivui %arg0, %arg1 : tensor<8x4x?xi64>
+ return %res : tensor<8x4x?xi64>
+// CHECK: %[[ZERO_SCALAR:.*]] = arith.constant 0 : i64
+// CHECK: %[[C2_IDX:.*]] = arith.constant 2 : index
+// CHECK: %[[ZERO_DIM:.*]] = tensor.dim %[[ARG0]], %[[C2_IDX]] : tensor<8x4x?xi64>
+// CHECK: %[[ZERO:.*]] = tensor.splat %[[ZERO_SCALAR]]{{\[}}%[[ZERO_DIM]]] : tensor<8x4x?xi64>
+// CHECK: %[[ISZERO:.*]] = arith.cmpi eq, %[[ARG0]], %[[ZERO]] : tensor<8x4x?xi64>
+// CHECK: %[[ONE_SCALAR:.*]] = arith.constant 1 : i64
+// CHECK: %[[C2_IDX_1:.*]] = arith.constant 2 : index
+// CHECK: %[[ONE_DIM:.*]] = tensor.dim %[[ARG0]], %[[C2_IDX_1]] : tensor<8x4x?xi64>
+// CHECK: %[[ONE:.*]] = tensor.splat %[[ONE_SCALAR]]{{\[}}%[[ONE_DIM]]] : tensor<8x4x?xi64>
+// CHECK: %[[SUB:.*]] = arith.subi %[[ARG0]], %[[ONE]] : tensor<8x4x?xi64>
+// CHECK: %[[DIV:.*]] = arith.divui %[[SUB]], %[[ARG1]] : tensor<8x4x?xi64>
+// CHECK: %[[ADD:.*]] = arith.addi %[[DIV]], %[[ONE]] : tensor<8x4x?xi64>
+// CHECK: %[[RES:.*]] = arith.select %[[ISZERO]], %[[ZERO]], %[[ADD]] : tensor<8x4x?xi1>, tensor<8x4x?xi64>
+}
+
+// -----
+
+// CHECK-LABEL: func.func @ceildivsi_dynamic_tensor(
+// CHECK-SAME: %[[ARG0:.*]]: tensor<8x?xi64>,
+// CHECK-SAME: %[[ARG1:.*]]: tensor<8x?xi64>) -> tensor<8x?xi64> {
+func.func @ceildivsi_dynamic_tensor(%arg0: tensor<8x?xi64>, %arg1: tensor<8x?xi64>) -> tensor<8x?xi64> {
+ %res = arith.ceildivsi %arg0, %arg1 : tensor<8x?xi64>
+ return %res : tensor<8x?xi64>
+// CHECK: %[[ZERO_SCALAR:.*]] = arith.constant 0 : i64
+// CHECK: %[[C1_IDX:.*]] = arith.constant 1 : index
+// CHECK: %[[ZERO_DIM:.*]] = tensor.dim %[[ARG0]], %[[C1_IDX]] : tensor<8x?xi64>
+// CHECK: %[[ZERO:.*]] = tensor.splat %[[ZERO_SCALAR]]{{\[}}%[[ZERO_DIM]]] : tensor<8x?xi64>
+// CHECK: %[[ONE_SCALAR:.*]] = arith.constant 1 : i64
+// CHECK: %[[C1_IDX_1:.*]] = arith.constant 1 : index
+// CHECK: %[[ONE_DIM:.*]] = tensor.dim %[[ARG0]], %[[C1_IDX_1]] : tensor<8x?xi64>
+// CHECK: %[[ONE:.*]] = tensor.splat %[[ONE_SCALAR]]{{\[}}%[[ONE_DIM]]] : tensor<8x?xi64>
+// CHECK: %[[DIV:.*]] = arith.divsi %[[ARG0]], %[[ARG1]] : tensor<8x?xi64>
+// CHECK: %[[ADD:.*]] = arith.addi %[[DIV]], %[[ONE]] : tensor<8x?xi64>
+}
+
+// -----
+
+// CHECK-LABEL: func.func @floordivsi_dynamic_tensor(
+// CHECK-SAME: %[[ARG0:.*]]: tensor<?x4xi64>,
+// CHECK-SAME: %[[ARG1:.*]]: tensor<?x4xi64>) -> tensor<?x4xi64> {
+func.func @floordivsi_dynamic_tensor(%arg0: tensor<?x4xi64>, %arg1: tensor<?x4xi64>) -> tensor<?x4xi64> {
+ %res = arith.floordivsi %arg0, %arg1 : tensor<?x4xi64>
+ return %res : tensor<?x4xi64>
+// CHECK: %[[DIV:.*]] = arith.divsi %[[ARG0]], %[[ARG1]] : tensor<?x4xi64>
+// CHECK: %[[ZERO_SCALAR:.*]] = arith.constant 0 : i64
+// CHECK: %[[C0_IDX:.*]] = arith.constant 0 : index
+// CHECK: %[[ZERO_DIM:.*]] = tensor.dim %[[ARG0]], %[[C0_IDX]] : tensor<?x4xi64>
+// CHECK: %[[ZERO:.*]] = tensor.splat %[[ZERO_SCALAR]]{{\[}}%[[ZERO_DIM]]] : tensor<?x4xi64>
+// CHECK: %[[NEG_ONE_SCALAR:.*]] = arith.constant -1 : i64
+// CHECK: %[[C0_IDX_1:.*]] = arith.constant 0 : index
+// CHECK: %[[NEG_ONE_DIM:.*]] = tensor.dim %[[ARG0]], %[[C0_IDX_1]] : tensor<?x4xi64>
+// CHECK: %[[NEG_ONE:.*]] = tensor.splat %[[NEG_ONE_SCALAR]]{{\[}}%[[NEG_ONE_DIM]]] : tensor<?x4xi64>
+// CHECK: %[[SUB_ONE:.*]] = arith.addi %[[DIV]], %[[NEG_ONE]] : tensor<?x4xi64>
+}
+
+// -----
+
// CHECK-LABEL: func @maximumf
func.func @maximumf(%a: f32, %b: f32) -> f32 {
%result = arith.maximumf %a, %b : f32
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index 3c99d3c5b60ce..58c66ab6f74c7 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -18,6 +18,7 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
+#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h"
#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
@@ -93,6 +94,7 @@ struct TestConvertToSPIRVPass final
}
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<spirv::SPIRVDialect>();
+ registry.insert<tensor::TensorDialect>();
registry.insert<vector::VectorDialect>();
}
>From 77863de1c79a7c5ae3d6f1b4cc8f62f9caf98498 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Fri, 10 Jul 2026 20:47:24 +0000
Subject: [PATCH 2/4] [mlir] Refine tensor splat expansion
---
mlir/include/mlir/Conversion/Passes.td | 2 +-
.../mlir/Dialect/Arith/Transforms/Passes.h | 3 +-
.../Conversion/ArithToLLVM/ArithToLLVM.cpp | 3 +-
.../lib/Conversion/ArithToLLVM/CMakeLists.txt | 1 -
.../Dialect/Arith/Transforms/ExpandOps.cpp | 117 ++++++++++++++----
.../ArithToLLVM/ceil-floor-div-tensor.mlir | 10 --
.../test/Conversion/ConvertToSPIRV/arith.mlir | 10 --
mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp | 2 -
8 files changed, 96 insertions(+), 52 deletions(-)
delete mode 100644 mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 23463342314b0..550e6b853057d 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -180,7 +180,7 @@ def ArithToLLVMConversionPass : Pass<"convert-arith-to-llvm"> {
let description = [{
This pass converts supported Arith ops to LLVM dialect instructions.
}];
- let dependentDialects = ["LLVM::LLVMDialect", "tensor::TensorDialect"];
+ let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
diff --git a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
index 5a07a01d0928a..11081342c2244 100644
--- a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
@@ -54,7 +54,8 @@ void populateEmulateUnsupportedFloatsPatterns(RewritePatternSet &patterns,
void populateEmulateUnsupportedFloatsLegality(ConversionTarget &target,
const TypeConverter &converter);
/// Add patterns to expand Arith ceil/floor division ops.
-void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns);
+void populateCeilFloorDivExpandOpsPatterns(
+ RewritePatternSet &patterns, bool enableDynamicTensorSplat = false);
/// Add patterns to expand Arith bf16 patterns to lower level bitcasts/shifts.
void populateExpandBFloat16Patterns(RewritePatternSet &patterns);
diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index 77e36b45a84af..6bf0fe85bb62f 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -17,7 +17,6 @@
#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/IR/TypeUtilities.h"
#include <type_traits>
@@ -737,7 +736,7 @@ struct ArithToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
: ConvertToLLVMPatternInterface(dialect) {}
void loadDependentDialects(MLIRContext *context) const final {
- context->loadDialect<LLVM::LLVMDialect, tensor::TensorDialect>();
+ context->loadDialect<LLVM::LLVMDialect>();
}
/// Hook for derived dialect interface to provide conversion patterns
diff --git a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
index 955fcc397dd37..0a0e25e18b47a 100644
--- a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
@@ -16,5 +16,4 @@ add_mlir_conversion_library(MLIRArithToLLVM
MLIRArithTransforms
MLIRLLVMCommonConversion
MLIRLLVMDialect
- MLIRTensorDialect
)
diff --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
index d9cfa6bc78dc6..b8c0e39dfddda 100644
--- a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
@@ -24,6 +24,10 @@ namespace arith {
using namespace mlir;
+namespace {
+
+enum class DynamicTensorConstantMaterialization { Disabled, TensorSplat };
+
/// Create an integer or index constant.
static Value createConst(Location loc, Type type, int value,
PatternRewriter &rewriter) {
@@ -38,16 +42,27 @@ static Value createConst(Location loc, Type type, int value,
/// Create an integer or index constant, using source as the dynamic shape
/// source for ranked tensors whose splat cannot be represented as a dense
/// attribute.
-static Value createConst(Location loc, Type type, int value,
- PatternRewriter &rewriter, Value source) {
+static FailureOr<Value>
+createConst(Location loc, Type type, int value, PatternRewriter &rewriter,
+ Value source,
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization) {
auto rankedTensorTy = dyn_cast<RankedTensorType>(type);
+ auto sourceTensorTy = dyn_cast<RankedTensorType>(source.getType());
if (!rankedTensorTy || rankedTensorTy.hasStaticShape())
return createConst(loc, type, value, rewriter);
+ if (!sourceTensorTy ||
+ rankedTensorTy.getShape() != sourceTensorTy.getShape() ||
+ dynamicTensorMaterialization !=
+ DynamicTensorConstantMaterialization::TensorSplat)
+ return failure();
+
+ // Dynamic shaped splats need runtime dimension operands from the source.
Value scalar =
createConst(loc, rankedTensorTy.getElementType(), value, rewriter);
return tensor::SplatOp::create(rewriter, loc, scalar,
- tensor::getMixedSizes(rewriter, loc, source));
+ tensor::getMixedSizes(rewriter, loc, source))
+ .getResult();
}
/// Create an integer constant from an APInt.
@@ -81,27 +96,42 @@ static Type cloneToShapedType(Type cloneFrom, Type cloneTo) {
return cloneTo;
}
-namespace {
-
/// Expands CeilDivUIOp (n, m) into
/// n == 0 ? 0 : ((n-1) / m) + 1
struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
+ CeilDivUIOpConverter(
+ MLIRContext *context,
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization)
+ : OpRewritePattern<arith::CeilDivUIOp>(context),
+ dynamicTensorMaterialization(dynamicTensorMaterialization) {}
+
using Base::Base;
LogicalResult matchAndRewrite(arith::CeilDivUIOp op,
PatternRewriter &rewriter) const final {
Location loc = op.getLoc();
Value a = op.getLhs();
Value b = op.getRhs();
- Value zero = createConst(loc, a.getType(), 0, rewriter, a);
- Value compare =
- arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
- Value one = createConst(loc, a.getType(), 1, rewriter, a);
- Value minusOne = arith::SubIOp::create(rewriter, loc, a, one);
+ FailureOr<Value> zero = createConst(loc, a.getType(), 0, rewriter, a,
+ dynamicTensorMaterialization);
+ if (failed(zero))
+ return rewriter.notifyMatchFailure(
+ op, "cannot materialize dynamically shaped tensor constants");
+ Value compare = arith::CmpIOp::create(rewriter, loc,
+ arith::CmpIPredicate::eq, a, *zero);
+ FailureOr<Value> one = createConst(loc, a.getType(), 1, rewriter, a,
+ dynamicTensorMaterialization);
+ if (failed(one))
+ return rewriter.notifyMatchFailure(
+ op, "cannot materialize dynamically shaped tensor constants");
+ Value minusOne = arith::SubIOp::create(rewriter, loc, a, *one);
Value quotient = arith::DivUIOp::create(rewriter, loc, minusOne, b);
- Value plusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
- rewriter.replaceOpWithNewOp<arith::SelectOp>(op, compare, zero, plusOne);
+ Value plusOne = arith::AddIOp::create(rewriter, loc, quotient, *one);
+ rewriter.replaceOpWithNewOp<arith::SelectOp>(op, compare, *zero, plusOne);
return success();
}
+
+private:
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization;
};
/// Expands CeilDivSIOp (a, b) into
@@ -112,6 +142,12 @@ struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
/// return z;
/// }
struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
+ CeilDivSIOpConverter(
+ MLIRContext *context,
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization)
+ : OpRewritePattern<arith::CeilDivSIOp>(context),
+ dynamicTensorMaterialization(dynamicTensorMaterialization) {}
+
using Base::Base;
LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
PatternRewriter &rewriter) const final {
@@ -120,8 +156,13 @@ struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
Value a = op.getLhs();
Value b = op.getRhs();
- Value zero = createConst(loc, type, 0, rewriter, a);
- Value one = createConst(loc, type, 1, rewriter, a);
+ FailureOr<Value> zero =
+ createConst(loc, type, 0, rewriter, a, dynamicTensorMaterialization);
+ FailureOr<Value> one =
+ createConst(loc, type, 1, rewriter, a, dynamicTensorMaterialization);
+ if (failed(zero) || failed(one))
+ return rewriter.notifyMatchFailure(
+ op, "cannot materialize dynamically shaped tensor constants");
Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
@@ -129,21 +170,25 @@ struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
rewriter, loc, arith::CmpIPredicate::ne, a, product);
Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
- a, zero);
+ a, *zero);
Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
- b, zero);
+ b, *zero);
Value signEqual = arith::CmpIOp::create(
rewriter, loc, arith::CmpIPredicate::eq, aNeg, bNeg);
Value cond =
arith::AndIOp::create(rewriter, loc, notEqualDivisor, signEqual);
- Value quotientPlusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
+ Value quotientPlusOne =
+ arith::AddIOp::create(rewriter, loc, quotient, *one);
rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
quotient);
return success();
}
+
+private:
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization;
};
/// Expands FloorDivSIOp (x, y) into
@@ -154,6 +199,12 @@ struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
/// return z;
/// }
struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
+ FloorDivSIOpConverter(
+ MLIRContext *context,
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization)
+ : OpRewritePattern<arith::FloorDivSIOp>(context),
+ dynamicTensorMaterialization(dynamicTensorMaterialization) {}
+
using Base::Base;
LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
PatternRewriter &rewriter) const final {
@@ -166,26 +217,37 @@ struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
Value notEqualDivisor = arith::CmpIOp::create(
rewriter, loc, arith::CmpIPredicate::ne, a, product);
- Value zero = createConst(loc, type, 0, rewriter, a);
+ FailureOr<Value> zero =
+ createConst(loc, type, 0, rewriter, a, dynamicTensorMaterialization);
+ if (failed(zero))
+ return rewriter.notifyMatchFailure(
+ op, "cannot materialize dynamically shaped tensor constants");
Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
- a, zero);
+ a, *zero);
Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
- b, zero);
+ b, *zero);
Value signOpposite = arith::CmpIOp::create(
rewriter, loc, arith::CmpIPredicate::ne, aNeg, bNeg);
Value cond =
arith::AndIOp::create(rewriter, loc, notEqualDivisor, signOpposite);
- Value minusOne = createConst(loc, type, -1, rewriter, a);
+ FailureOr<Value> minusOne =
+ createConst(loc, type, -1, rewriter, a, dynamicTensorMaterialization);
+ if (failed(minusOne))
+ return rewriter.notifyMatchFailure(
+ op, "cannot materialize dynamically shaped tensor constants");
Value quotientMinusOne =
- arith::AddIOp::create(rewriter, loc, quotient, minusOne);
+ arith::AddIOp::create(rewriter, loc, quotient, *minusOne);
rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
quotient);
return success();
}
+
+private:
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization;
};
template <typename OpTy, arith::CmpIPredicate pred>
@@ -921,10 +983,14 @@ struct ArithExpandOpsPass
} // namespace
void mlir::arith::populateCeilFloorDivExpandOpsPatterns(
- RewritePatternSet &patterns) {
+ RewritePatternSet &patterns, bool enableDynamicTensorSplat) {
+ DynamicTensorConstantMaterialization dynamicTensorMaterialization =
+ enableDynamicTensorSplat
+ ? DynamicTensorConstantMaterialization::TensorSplat
+ : DynamicTensorConstantMaterialization::Disabled;
patterns
.add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
- patterns.getContext());
+ patterns.getContext(), dynamicTensorMaterialization);
}
void mlir::arith::populateExpandBFloat16Patterns(RewritePatternSet &patterns) {
@@ -954,7 +1020,8 @@ void mlir::arith::populateExpandFlushDenormalsPatterns(
}
void mlir::arith::populateArithExpandOpsPatterns(RewritePatternSet &patterns) {
- populateCeilFloorDivExpandOpsPatterns(patterns);
+ populateCeilFloorDivExpandOpsPatterns(patterns,
+ /*enableDynamicTensorSplat=*/true);
populateExpandScalingExtTruncPatterns(patterns);
// clang-format off
patterns.add<
diff --git a/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir b/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
deleted file mode 100644
index 9d169bc60cade..0000000000000
--- a/mlir/test/Conversion/ArithToLLVM/ceil-floor-div-tensor.mlir
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm))" %s -split-input-file | FileCheck %s
-// RUN: mlir-opt --convert-to-llvm="filter-dialects=arith" --split-input-file %s | FileCheck %s
-
-// CHECK-LABEL: @ceildivui_dynamic_tensor
-// CHECK-SAME: %[[ARG0:.*]]: tensor<8x4x?xi64>) -> tensor<8x4x?xi64>
-func.func @ceildivui_dynamic_tensor(%arg0 : tensor<8x4x?xi64>) -> tensor<8x4x?xi64> {
-// CHECK: arith.ceildivui %[[ARG0]], %[[ARG0]] : tensor<8x4x?xi64>
- %0 = arith.ceildivui %arg0, %arg0 : tensor<8x4x?xi64>
- return %0: tensor<8x4x?xi64>
-}
diff --git a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
index 343c34c9f0ba8..65a8180e480b7 100644
--- a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
+++ b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
@@ -89,16 +89,6 @@ func.func @vector_ceildivsi(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> vector<
return %0 : vector<4xi32>
}
-// CHECK-LABEL: @dynamic_tensor_ceildivui
-// CHECK-SAME: (%[[LHS:.+]]: tensor<8x4x?xi32>, %[[RHS:.+]]: tensor<8x4x?xi32>)
-func.func @dynamic_tensor_ceildivui(%lhs: tensor<8x4x?xi32>, %rhs: tensor<8x4x?xi32>) -> tensor<8x4x?xi32> {
- // CHECK: arith.ceildivui %[[LHS]], %[[RHS]] : tensor<8x4x?xi32>
- %0 = arith.ceildivui %lhs, %rhs : tensor<8x4x?xi32>
- return %0 : tensor<8x4x?xi32>
-}
-
-// -----
-
//===----------------------------------------------------------------------===//
// arith bit ops
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index 58c66ab6f74c7..3c99d3c5b60ce 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -18,7 +18,6 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h"
#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
@@ -94,7 +93,6 @@ struct TestConvertToSPIRVPass final
}
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<spirv::SPIRVDialect>();
- registry.insert<tensor::TensorDialect>();
registry.insert<vector::VectorDialect>();
}
>From ae1131363388ffca29bb2d1c70e2d379a716701c Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Fri, 10 Jul 2026 21:30:10 +0000
Subject: [PATCH 3/4] [mlir] Restore SPIR-V test
---
mlir/test/Conversion/ConvertToSPIRV/arith.mlir | 10 ++++++++++
mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp | 2 ++
2 files changed, 12 insertions(+)
diff --git a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
index 65a8180e480b7..343c34c9f0ba8 100644
--- a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
+++ b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
@@ -89,6 +89,16 @@ func.func @vector_ceildivsi(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> vector<
return %0 : vector<4xi32>
}
+// CHECK-LABEL: @dynamic_tensor_ceildivui
+// CHECK-SAME: (%[[LHS:.+]]: tensor<8x4x?xi32>, %[[RHS:.+]]: tensor<8x4x?xi32>)
+func.func @dynamic_tensor_ceildivui(%lhs: tensor<8x4x?xi32>, %rhs: tensor<8x4x?xi32>) -> tensor<8x4x?xi32> {
+ // CHECK: arith.ceildivui %[[LHS]], %[[RHS]] : tensor<8x4x?xi32>
+ %0 = arith.ceildivui %lhs, %rhs : tensor<8x4x?xi32>
+ return %0 : tensor<8x4x?xi32>
+}
+
+// -----
+
//===----------------------------------------------------------------------===//
// arith bit ops
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index 3c99d3c5b60ce..58c66ab6f74c7 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -18,6 +18,7 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
+#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h"
#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
@@ -93,6 +94,7 @@ struct TestConvertToSPIRVPass final
}
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<spirv::SPIRVDialect>();
+ registry.insert<tensor::TensorDialect>();
registry.insert<vector::VectorDialect>();
}
>From 4f6a92bef6a65f92a103adb2c4a6c8211ea31352 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Fri, 10 Jul 2026 21:54:16 +0000
Subject: [PATCH 4/4] [mlir] Drop SPIR-V tensor test
---
mlir/test/Conversion/ConvertToSPIRV/arith.mlir | 8 --------
mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp | 2 --
2 files changed, 10 deletions(-)
diff --git a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
index 343c34c9f0ba8..fa204c4df8ace 100644
--- a/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
+++ b/mlir/test/Conversion/ConvertToSPIRV/arith.mlir
@@ -89,14 +89,6 @@ func.func @vector_ceildivsi(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> vector<
return %0 : vector<4xi32>
}
-// CHECK-LABEL: @dynamic_tensor_ceildivui
-// CHECK-SAME: (%[[LHS:.+]]: tensor<8x4x?xi32>, %[[RHS:.+]]: tensor<8x4x?xi32>)
-func.func @dynamic_tensor_ceildivui(%lhs: tensor<8x4x?xi32>, %rhs: tensor<8x4x?xi32>) -> tensor<8x4x?xi32> {
- // CHECK: arith.ceildivui %[[LHS]], %[[RHS]] : tensor<8x4x?xi32>
- %0 = arith.ceildivui %lhs, %rhs : tensor<8x4x?xi32>
- return %0 : tensor<8x4x?xi32>
-}
-
// -----
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index 58c66ab6f74c7..3c99d3c5b60ce 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -18,7 +18,6 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h"
#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
@@ -94,7 +93,6 @@ struct TestConvertToSPIRVPass final
}
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<spirv::SPIRVDialect>();
- registry.insert<tensor::TensorDialect>();
registry.insert<vector::VectorDialect>();
}
More information about the Mlir-commits
mailing list