Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[MLIR][SCF] Expose scf util functions in header file #138784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

Cubevoid
Copy link

@Cubevoid Cubevoid commented May 6, 2025

This patch exposes the delinearizeInductionVariable and getProductOfIntsOrIndexes helpers in the header file for the SCF utils, as these are useful for downstream users.

Additionally, getProductOfIntsOrIndexes will now constant-fold the generated arith::MulIOp.

Copy link

github-actions bot commented May 6, 2025

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented May 6, 2025

@llvm/pr-subscribers-mlir-scf

Author: Colin De Vlieghere (Cubevoid)

Changes

This patch exposes the delinearizeInductionVariable and getProductOfIntsOrIndexes helpers in the header file for the SCF utils, as these are useful for downstream users.

Additionally, getProductOfIntsOrIndexes will now constant-fold the generated arith::MulIOp.


Full diff: https://github.com/llvm/llvm-project/pull/138784.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Dialect/SCF/Utils/Utils.h (+17)
  • (modified) mlir/lib/Dialect/SCF/Utils/Utils.cpp (+8-16)
  • (modified) mlir/test/Dialect/SCF/transform-ops.mlir (+1-3)
diff --git a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
index e620067c15be9..c7a3208a4176e 100644
--- a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
@@ -148,6 +148,23 @@ void denormalizeInductionVariable(RewriterBase &rewriter, Location loc,
                                   Value normalizedIv, OpFoldResult origLb,
                                   OpFoldResult origStep);
 
+/// For each original loop, the value of the
+/// induction variable can be obtained by dividing the induction variable of
+/// the linearized loop by the total number of iterations of the loops nested
+/// in it modulo the number of iterations in this loop (remove the values
+/// related to the outer loops):
+///   iv_i = floordiv(iv_linear, product-of-loop-ranges-until-i) mod range_i.
+/// Compute these iteratively from the innermost loop by creating a "running
+/// quotient" of division by the range.
+/// Returns the delinearized induction variables and the preserved users.
+std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
+delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
+                             Value linearizedIv, ArrayRef<Value> ubs);
+
+/// Helper function to multiply a sequence of values.
+Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
+                                ArrayRef<Value> values);
+
 /// Tile a nest of standard for loops rooted at `rootForOp` by finding such
 /// parametric tile sizes that the outer loops have a fixed number of iterations
 /// as defined in `sizes`.
diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp
index e9471c1dbd0b7..42a27e5ff783d 100644
--- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp
@@ -17,6 +17,7 @@
 #include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/Dialect/Utils/StaticValueUtils.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/IRMapping.h"
 #include "mlir/IR/OpDefinition.h"
