[Mlir-commits] [flang] [llvm] [mlir] [mlir][Arith] Move ceil/floor div expansion to ArithUtils. NFC (PR #231064)

Fangrui Song llvmlistbot at llvm.org
Tue Oct 13 21:01:44 PDT 2026


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/231064

>From c3b2b06ef5e9cc3f05303282583757f9eb71c6ca Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 11 Oct 2026 15:34:14 -0700
Subject: [PATCH 1/2] [mlir][Arith] Move ceil/floor div expansion to
 ArithUtils. NFC

MLIRArithToLLVM depends on MLIRArithTransforms only for
populateCeilFloorDivExpandOpsPatterns (#118839). MLIRArithTransforms
pulls in Bufferization, SCF, Shard, SparseTensor, Tensor, and Vector, so
every user of the LLVM lowering builds them. ClangIR reaches
MLIRArithToLLVM through MLIROpenMPToLLVM.

Move the three patterns and their populate function to MLIRArithUtils,
which MLIRArithTransforms now links. The declaration moves from
Arith/Transforms/Passes.h to Arith/Utils/Utils.h.

LLM aided. With -DCLANG_ENABLE_CIR=ON, clang links 16 fewer MLIR
libraries (90 -> 74), whose 64 object files take 147 s summed to
compile.
---
 .../mlir/Dialect/Arith/Transforms/Passes.h    |   3 -
 mlir/include/mlir/Dialect/Arith/Utils/Utils.h |   2 +
 .../Conversion/ArithToLLVM/ArithToLLVM.cpp    |   3 +-
 .../lib/Conversion/ArithToLLVM/CMakeLists.txt |   2 +-
 .../Dialect/Arith/Transforms/CMakeLists.txt   |   1 +
 .../Dialect/Arith/Transforms/ExpandOps.cpp    | 113 +---------------
 mlir/lib/Dialect/Arith/Utils/Utils.cpp        | 126 ++++++++++++++++++
 mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp |   1 +
 .../llvm-project-overlay/mlir/BUILD.bazel     |   2 +-
 .../mlir/test/BUILD.bazel                     |   1 +
 10 files changed, 136 insertions(+), 118 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
index 26832ba652680..7d7909c5f8231 100644
--- a/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Arith/Transforms/Passes.h
@@ -53,9 +53,6 @@ void populateEmulateUnsupportedFloatsPatterns(RewritePatternSet &patterns,
 /// float types.
 void populateEmulateUnsupportedFloatsLegality(ConversionTarget &target,
                                               const TypeConverter &converter);
-/// Add patterns to expand Arith ceil/floor division ops.
-void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns);
-
 /// Add patterns to expand Arith bf16 patterns to lower level bitcasts/shifts.
 void populateExpandBFloat16Patterns(RewritePatternSet &patterns);
 
diff --git a/mlir/include/mlir/Dialect/Arith/Utils/Utils.h b/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
index 4ebb7e16239f7..3594453a492a5 100644
--- a/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
@@ -129,6 +129,8 @@ struct ArithIndexingBuilder : public ArithBuilder {
 };
 
 namespace arith {
+/// Add patterns to expand Arith ceil/floor division ops.
+void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns);
 
 // Build the product of a sequence.
 // If values = (v0, v1, ..., vn) than the returned
diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index bac19144d6ea7..82ff88f55228e 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -14,12 +14,13 @@
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/VectorPattern.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Arith/Transforms/Passes.h"
+#include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/TypeUtilities.h"
+#include "mlir/Pass/Pass.h"
 #include <type_traits>
 
 namespace mlir {
diff --git a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
index 8fdfa991a35d3..d445cbe2f1260 100644
--- a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
@@ -13,7 +13,7 @@ add_mlir_conversion_library(MLIRArithToLLVM
   LINK_LIBS PUBLIC
   MLIRArithAttrToLLVMConversion
   MLIRArithDialect
-  MLIRArithTransforms
+  MLIRArithUtils
   MLIRAnalysis
   MLIRDataLayoutInterfaces
   MLIRLLVMCommonConversion
diff --git a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
index 637e16a3963d6..3f850589d4166 100644
--- a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
@@ -20,6 +20,7 @@ add_mlir_dialect_library(MLIRArithTransforms
   LINK_LIBS PUBLIC
   MLIRAnalysis
   MLIRArithDialect
+  MLIRArithUtils
   MLIRBufferizationDialect
   MLIRBufferizationTransforms
   MLIRFuncDialect
diff --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
index 2e02d44bdbe2c..829f568e33e6b 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/Arith/Utils/Utils.h"
 #include "mlir/Dialect/Vector/IR/VectorDialect.h"
 #include "mlir/IR/BuiltinTypeInterfaces.h"
 #include "mlir/IR/Location.h"
@@ -67,111 +68,6 @@ static Type cloneToShapedType(Type cloneFrom, Type cloneTo) {
 
 namespace {
 
-/// Expands CeilDivUIOp (n, m) into
-///  n == 0 ? 0 : ((n-1) / m) + 1
-struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
-  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);
-    Value compare =
-        arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
-    Value one = createConst(loc, a.getType(), 1, rewriter);
-    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);
-    return success();
-  }
-};
-
-/// Expands CeilDivSIOp (a, b) into
-/// z = a / b
-/// if (z * b != a && (a < 0) == (b < 0)) {
-///   return z + 1;
-/// } else {
-///   return z;
-/// }
-struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
-  using Base::Base;
-  LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
-                                PatternRewriter &rewriter) const final {
-    Location loc = op.getLoc();
-    Type type = op.getType();
-    Value a = op.getLhs();
-    Value b = op.getRhs();
-
-    Value zero = createConst(loc, type, 0, rewriter);
-    Value one = createConst(loc, type, 1, rewriter);
-
-    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
-    Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
-    Value notEqualDivisor = arith::CmpIOp::create(
-        rewriter, loc, arith::CmpIPredicate::ne, a, product);
-
-    Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       a, zero);
-    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       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);
-
-    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
-                                                 quotient);
-    return success();
-  }
-};
-
-/// Expands FloorDivSIOp (x, y) into
-/// z = x / y
-/// if (z * y != x && (x < 0) != (y < 0)) {
-///   return  z - 1;
-/// } else {
-///   return z;
-/// }
-struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
-  using Base::Base;
-  LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
-                                PatternRewriter &rewriter) const final {
-    Location loc = op.getLoc();
-    Type type = op.getType();
-    Value a = op.getLhs();
-    Value b = op.getRhs();
-
-    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
-    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 aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       a, zero);
-    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       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);
-    Value quotientMinusOne =
-        arith::AddIOp::create(rewriter, loc, quotient, minusOne);
-
-    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
-                                                 quotient);
-    return success();
-  }
-};
-
 template <typename OpTy, arith::CmpIPredicate pred>
 struct MaxMinIOpConverter : public OpRewritePattern<OpTy> {
 public:
@@ -1197,13 +1093,6 @@ struct ArithExpandOpsPass
 
 } // namespace
 
