llvm / llvm/llvm-project

[MLIR] `affine-loop-tiling` causes performance regression due to degenerate single-iteration loop

Open
#220,194 3 comments 0 reactions 0 assignees View on GitHub
mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Applying `-affine-loop-tile` to a 2D loop nest with an `affine.apply` between loops results in a performance regression and IR bloat.

Instead of tiling the 2D loop band or leaving it untouched, the pass transforms the code by introducing a redundant intermediate loop that executes exactly once (`arg1` to `arg1 + 1`). This fails to improve spatial locality while adding unnecessary loop control overhead.

### Repro

Run `mlir-opt --affine-loop-tile` on the following IR:

```llvm
#map = affine_map<(d0) -> (d0)>
module {
func.func @between_loops(%arg0: memref<64x64xf32>) {
%cst = arith.constant 4.000000e+00 : f32
affine.for %arg1 = 0 to 64 {
%0 = affine.apply #map(%arg1)
affine.for %arg2 = 0 to 64 {
affine.store %cst, %arg0[%0, %arg2] : memref<64x64xf32>
}
}
return
}
}
```

### Actual Output
```llvm
#map = affine_map<(d0) -> (d0)>
#map1 = affine_map<(d0) -> (d0 + 1)>
module {
func.func @between_loops(%arg0: memref<64x64xf32>) {
%cst = arith.constant 4.000000e+00 : f32
affine.for %arg1 = 0 to 64 {
affine.for %arg2 = #map(%arg1) to #map1(%arg1) {
%0 = affine.apply #map(%arg2)
affine.for %arg3 = 0 to 64 {
affine.store %cst, %arg0[%0, %arg3] : memref<64x64xf32>
}
}
}
return
}
}
```

### Expected Behavior
Either:
* Safely sink/ignore side-effect-free `affine.apply` and perform proper 2D tiling.
* Keep the IR unchanged (no-op) to avoid performance degradation when 2D tiling cannot be formed.

Version: b37a8a70cc98915d157cac2f049e9f46d6da8fe5

Contributor guide

Open the contributing guide

Research direction

Run mlir-opt --affine-loop-tile with the provided 2D loop nest and compare the transformed IR with the actual output. Start from the affine-loop-tile entry point and investigate how the affine.apply between loops affects tiling. Done means the pass either performs proper 2D tiling or leaves this case unchanged without introducing a single-iteration loop.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.