Affine map lower/upper bound affine map definition

Hi all,

I’m trying to understand the affine.for's loop bound syntax:

lower-bound ::= `max`? affine-map-attribute dim-and-symbol-use-list | shorthand-bound
upper-bound ::= `min`? affine-map-attribute dim-and-symbol-use-list | shorthand-bound

To my understanding, the lower bound can either be a shorthand with SSA id/integer, or the max of an affine-map application. I don’t get why the lower-bound is the max of an affine-map application, and the upper-bound is the min of an affine-map application, seems like it should be the other way around? When would it be useful to define loop bound with affine map application?

Also, does affine-map-attribute here mean the affine map is attached as an attribute to the affine.for operation? Can I attach other types of attribute to affine.for?

Thanks,
Niansong

Right.

Because a lower bound of the form a >= max(b,c) can be expressed as a conjuction a >= b && a >= c, and an upper bound of the form d < min(e,f) can be similarly expressed as a conjunction d < e && d < f. The inverse would use disjunctions (“or” operator) that would make the iteration domain not expressible as a convex set, which in turn breaks the requirement of the underlying polyhedral abstraction. So no, it should not be the other way around.

Whenever you want the affine analyses to be able to reason about the bound… We don’t want to (and actually cannot using the code available in upstream MLIR) infer the closed affine expression form from individual arithmetic operations.

Yes.

You can attach any attribute to any operation. That being said, many operations have inherent attributes that impact their semantics, and require those attributes to be present and have a specific type (see MLIR Language Reference - MLIR). This is the case of affine.for that requires the bounds to be AffineMapAttr so you cannot use other attributes to denote maps.

1 Like

@ftynse Thank you very much, the answer is very clear.

I have a followup question on attaching attribute to affine.for:

I’m building a dialect that would operate transformations on affine.for loops. Therefore, I would need to specify which loop to operate. Is it possible to define a “loop id variable” then attach it to affine.for operation, so that I can use the variable to refer to the target loop?

I suspect that it is impossible to attach such “loop id variables” as attributes without making intrusive changes on affine.for's semantics. Is that the case?

Like I said, you can attach any attribute to any operation. Something like:

affine.for %i = 0 to 42  {
 // loop bodu here
} { mydialect.myattribute = "something random" }

should work. However, there is no guarantee that transformations preserve these attributes (consider the case of loop fusion, for example, it is unclear how to “fuse” names) so don’t mix existing passes with the ones that rely on this attribute being present.

Thank you very much for the clarification.

I tried the code above and it works. I wonder if I can an SSA value as attribute? such as:

%0 = mydialect.myop : !mydialect.mytype
affine.for %i = 0 to 42 {
  // loop body
} { mydialect.myattr = %0 : !mydialect.mytype}

I tried this and got an error saying “expected non-function type”. Does it mean only basic type values like index, integer, string are allowed to attach as attribute?

Thanks

No. Attributes represent information known at compile time. SSA values only have a value at runtime.

We actually should but that is another discussion :smiley:

@chelini and @wsmoses have it in Polygeist, that’s why I explicitly mentioned upstream MLIR.

I was thinking more in terms of canonicalizations of arith ops into affine_apply, min, max and going towards scf.for being supported by affine analyses along the lines of Steps towards generalizing vectorization in Affine - #9 by nicolasvasilache.

Any interest in starting to contribute towards these goals?