@@ -807,7 +808,7 @@ void mlir::denormalizeInductionVariable(RewriterBase &rewriter, Location loc,
 
 static OpFoldResult getProductOfIndexes(RewriterBase &rewriter, Location loc,
                                         ArrayRef<OpFoldResult> values) {
-  assert(!values.empty() && "unexecpted empty array");
+  assert(!values.empty() && "unexpected empty array");
   AffineExpr s0, s1;
   bindSymbols(rewriter.getContext(), s0, s1);
   AffineExpr mul = s0 * s1;
@@ -819,9 +820,8 @@ static OpFoldResult getProductOfIndexes(RewriterBase &rewriter, Location loc,
   return products;
 }
 
-/// Helper function to multiply a sequence of values.
-static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
-                                       ArrayRef<Value> values) {
+Value mlir::getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
+                                      ArrayRef<Value> values) {
   assert(!values.empty() && "unexpected empty list");
   if (getType(values.front()).isIndex()) {
     SmallVector<OpFoldResult> ofrs = getAsOpFoldResult(values);
@@ -835,7 +835,7 @@ static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
       continue;
     if (productOf)
       productOf =
-          rewriter.create<arith::MulIOp>(loc, productOf.value(), v).getResult();
+          rewriter.createOrFold<arith::MulIOp>(loc, productOf.value(), v);
     else
       productOf = v;
   }
@@ -848,17 +848,9 @@ static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
   return productOf.value();
 }
 
-/// For each original loop, the value of the
-/// induction variable can be obtained by dividing the induction variable of
-/// the linearized loop by the total number of iterations of the loops nested
-/// in it modulo the number of iterations in this loop (remove the values
-/// related to the outer loops):
-///   iv_i = floordiv(iv_linear, product-of-loop-ranges-until-i) mod range_i.
-/// Compute these iteratively from the innermost loop by creating a "running
-/// quotient" of division by the range.
-static std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
-delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
-                             Value linearizedIv, ArrayRef<Value> ubs) {
+std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
+mlir::delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
+                                   Value linearizedIv, ArrayRef<Value> ubs) {
 
   if (linearizedIv.getType().isIndex()) {
     Operation *delinearizedOp =
diff --git a/mlir/test/Dialect/SCF/transform-ops.mlir b/mlir/test/Dialect/SCF/transform-ops.mlir
index d9445182769e7..81462885dba4c 100644
--- a/mlir/test/Dialect/SCF/transform-ops.mlir
+++ b/mlir/test/Dialect/SCF/transform-ops.mlir
@@ -500,13 +500,11 @@ func.func @coalesce_i32_loops() {
   %1 = arith.constant 128 : i32
   %2 = arith.constant 2 : i32
   %3 = arith.constant 64 : i32
-  // CHECK:           %[[VAL_4:.*]] = arith.constant 64 : i32
   // CHECK:           %[[ZERO:.*]] = arith.constant 0 : i32
   // CHECK:           %[[ONE:.*]] = arith.constant 1 : i32
-  // CHECK:           %[[VAL_7:.*]] = arith.constant 32 : i32
   // CHECK:           %[[VAL_8:.*]] = arith.constant 0 : i32
   // CHECK:           %[[VAL_9:.*]] = arith.constant 1 : i32
-  // CHECK:           %[[UB:.*]] = arith.muli %[[VAL_4]], %[[VAL_7]] : i32
+  // CHECK:           %[[UB:.*]] = arith.constant 2048 : i32
   // CHECK:           scf.for %[[VAL_11:.*]] = %[[ZERO]] to %[[UB]] step %[[ONE]]  : i32 {
   scf.for %i = %0 to %1 step %2 : i32 {
     scf.for %j = %0 to %3 step %2 : i32 {

@llvmbot
Copy link
Member

llvmbot commented May 6, 2025

@llvm/pr-subscribers-mlir

Author: Colin De Vlieghere (Cubevoid)

Changes

This patch exposes the delinearizeInductionVariable and getProductOfIntsOrIndexes helpers in the header file for the SCF utils, as these are useful for downstream users.

Additionally, getProductOfIntsOrIndexes will now constant-fold the generated arith::MulIOp.


Full diff: https://github.com/llvm/llvm-project/pull/138784.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Dialect/SCF/Utils/Utils.h (+17)
  • (modified) mlir/lib/Dialect/SCF/Utils/Utils.cpp (+8-16)
  • (modified) mlir/test/Dialect/SCF/transform-ops.mlir (+1-3)
diff --git a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
index e620067c15be9..c7a3208a4176e 100644
--- a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
@@ -148,6 +148,23 @@ void denormalizeInductionVariable(RewriterBase &rewriter, Location loc,
                                   Value normalizedIv, OpFoldResult origLb,
                                   OpFoldResult origStep);
 
+/// For each original loop, the value of the
+/// induction variable can be obtained by dividing the induction variable of
+/// the linearized loop by the total number of iterations of the loops nested
+/// in it modulo the number of iterations in this loop (remove the values
+/// related to the outer loops):
+///   iv_i = floordiv(iv_linear, product-of-loop-ranges-until-i) mod range_i.
+/// Compute these iteratively from the innermost loop by creating a "running
+/// quotient" of division by the range.
+/// Returns the delinearized induction variables and the preserved users.
+std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
+delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
+                             Value linearizedIv, ArrayRef<Value> ubs);
+
+/// Helper function to multiply a sequence of values.
+Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
+                                ArrayRef<Value> values);
+
 /// Tile a nest of standard for loops rooted at `rootForOp` by finding such
 /// parametric tile sizes that the outer loops have a fixed number of iterations
 /// as defined in `sizes`.
diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp
index e9471c1dbd0b7..42a27e5ff783d 100644
--- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp
@@ -17,6 +17,7 @@
 #include "mlir/Dialect/Arith/Utils/Utils.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/Dialect/Utils/StaticValueUtils.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/IRMapping.h"
 #include "mlir/IR/OpDefinition.h"
@@ -807,7 +808,7 @@ void mlir::denormalizeInductionVariable(RewriterBase &rewriter, Location loc,
 
 static OpFoldResult getProductOfIndexes(RewriterBase &rewriter, Location loc,
                                         ArrayRef<OpFoldResult> values) {
-  assert(!values.empty() && "unexecpted empty array");
+  assert(!values.empty() && "unexpected empty array");
   AffineExpr s0, s1;
   bindSymbols(rewriter.getContext(), s0, s1);
   AffineExpr mul = s0 * s1;
@@ -819,9 +820,8 @@ static OpFoldResult getProductOfIndexes(RewriterBase &rewriter, Location loc,
   return products;
 }
 
-/// Helper function to multiply a sequence of values.
-static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
-                                       ArrayRef<Value> values) {
+Value mlir::getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
+                                      ArrayRef<Value> values) {
   assert(!values.empty() && "unexpected empty list");
   if (getType(values.front()).isIndex()) {
     SmallVector<OpFoldResult> ofrs = getAsOpFoldResult(values);
@@ -835,7 +835,7 @@ static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
       continue;
     if (productOf)
       productOf =
-          rewriter.create<arith::MulIOp>(loc, productOf.value(), v).getResult();
+          rewriter.createOrFold<arith::MulIOp>(loc, productOf.value(), v);
     else
       productOf = v;
   }
@@ -848,17 +848,9 @@ static Value getProductOfIntsOrIndexes(RewriterBase &rewriter, Location loc,
   return productOf.value();
 }
 
-/// For each original loop, the value of the
-/// induction variable can be obtained by dividing the induction variable of
-/// the linearized loop by the total number of iterations of the loops nested
-/// in it modulo the number of iterations in this loop (remove the values
-/// related to the outer loops):
-///   iv_i = floordiv(iv_linear, product-of-loop-ranges-until-i) mod range_i.
-/// Compute these iteratively from the innermost loop by creating a "running
-/// quotient" of division by the range.
-static std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
-delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
-                             Value linearizedIv, ArrayRef<Value> ubs) {
+std::pair<SmallVector<Value>, SmallPtrSet<Operation *, 2>>
+mlir::delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
+                                   Value linearizedIv, ArrayRef<Value> ubs) {
 
   if (linearizedIv.getType().isIndex()) {
     Operation *delinearizedOp =
diff --git a/mlir/test/Dialect/SCF/transform-ops.mlir b/mlir/test/Dialect/SCF/transform-ops.mlir
index d9445182769e7..81462885dba4c 100644
--- a/mlir/test/Dialect/SCF/transform-ops.mlir
+++ b/mlir/test/Dialect/SCF/transform-ops.mlir
@@ -500,13 +500,11 @@ func.func @coalesce_i32_loops() {
   %1 = arith.constant 128 : i32
   %2 = arith.constant 2 : i32
   %3 = arith.constant 64 : i32
-  // CHECK:           %[[VAL_4:.*]] = arith.constant 64 : i32
   // CHECK:           %[[ZERO:.*]] = arith.constant 0 : i32
   // CHECK:           %[[ONE:.*]] = arith.constant 1 : i32
-  // CHECK:           %[[VAL_7:.*]] = arith.constant 32 : i32
   // CHECK:           %[[VAL_8:.*]] = arith.constant 0 : i32
   // CHECK:           %[[VAL_9:.*]] = arith.constant 1 : i32
-  // CHECK:           %[[UB:.*]] = arith.muli %[[VAL_4]], %[[VAL_7]] : i32
+  // CHECK:           %[[UB:.*]] = arith.constant 2048 : i32
   // CHECK:           scf.for %[[VAL_11:.*]] = %[[ZERO]] to %[[UB]] step %[[ONE]]  : i32 {
   scf.for %i = %0 to %1 step %2 : i32 {
     scf.for %j = %0 to %3 step %2 : i32 {

Copy link
Contributor

@mfrancio mfrancio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

This patch exposes the `delinearizeInductionVariable` and
`getProductOfIntsOrIndexes` helpers in the header file for the SCF utils, as
these are useful for downstream users.

Additionally, `getProductOfIntsOrIndexes` will now constant-fold the generated
`arith::MulIOp`.
@Cubevoid Cubevoid force-pushed the mlir/scf/expose_utils_in_api branch from 5d2e83b to f0ecc8f Compare May 7, 2025 00:37
Copy link
Contributor

@MaheshRavishankar MaheshRavishankar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this you could just use affine.delinearize. I think I want even the upstream methods to use affine.delinearize

@Cubevoid
Copy link
Author

Cubevoid commented May 7, 2025

Instead of this you could just use affine.delinearize. I think I want even the upstream methods to use affine.delinearize

Good to know, thanks!

@Cubevoid Cubevoid closed this May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants