2021-06-29 18:03:30 +08:00
|
|
|
# MLIR Reduce
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
|
|
An MLIR input may trigger bugs after series of transformations. To root cause
|
|
|
|
the problem or help verification after fixes, developers want to be able to
|
|
|
|
reduce the size of a reproducer for a bug. This document describes
|
|
|
|
`mlir-reduce`, which is similar to
|
|
|
|
[bugpoint](https://llvm.org/docs/CommandGuide/bugpoint.html), a tool that can
|
|
|
|
reduce the size of the input needed to trigger the error.
|
|
|
|
|
|
|
|
`mlir-reduce` supports reducing the input in several ways, including simply
|
|
|
|
deleting code not required to reproduce an error, applying the reducer
|
|
|
|
patterns heuristically or run with optimization passes to reduce the input. To
|
|
|
|
use it, the first thing you need to do is, provide a command which tells if an
|
|
|
|
input is interesting, e.g., exhibits the characteristics that you would like to
|
|
|
|
focus on. For example, you may want to see if `mlir-opt` invocation fails after
|
|
|
|
it runs on the certain MLIR input. Afterwards, select your reduction strategy
|
2021-10-29 15:19:11 +08:00
|
|
|
then `mlir-reduce` will do the remaining works for you.
|
2021-06-29 18:03:30 +08:00
|
|
|
|
|
|
|
## How to Use it
|
|
|
|
|
2021-07-09 08:00:36 +08:00
|
|
|
`mlir-reduce` adopts the reduction-tree algorithm to reduce the input. It
|
|
|
|
generates several reduced outputs and further reduces in between them according
|
2021-06-29 18:03:30 +08:00
|
|
|
to the tree traversal strategy. The different strategies may lead to different
|
2021-07-09 08:00:36 +08:00
|
|
|
results and different time complexity. You can run as
|
2021-06-29 18:03:30 +08:00
|
|
|
`-reduction-tree='traversal-mode=0'` to select the mode for example.
|
|
|
|
|
2021-07-09 08:00:36 +08:00
|
|
|
### Write the script for testing interestingness
|
2021-06-29 18:03:30 +08:00
|
|
|
|
2021-07-09 08:00:36 +08:00
|
|
|
As mentioned, you need to provide a command to `mlir-reduce` which identifies
|
|
|
|
cases you're interested in. For each intermediate output generated during
|
|
|
|
reduction, `mlir-reduce` will run the command over the it, the script should
|
|
|
|
returns 1 for interesting case, 0 otherwise. The sample script,
|
2021-06-29 18:03:30 +08:00
|
|
|
|
|
|
|
```shell
|
|
|
|
mlir-opt -convert-vector-to-spirv $1 | grep "failed to materialize"
|
|
|
|
if [[ $? -eq 1 ]]; then
|
|
|
|
exit 1
|
|
|
|
else
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
```
|
|
|
|
|
|
|
|
The sample usage will be like, note that the `test` argument is part of the mode
|
|
|
|
argument.
|
|
|
|
|
|
|
|
```shell
|
|
|
|
mlir-reduce $INPUT -reduction-tree='traversal-mode=0 test=$TEST_SCRIPT'
|
|
|
|
```
|
|
|
|
|
|
|
|
## Available reduction strategies
|
|
|
|
|
|
|
|
### Operation elimination
|
|
|
|
|
|
|
|
`mlir-reduce` will try to remove the operations directly. This is the most
|
|
|
|
aggressive reduction as it may result in an invalid output as long as it ends up
|
|
|
|
retaining the error message that the test script is interesting. To avoid that,
|
|
|
|
`mlir-reduce` always checks the validity and it expects the user will provide a
|
|
|
|
valid input as well.
|
|
|
|
|
|
|
|
### Rewrite patterns into simpler forms
|
|
|
|
|
|
|
|
In some cases, rewrite an operation into a simpler or smaller form can still
|
|
|
|
retain the interestingness. For example, `mlir-reduce` will try to rewrite a
|
|
|
|
`tensor<?xindex>` with unknown rank into a constant rank one like
|
|
|
|
`tensor<1xi32>`. Not only produce a simpler operation, it may introduce further
|
|
|
|
reduction chances because of precise type information.
|
|
|
|
|
|
|
|
MLIR supports dialects and `mlir-reduce` supports rewrite patterns for every
|
|
|
|
dialect as well. Which means you can have the dialect specific rewrite patterns.
|
|
|
|
To do that, you need to implement the `DialectReductionPatternInterface`. For
|
|
|
|
example,
|
|
|
|
|
|
|
|
```c++
|
|
|
|
#include "mlir/Reducer/ReductionPatternInterface.h"
|
|
|
|
|
|
|
|
struct MyReductionPatternInterface : public DialectReductionPatternInterface {
|
|
|
|
virtual void
|
|
|
|
populateReductionPatterns(RewritePatternSet &patterns) const final {
|
|
|
|
populateMyReductionPatterns(patterns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
`mlir-reduce` will call `populateReductionPatterns` to collect the reduction
|
|
|
|
rewrite patterns provided by each dialect. Here's a hint, if you use
|
|
|
|
[DRR](../DeclarativeRewrites.md) to write the reduction patterns, you can
|
|
|
|
leverage the method `populateWithGenerated` generated by `mlir-tblgen`.
|
|
|
|
|
|
|
|
### Reduce with built-in optimization passes
|
|
|
|
|
|
|
|
MLIR provides amount of transformation passes and some of them are useful for
|
|
|
|
reducing the input size, e.g., Symbol-DCE. `mlir-reduce` will schedule them
|
|
|
|
along with above two strategies.
|
|
|
|
|
|
|
|
## Build a custom mlir-reduce
|
|
|
|
|
|
|
|
In the cases of, 1. have defined a custom syntax, 2. the failure is specific to
|
|
|
|
certain dialects or 3. there's a dialect specific reducer patterns, you need to
|
|
|
|
build your own `mlir-reduce`. Link it with `MLIRReduceLib` and implement it
|
|
|
|
like,
|
|
|
|
|
|
|
|
```c++
|
|
|
|
#include "mlir/Tools/mlir-reduce/MlirReduceMain.h"
|
|
|
|
using namespace mlir;
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
DialectRegistry registry;
|
|
|
|
registerMyDialects(registry);
|
|
|
|
// Register the DialectReductionPatternInterface if any.
|
|
|
|
MLIRContext context(registry);
|
|
|
|
return failed(mlirReduceMain(argc, argv, context));
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
## Future works
|
|
|
|
|
|
|
|
`mlir-reduce` is missing several features,
|
|
|
|
|
|
|
|
* `-reduction-tree` now only supports `Single-Path` traversal mode, extends it
|
2021-10-29 15:19:11 +08:00
|
|
|
with different traversal strategies may reduce the input better.
|
|
|
|
* Produce the optimal result when interrupted. The reduction process may take
|
2021-06-29 18:03:30 +08:00
|
|
|
a quite long time, it'll be better to get an optimal result so far while an
|
2021-10-29 15:19:11 +08:00
|
|
|
interrupt is triggered.
|