-void mlir::arith::populateCeilFloorDivExpandOpsPatterns(
-    RewritePatternSet &patterns) {
-  patterns
-      .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
-          patterns.getContext());
-}
-
 void mlir::arith::populateExpandBFloat16Patterns(RewritePatternSet &patterns) {
   patterns.add<BFloat16ExtFOpConverter, BFloat16TruncFOpConverter>(
       patterns.getContext());
diff --git a/mlir/lib/Dialect/Arith/Utils/Utils.cpp b/mlir/lib/Dialect/Arith/Utils/Utils.cpp
index 8cbddd920c91f..8b90be0f87346 100644
--- a/mlir/lib/Dialect/Arith/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Arith/Utils/Utils.cpp
@@ -16,6 +16,7 @@
 #include "mlir/Dialect/Complex/IR/Complex.h"
 #include "mlir/Dialect/Utils/StaticValueUtils.h"
 #include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/TypeUtilities.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVectorExtras.h"
 #include <numeric>
@@ -375,3 +376,128 @@ FloatType parseFloatType(MLIRContext *ctx, StringRef name) {
 }
 
 } // namespace mlir::arith
+
+/// Create an integer or index constant.
+static Value createConst(Location loc, Type type, int value,
+                         PatternRewriter &rewriter) {
+  auto attr = rewriter.getIntegerAttr(getElementTypeOrSelf(type), value);
+  if (auto shapedTy = dyn_cast<ShapedType>(type)) {
+    return arith::ConstantOp::create(rewriter, loc,
+                                     DenseElementsAttr::get(shapedTy, attr));
+  }
+  return arith::ConstantOp::create(rewriter, loc, attr);
+}
+
+namespace {
+/// Expands CeilDivUIOp (n, m) into
+///  n == 0 ? 0 : ((n-1) / m) + 1
+struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
+  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);
+    Value compare =
+        arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
+    Value one = createConst(loc, a.getType(), 1, rewriter);
+    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);
+    return success();
+  }
+};
+
+/// Expands CeilDivSIOp (a, b) into
+/// z = a / b
+/// if (z * b != a && (a < 0) == (b < 0)) {
+///   return z + 1;
+/// } else {
+///   return z;
+/// }
+struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
+  using Base::Base;
+  LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
+                                PatternRewriter &rewriter) const final {
+    Location loc = op.getLoc();
+    Type type = op.getType();
+    Value a = op.getLhs();
+    Value b = op.getRhs();
+
+    Value zero = createConst(loc, type, 0, rewriter);
+    Value one = createConst(loc, type, 1, rewriter);
+
+    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
+    Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
+    Value notEqualDivisor = arith::CmpIOp::create(
+        rewriter, loc, arith::CmpIPredicate::ne, a, product);
+
+    Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       a, zero);
+    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       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);
+
+    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
+                                                 quotient);
+    return success();
+  }
+};
+
+/// Expands FloorDivSIOp (x, y) into
+/// z = x / y
+/// if (z * y != x && (x < 0) != (y < 0)) {
+///   return  z - 1;
+/// } else {
+///   return z;
+/// }
+struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
+  using Base::Base;
+  LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
+                                PatternRewriter &rewriter) const final {
+    Location loc = op.getLoc();
+    Type type = op.getType();
+    Value a = op.getLhs();
+    Value b = op.getRhs();
+
+    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
+    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 aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       a, zero);
+    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       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);
+    Value quotientMinusOne =
+        arith::AddIOp::create(rewriter, loc, quotient, minusOne);
+
+    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
+                                                 quotient);
+    return success();
+  }
+};
+} // namespace
+
+void mlir::arith::populateCeilFloorDivExpandOpsPatterns(
+    RewritePatternSet &patterns) {
+  patterns
+      .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
+          patterns.getContext());
+}
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index fa07a94aba474..253f7343231cc 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -17,6 +17,7 @@
 #include "mlir/Conversion/UBToSPIRV/UBToSPIRV.h"
 #include "mlir/Conversion/VectorToSPIRV/VectorToSPIRV.h"
 #include "mlir/Dialect/Arith/Transforms/Passes.h"
+#include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
 #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index be52547a9da73..27251d9fa6526 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -8971,7 +8971,7 @@ cc_library(
         ":Analysis",
         ":ArithAttrToLLVMConversion",
         ":ArithDialect",
-        ":ArithTransforms",
+        ":ArithUtils",
         ":ConversionPassIncGen",
         ":ConvertToLLVMInterface",
         ":IR",
diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
index ee7215395cedf..f46074f0d1d1b 100644
--- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
@@ -554,6 +554,7 @@ cc_library(
         "//llvm:Support",
         "//mlir:ArithToSPIRV",
         "//mlir:ArithTransforms",
+        "//mlir:ArithUtils",
         "//mlir:ControlFlowToSPIRV",
         "//mlir:FuncDialect",
         "//mlir:FuncToSPIRV",

>From 439fd73d46723f427962fc77b08dd7293523cbd5 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 13 Oct 2026 21:01:31 -0700
Subject: [PATCH 2/2] rebase on 231743

---
 flang/lib/Optimizer/CodeGen/CodeGen.cpp       |   2 +-
 .../AttrToLLVMConverter.h                     |   6 +-
 .../ArithCommon/CeilFloorDivExpansion.h       |  21 +++
 mlir/include/mlir/Dialect/Arith/Utils/Utils.h |   2 -
 .../AttrToLLVMConverter.cpp                   |   2 +-
 .../Conversion/ArithAttrToLLVM/CMakeLists.txt |  10 ++
 .../lib/Conversion/ArithCommon/CMakeLists.txt |   9 +-
 .../ArithCommon/CeilFloorDivExpansion.cpp     | 139 ++++++++++++++++++
 .../Conversion/ArithToLLVM/ArithToLLVM.cpp    |   4 +-
 .../lib/Conversion/ArithToLLVM/CMakeLists.txt |   2 +-
 mlir/lib/Conversion/CMakeLists.txt            |   1 +
 .../ComplexToLLVM/ComplexToLLVM.cpp           |   2 +-
 mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp |   2 +-
 mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp |   2 +-
 .../VectorToLLVM/ConvertVectorToLLVM.cpp      |   2 +-
 .../Dialect/Arith/Transforms/CMakeLists.txt   |   2 +-
 .../Dialect/Arith/Transforms/ExpandOps.cpp    |   2 +-
 mlir/lib/Dialect/Arith/Utils/Utils.cpp        | 126 ----------------
 mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp |   2 +-
 .../llvm-project-overlay/mlir/BUILD.bazel     |  16 +-
 .../mlir/test/BUILD.bazel                     |   2 +-
 21 files changed, 204 insertions(+), 152 deletions(-)
 rename mlir/include/mlir/Conversion/{ArithCommon => ArithAttrToLLVM}/AttrToLLVMConverter.h (97%)
 create mode 100644 mlir/include/mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h
 rename mlir/lib/Conversion/{ArithCommon => ArithAttrToLLVM}/AttrToLLVMConverter.cpp (98%)
 create mode 100644 mlir/lib/Conversion/ArithAttrToLLVM/CMakeLists.txt
 create mode 100644 mlir/lib/Conversion/ArithCommon/CeilFloorDivExpansion.cpp

diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index b59996a9491e4..d72b1fb4a1d78 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -33,7 +33,7 @@
 #include "flang/Runtime/allocator-registry-consts.h"
 #include "flang/Runtime/descriptor-consts.h"
 #include "flang/Semantics/runtime-type-info.h"
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
 #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
 #include "mlir/Conversion/ComplexToROCDLLibraryCalls/ComplexToROCDLLibraryCalls.h"
diff --git a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h b/mlir/include/mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h
similarity index 97%
rename from mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
rename to mlir/include/mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h
index 23a4ef863b532..16985c1912ad5 100644
--- a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
+++ b/mlir/include/mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_CONVERSION_ARITHCOMMON_ATTRTOLLVMCONVERTER_H
-#define MLIR_CONVERSION_ARITHCOMMON_ATTRTOLLVMCONVERTER_H
+#ifndef MLIR_CONVERSION_ARITHATTRTOLLVM_ATTRTOLLVMCONVERTER_H
+#define MLIR_CONVERSION_ARITHATTRTOLLVM_ATTRTOLLVMCONVERTER_H
 
 #include "mlir/Dialect/Arith/IR/ArithAttributes.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
@@ -177,4 +177,4 @@ class AttrConverterConstrainedFPToLLVM {
 } // namespace arith
 } // namespace mlir
 
-#endif // MLIR_CONVERSION_ARITHCOMMON_ATTRTOLLVMCONVERTER_H
+#endif // MLIR_CONVERSION_ARITHATTRTOLLVM_ATTRTOLLVMCONVERTER_H
diff --git a/mlir/include/mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h b/mlir/include/mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h
new file mode 100644
index 0000000000000..1080f1a468e07
--- /dev/null
+++ b/mlir/include/mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_CONVERSION_ARITHCOMMON_CEILFLOORDIVEXPANSION_H
+#define MLIR_CONVERSION_ARITHCOMMON_CEILFLOORDIVEXPANSION_H
+
+namespace mlir {
+class RewritePatternSet;
+
+namespace arith {
+// Add patterns to expand Arith ceil/floor division ops.
+void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns);
+} // namespace arith
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_ARITHCOMMON_CEILFLOORDIVEXPANSION_H
diff --git a/mlir/include/mlir/Dialect/Arith/Utils/Utils.h b/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
index 3594453a492a5..4ebb7e16239f7 100644
--- a/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/Arith/Utils/Utils.h
@@ -129,8 +129,6 @@ struct ArithIndexingBuilder : public ArithBuilder {
 };
 
 namespace arith {
-/// Add patterns to expand Arith ceil/floor division ops.
-void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns);
 
 // Build the product of a sequence.
 // If values = (v0, v1, ..., vn) than the returned
diff --git a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp b/mlir/lib/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.cpp
similarity index 98%
rename from mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp
rename to mlir/lib/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.cpp
index cf60a048f782c..01b586e815ff9 100644
--- a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp
+++ b/mlir/lib/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 
 using namespace mlir;
 
diff --git a/mlir/lib/Conversion/ArithAttrToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithAttrToLLVM/CMakeLists.txt
new file mode 100644
index 0000000000000..888c45f2e52fe
--- /dev/null
+++ b/mlir/lib/Conversion/ArithAttrToLLVM/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_mlir_conversion_library(MLIRArithAttrToLLVMConversion
+  AttrToLLVMConverter.cpp
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRArithDialect
+  MLIRLLVMDialect
+  )
diff --git a/mlir/lib/Conversion/ArithCommon/CMakeLists.txt b/mlir/lib/Conversion/ArithCommon/CMakeLists.txt
index 888c45f2e52fe..dcea6095f6d83 100644
--- a/mlir/lib/Conversion/ArithCommon/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithCommon/CMakeLists.txt
@@ -1,10 +1,7 @@
-add_mlir_conversion_library(MLIRArithAttrToLLVMConversion
-  AttrToLLVMConverter.cpp
-
-  LINK_COMPONENTS
-  Core
+add_mlir_conversion_library(MLIRArithCommonConversion
+  CeilFloorDivExpansion.cpp
 
   LINK_LIBS PUBLIC
   MLIRArithDialect
-  MLIRLLVMDialect
+  MLIRIR
   )
diff --git a/mlir/lib/Conversion/ArithCommon/CeilFloorDivExpansion.cpp b/mlir/lib/Conversion/ArithCommon/CeilFloorDivExpansion.cpp
new file mode 100644
index 0000000000000..8b48ce88ead97
--- /dev/null
+++ b/mlir/lib/Conversion/ArithCommon/CeilFloorDivExpansion.cpp
@@ -0,0 +1,139 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/Conversion/ArithCommon/CeilFloorDivExpansion.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/IR/TypeUtilities.h"
+
+using namespace mlir;
+
+/// Create an integer or index constant.
+static Value createConst(Location loc, Type type, int value,
+                         PatternRewriter &rewriter) {
+  auto attr = rewriter.getIntegerAttr(getElementTypeOrSelf(type), value);
+  if (auto shapedTy = dyn_cast<ShapedType>(type)) {
+    return arith::ConstantOp::create(rewriter, loc,
+                                     DenseElementsAttr::get(shapedTy, attr));
+  }
+  return arith::ConstantOp::create(rewriter, loc, attr);
+}
+
+namespace {
+/// Expands CeilDivUIOp (n, m) into
+///  n == 0 ? 0 : ((n-1) / m) + 1
+struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
+  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);
+    Value compare =
+        arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
+    Value one = createConst(loc, a.getType(), 1, rewriter);
+    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);
+    return success();
+  }
+};
+
+/// Expands CeilDivSIOp (a, b) into
+/// z = a / b
+/// if (z * b != a && (a < 0) == (b < 0)) {
+///   return z + 1;
+/// } else {
+///   return z;
+/// }
+struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
+  using Base::Base;
+  LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
+                                PatternRewriter &rewriter) const final {
+    Location loc = op.getLoc();
+    Type type = op.getType();
+    Value a = op.getLhs();
+    Value b = op.getRhs();
+
+    Value zero = createConst(loc, type, 0, rewriter);
+    Value one = createConst(loc, type, 1, rewriter);
+
+    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
+    Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
+    Value notEqualDivisor = arith::CmpIOp::create(
+        rewriter, loc, arith::CmpIPredicate::ne, a, product);
+
+    Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       a, zero);
+    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       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);
+
+    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
+                                                 quotient);
+    return success();
+  }
+};
+
+/// Expands FloorDivSIOp (x, y) into
+/// z = x / y
+/// if (z * y != x && (x < 0) != (y < 0)) {
+///   return  z - 1;
+/// } else {
+///   return z;
+/// }
+struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
+  using Base::Base;
+  LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
+                                PatternRewriter &rewriter) const final {
+    Location loc = op.getLoc();
+    Type type = op.getType();
+    Value a = op.getLhs();
+    Value b = op.getRhs();
+
+    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
+    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 aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       a, zero);
+    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
+                                       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);
+    Value quotientMinusOne =
+        arith::AddIOp::create(rewriter, loc, quotient, minusOne);
+
+    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
+                                                 quotient);
+    return success();
+  }
+};
+} // namespace
+
+void mlir::arith::populateCeilFloorDivExpandOpsPatterns(
+    RewritePatternSet &patterns) {
+  patterns
+      .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
+          patterns.getContext());
+}
diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index 4cc50543343c2..9b523a52c09a3 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -9,12 +9,12 @@
 #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
 
 #include "mlir/Analysis/DataLayoutAnalysis.h"
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/VectorPattern.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
diff --git a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
index d445cbe2f1260..8d8b42da835bc 100644
--- a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
@@ -12,8 +12,8 @@ add_mlir_conversion_library(MLIRArithToLLVM
 
   LINK_LIBS PUBLIC
   MLIRArithAttrToLLVMConversion
+  MLIRArithCommonConversion
   MLIRArithDialect
-  MLIRArithUtils
   MLIRAnalysis
   MLIRDataLayoutInterfaces
   MLIRLLVMCommonConversion
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index cee1a069ad3b1..2af8209d107c4 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_subdirectory(AffineToStandard)
 add_subdirectory(AMDGPUToROCDL)
+add_subdirectory(ArithAttrToLLVM)
 add_subdirectory(ArithCommon)
 add_subdirectory(ArithToAMDGPU)
 add_subdirectory(ArithAndMathToAPFloat)
diff --git a/mlir/lib/Conversion/ComplexToLLVM/ComplexToLLVM.cpp b/mlir/lib/Conversion/ComplexToLLVM/ComplexToLLVM.cpp
index cbe5820300f82..94a07ad12bae3 100644
--- a/mlir/lib/Conversion/ComplexToLLVM/ComplexToLLVM.cpp
+++ b/mlir/lib/Conversion/ComplexToLLVM/ComplexToLLVM.cpp
@@ -8,7 +8,7 @@
 
 #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
 
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 #include "mlir/Conversion/ComplexCommon/DivisionConverter.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
diff --git a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
index ca7888a9aec76..17436cfe65c13 100644
--- a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
+++ b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
@@ -8,7 +8,7 @@
 
 #include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
 
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
diff --git a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
index bf63d6f118f67..55d7076163d40 100644
--- a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
+++ b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
@@ -8,7 +8,7 @@
 
 #include "mlir/Conversion/MathToXeVM/MathToXeVM.h"
 #include "mlir/Analysis/DataLayoutAnalysis.h"
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
index f28d163825fee..25646ec847744 100644
--- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
+++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
@@ -8,7 +8,7 @@
 
 #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h"
 
-#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
+#include "mlir/Conversion/ArithAttrToLLVM/AttrToLLVMConverter.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/PrintCallHelper.h"
 #include "mlir/Conversion/LLVMCommon/TypeConverter.h"
diff --git a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
index 3f850589d4166..7c889385b4ad6 100644
--- a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
@@ -19,8 +19,8 @@ add_mlir_dialect_library(MLIRArithTransforms
 
   LINK_LIBS PUBLIC
   MLIRAnalysis
+  MLIRArithCommonConversion
   MLIRArithDialect
-  MLIRArithUtils
   MLIRBufferizationDialect
   MLIRBufferizationTransforms
   MLIRFuncDialect
diff --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
index 829f568e33e6b..fd8e8e8368f6c 100644
--- a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
@@ -6,9 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/Arith/Transforms/Passes.h"
-#include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/Vector/IR/VectorDialect.h"
 #include "mlir/IR/BuiltinTypeInterfaces.h"
 #include "mlir/IR/Location.h"
diff --git a/mlir/lib/Dialect/Arith/Utils/Utils.cpp b/mlir/lib/Dialect/Arith/Utils/Utils.cpp
index 8b90be0f87346..8cbddd920c91f 100644
--- a/mlir/lib/Dialect/Arith/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Arith/Utils/Utils.cpp
@@ -16,7 +16,6 @@
 #include "mlir/Dialect/Complex/IR/Complex.h"
 #include "mlir/Dialect/Utils/StaticValueUtils.h"
 #include "mlir/IR/Diagnostics.h"
-#include "mlir/IR/TypeUtilities.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVectorExtras.h"
 #include <numeric>
@@ -376,128 +375,3 @@ FloatType parseFloatType(MLIRContext *ctx, StringRef name) {
 }
 
 } // namespace mlir::arith
-
-/// Create an integer or index constant.
-static Value createConst(Location loc, Type type, int value,
-                         PatternRewriter &rewriter) {
-  auto attr = rewriter.getIntegerAttr(getElementTypeOrSelf(type), value);
-  if (auto shapedTy = dyn_cast<ShapedType>(type)) {
-    return arith::ConstantOp::create(rewriter, loc,
-                                     DenseElementsAttr::get(shapedTy, attr));
-  }
-  return arith::ConstantOp::create(rewriter, loc, attr);
-}
-
-namespace {
-/// Expands CeilDivUIOp (n, m) into
-///  n == 0 ? 0 : ((n-1) / m) + 1
-struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
-  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);
-    Value compare =
-        arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
-    Value one = createConst(loc, a.getType(), 1, rewriter);
-    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);
-    return success();
-  }
-};
-
-/// Expands CeilDivSIOp (a, b) into
-/// z = a / b
-/// if (z * b != a && (a < 0) == (b < 0)) {
-///   return z + 1;
-/// } else {
-///   return z;
-/// }
-struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
-  using Base::Base;
-  LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
-                                PatternRewriter &rewriter) const final {
-    Location loc = op.getLoc();
-    Type type = op.getType();
-    Value a = op.getLhs();
-    Value b = op.getRhs();
-
-    Value zero = createConst(loc, type, 0, rewriter);
-    Value one = createConst(loc, type, 1, rewriter);
-
-    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
-    Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
-    Value notEqualDivisor = arith::CmpIOp::create(
-        rewriter, loc, arith::CmpIPredicate::ne, a, product);
-
-    Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       a, zero);
-    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       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);
-
-    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
-                                                 quotient);
-    return success();
-  }
-};
-
-/// Expands FloorDivSIOp (x, y) into
-/// z = x / y
-/// if (z * y != x && (x < 0) != (y < 0)) {
-///   return  z - 1;
-/// } else {
-///   return z;
-/// }
-struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
-  using Base::Base;
-  LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
-                                PatternRewriter &rewriter) const final {
-    Location loc = op.getLoc();
-    Type type = op.getType();
-    Value a = op.getLhs();
-    Value b = op.getRhs();
-
-    Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
-    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 aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       a, zero);
-    Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
-                                       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);
-    Value quotientMinusOne =
-        arith::AddIOp::create(rewriter, loc, quotient, minusOne);
-
-    rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
-                                                 quotient);
-    return success();
-  }
-};
-} // namespace
-
-void mlir::arith::populateCeilFloorDivExpandOpsPatterns(
-    RewritePatternSet &patterns) {
-  patterns
-      .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
-          patterns.getContext());
-}
diff --git a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
index 253f7343231cc..6b0d1368b0679 100644
--- a/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
+++ b/mlir/test/lib/Pass/TestConvertToSPIRVPass.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "mlir/Conversion/ArithCommon/CeilFloorDivExpansion.h"
 #include "mlir/Conversion/ArithToSPIRV/ArithToSPIRV.h"
 #include "mlir/Conversion/ControlFlowToSPIRV/ControlFlowToSPIRV.h"
 #include "mlir/Conversion/FuncToSPIRV/FuncToSPIRV.h"
@@ -17,7 +18,6 @@
 #include "mlir/Conversion/UBToSPIRV/UBToSPIRV.h"
 #include "mlir/Conversion/VectorToSPIRV/VectorToSPIRV.h"
 #include "mlir/Dialect/Arith/Transforms/Passes.h"
-#include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
 #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index bcf0e9045efde..c2751dae54aaf 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -8860,12 +8860,23 @@ cc_library(
 
 cc_library(
     name = "ArithAttrToLLVMConversion",
+    srcs = glob(["lib/Conversion/ArithAttrToLLVM/*.cpp"]),
+    hdrs = glob(["include/mlir/Conversion/ArithAttrToLLVM/*.h"]),
+    includes = ["include"],
+    deps = [
+        ":ArithDialect",
+        ":LLVMDialect",
+    ],
+)
+
+cc_library(
+    name = "ArithCommonConversion",
     srcs = glob(["lib/Conversion/ArithCommon/*.cpp"]),
     hdrs = glob(["include/mlir/Conversion/ArithCommon/*.h"]),
     includes = ["include"],
     deps = [
         ":ArithDialect",
-        ":LLVMDialect",
+        ":IR",
     ],
 )
 
@@ -8971,8 +8982,8 @@ cc_library(
     deps = [
         ":Analysis",
         ":ArithAttrToLLVMConversion",
+        ":ArithCommonConversion",
         ":ArithDialect",
-        ":ArithUtils",
         ":ConversionPassIncGen",
         ":ConvertToLLVMInterface",
         ":IR",
@@ -13460,6 +13471,7 @@ cc_library(
     includes = ["include"],
     deps = [
         ":Analysis",
+        ":ArithCommonConversion",
         ":ArithDialect",
         ":ArithPassIncGen",
         ":ArithUtils",
diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
index f46074f0d1d1b..43b1d601762e2 100644
--- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
@@ -552,9 +552,9 @@ cc_library(
     deps = [
         ":TestDialect",
         "//llvm:Support",
+        "//mlir:ArithCommonConversion",
         "//mlir:ArithToSPIRV",
         "//mlir:ArithTransforms",
-        "//mlir:ArithUtils",
         "//mlir:ControlFlowToSPIRV",
         "//mlir:FuncDialect",
         "//mlir:FuncToSPIRV",



More information about the Mlir-commits mailing list