Skip to content

[mlir][affine] allow iter args as valid dims #139069

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

Merged
merged 1 commit into from
May 8, 2025
Merged

Conversation

metaflow
Copy link
Contributor

@metaflow metaflow commented May 8, 2025

that is effectivevely a revert of
7aabf47 for
mlir/lib/Dialect/Affine/IR/AffineOps.cpp

there are situations when iter args can be used as a dims. For example in
https://github.com/google/heir/blob/main/lib/Dialect/Polynomial/Conversions/PolynomialToModArith/PolynomialToModArith.cpp#L1036

rootExp and batchSize are iter args that are being used as dims and from the point of internal loops
they are fixed.

@llvmbot
Copy link
Member

llvmbot commented May 8, 2025

@llvm/pr-subscribers-mlir-affine

@llvm/pr-subscribers-mlir

Author: Mikhail Goncharov (metaflow)

Changes

that is effectivevely a revert of
7aabf47 for
mlir/lib/Dialect/Affine/IR/AffineOps.cpp

there are situations when iter args can be used as a dims. For example in
https://github.com/google/heir/blob/main/lib/Dialect/Polynomial/Conversions/PolynomialToModArith/PolynomialToModArith.cpp#L1036

rootExp and batchSize are iter args that are being used as dims and from the point of internal loops
they are fixed.


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

1 Files Affected:

  • (modified) mlir/lib/Dialect/Affine/IR/AffineOps.cpp (+6-7)
diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
index 65f85444e70db..eb23403a68813 100644
--- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
+++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
@@ -294,12 +294,10 @@ bool mlir::affine::isValidDim(Value value) {
     return isValidDim(value, getAffineScope(defOp));
 
   // This value has to be a block argument for an op that has the
-  // `AffineScope` trait or an induction var of an affine.for or
-  // affine.parallel.
-  if (isAffineInductionVar(value))
-    return true;
+  // `AffineScope` trait or for an affine.for or affine.parallel.
   auto *parentOp = llvm::cast<BlockArgument>(value).getOwner()->getParentOp();
-  return parentOp && parentOp->hasTrait<OpTrait::AffineScope>();
+  return parentOp && (parentOp->hasTrait<OpTrait::AffineScope>() ||
+                      isa<AffineForOp, AffineParallelOp>(parentOp));
 }
 
 // Value can be used as a dimension id iff it meets one of the following
@@ -318,9 +316,10 @@ bool mlir::affine::isValidDim(Value value, Region *region) {
 
   auto *op = value.getDefiningOp();
   if (!op) {
-    // This value has to be an induction var for an affine.for or an
+    // This value has to be a block argument for an affine.for or an
     // affine.parallel.
-    return isAffineInductionVar(value);
+    auto *parentOp = llvm::cast<BlockArgument>(value).getOwner()->getParentOp();
+    return isa<AffineForOp, AffineParallelOp>(parentOp);
   }
 
   // Affine apply operation is ok if all of its operands are ok.

@metaflow
Copy link
Contributor Author

metaflow commented May 8, 2025

need to update the test, hold on..

that is effectivevely a revert of
7aabf47 for
mlir/lib/Dialect/Affine/IR/AffineOps.cpp

As iter args can be used as a dims is some
situations. For example in

[heir PolynomialToModArith](https://github.com/google/heir/blob/main/lib/Dialect/Polynomial/Conversions/PolynomialToModArith/PolynomialToModArith.cpp#L1036)

`rootExp`` and `batchSize`` are iter args that are
being used as dims and from the point of internal
loops they are fixed.
@metaflow
Copy link
Contributor Author

metaflow commented May 8, 2025

cc @oowekyala please take a look

@metaflow
Copy link
Contributor Author

metaflow commented May 8, 2025

alright, I will merge as is to unblock builds, please feel free to follow up

@metaflow metaflow merged commit 5f9fd47 into llvm:main May 8, 2025
9 of 10 checks passed
@oowekyala
Copy link
Contributor

@metaflow thanks for fixing this so quickly. I wasn't aware of a use case for this.

@asraa
Copy link
Contributor

asraa commented May 9, 2025

Hey, HEIR maintainer here - I don't really know whether what we are doing (updating the upper bound using an operand from the iter_args) counts as an "affine" loop.

In that fastNTT algorithm, all the accessors are affine expressions of the induction var - so by that definition it seems like it might be an affine loop.

But the upper bound's expression uses loop-carried vars as operands and not just induction vars and constants. I don't know whether the loop-carried vars are considered to be regular enough that they can be used as operands to the bound maps.

I was thinking that if this change is valid to make reduce the scope of an affine for loop, I would have to rewrite this at a lower level, which I can do. But I don't know the "right" answer.

@ftynse
Copy link
Member

ftynse commented May 20, 2025

Haven't dug too deep into this, but IMO the original change that got reverted was in fact correct. Since we don't know how secondary iteration args evolve with loop iterations (e.g., the loop may be yielding the result of a function call or the state of a PRNG), we cannot statically represent them as an integer set bound by affine constraints, unlike primary iteration args where the evolution is clear.

@asraa
Copy link
Contributor

asraa commented May 20, 2025

I think that's fair - I'm happy to update our code to avoid using affine loops. In the end, this code is destined to lower to LLVM IR, and it really shouldn't matter if I use a lower level abstraction.

@ftynse
Copy link
Member

ftynse commented May 20, 2025

#140808. @asraa please let me know when you are done updating downstream.

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.

6 participants