llvm / llvm/llvm-project

Misbehavior in mlir::affine::createLoopUnrollPass

Open
#204,801 2 comments 0 reactions 0 assignees View on GitHub
mlir:affine
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

I believe the function `mlir::affine::createLoopUnrollPass` defined in `mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp` is not working correctly with argument `unrollFactor = -1`. The function checks for a value of -1, and passes on `unrollFactor = nullopt` to the pass constructor, which then gets transformed into the default value (in this case 4).

However, the value -1 for `unrollFactor` has the concrete meaning of unrolling the loop completely, as seen in the same file in `LoopUnroll::runOnAffineForOp`:
```cpp
// Unroll completely if full loop unroll was specified.
if (unrollFactor.getValue() == -1)
return loopUnrollFull(forOp);
```
It is not possible to reach this case when creating the pass via `mlir::affine::createLoopUnrollPass`.
In constructing a pass pipeline, we get the oddity:
```cpp
mlir::parsePassPipeline("func.func(affine-loop-unroll{unroll-factor=-1})", pm); // -1 means "unroll fully"
pm.addNestedPass(mlir::affine::createLoopUnrollPass(-1)); // -1 means "take the default value"
```

Recently, in #164658, the explicit option to unroll fully has been removed, so I believe this was when the bug was introduced.

If desired I can provide tests that document this, but they are a bit clumsy, and the issue is clear to see from the code.
I'd be happy to fix this, as I use this functionality in a project. I'd propose to either remove this function and have it be generated from tablegen with `LoopUnrollOptions` as argument, or to turn the `unrollFactor` into a `std::optional`.

Observed in revision `cf004c9003`.

Contributor guide

Open the contributing guide

Research direction

Start in mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp, comparing createLoopUnrollPass with LoopUnroll::runOnAffineForOp and how each handles unrollFactor = -1. Add regression coverage for the factory-created pass and verify that -1 produces the same full-unroll behavior as the parsed pass pipeline.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.