MLIR is sufficiently expressive to capture general multidimensional
array references without lose of information. Fortran pointers
may require speicial handling, as non-contiguous memory may be
described - forward or backward in each dimension.
p => A(I1:I2:-3, J1:j2, K1:k2:K3)
Fortran also permits empty arrays: call S(A(1:0)).
The BIG design chooses include:
- Augment LLVM IR to provide a more general GEP; continue loop restructuring
work in LLVM; MLIR may be used for additional high-level optimization.
OR
- Create a middle-LLVM that works on MLIR; do all loop restructuring here;
phase out existing LLVM loop restructuring .
OR
- adopt MLIR in LLVM … (a bridge too far).
In my mind, delinearization is a side issue. The central problem is retaining
subscript information needed for loop restructuring. Broad agreement is
clearly needed up front.
MLIR is sufficiently expressive to capture general multidimensional
array references without lose of information. Fortran pointers
may require speicial handling, as non-contiguous memory may be
described - forward or backward in each dimension.
p => A(I1:I2:-3, J1:j2, K1:k2:K3)
Can you explain what this does?
Fortran also permits empty arrays: call S(A(1:0)).
This should not be a problem since it will never be accessed.
The BIG design chooses include:
1. Augment LLVM IR to provide a more general GEP; continue loop restructuring
work in LLVM; MLIR may be used for additional high-level optimization.
OR
2. Create a middle-LLVM that works on MLIR; do all loop restructuring here;
phase out existing LLVM loop restructuring .
OR
3. adopt MLIR in LLVM ... (a bridge too far).
LLVM is not going to add a dependency on MLIR. I think their goals are
different. Regarding (2.), flang is going to generate MLIR and some
transformations can be done their. LLVM will still do loop
optimizations if only for languages that do not generate MLIR, or have
semantics that are not high-level enough to be represented by MLIR
high-level constructs such as "affine.for". Unless you add some
raising analysis (e.g for-loop to affine.for; delinearization), you
are still stuck on the lower level constructs without gaining
anything. Same is true if you do LLVM->MLIR->LLVM.
Having said that, I believe a loop-centric (in contrast to
control-flow) representation on which loop transformation work is a
good idea, which I am working on.
In my mind, delinearization is a side issue. The central problem is retaining
subscript information needed for loop restructuring. Broad agreement is
clearly needed up front.
Agreed, it is preferable to get this information from the front-end
(if available) than trying to recover it.
Michael
My 2c:
I think that path 3 is a bridge too far, and not worth considering in the immediate term.
#1 can definitely provide some value, but it isn’t clear that it provides a lot of utility and will take us to where we really need to go.
#2 is a promising direction if the “loop optimizer” is an optional component that (e.g.) clang would turn on and off monolithically with a flag. This path is structurally similar to the “enable poly” sort of design, with more flexibility on how the loop optimizer is implemented, and different compile time characteristics.
I think that path #2 is very interesting to scope out, and path #1 is interesting if there are very specific objectives that need to be reached for some purpose.
-Chris