diff --git a/mlir/docs/Tools/MLIRREDUCE.md b/mlir/docs/Tools/MLIRREDUCE.md new file mode 100644 --- /dev/null +++ b/mlir/docs/Tools/MLIRREDUCE.md @@ -0,0 +1,120 @@ +# MLIR Reduce + +[TOC] + +A mlir module may contain unexpected behaviors after series of transformations. +To root cause the problem or help verification after fixes, we may want to have +a smaller case to work with. This document describes how we can narrow down a +mlir module. + +## MLIR Reduce + +`mlir-reduce` supports reducing the module in several ways, e.g., rewrite +complicated patterns into simpler form. To use it, the first thing you need to +do is, provide a command which tells if a module is still the interesting case +as the original module. Afterwards, select your reduction strategy then +`mlir-reduce` will do the remining works for you. It's similar to +[bugpoint](https://llvm.org/docs/CommandGuide/bugpoint.html). + +### Remove redundant operations + +`mlir-reduce` will try to remove a redundant operation by either eliminating it +directly or applying some patterns. This is the most aggressive reduction way +as it may result in an invalid module and we may end up retaining the error +message. To avoid that, `mlir-reduce` always checks the validity and it expects +the user will provide a valid module as well. + +### Reduce complicated patterns into simpler forms + +In some cases, you may want to rewrite an operation into a form you know which +will not affect the problem you're debugging and it's simpler and smaller. For +example, you may want to rewrite a tensor with unknown rank into a +constant rank one like tensor<1xi32>. This may introduce further reduction +chances because of precise type information. + +MLIR supports abundant dialects and `mlir-reduce` supports custom rewrite +patterns for every dialect as well. 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 passes + +MLIR provides amount of tranformation passes and some of them are useful for +reducing the module size, e.g., Symbol-DCE. You can just use them to reduce the +module. + +## How to Use it + +So far we provide two modes, the first one is reduction-tree, it will generate +several reduced modules and try to do further reduction in between them. It will +form a tree structure which tells how each intermediate module is reduced. +According to different tree traversal mode, it may lead to different result. You +can run with `-reduction-tree='traversal-mode=0'` for example. + +The second mode is opt-reduction-pass, it applies the given passes to reduce the +module. Run it with arg `-opt-reduction-pass='opt-pass=symbol-dce'`. + +### Write the script for testing interesting + +As mentioned, you need to provide a command to hint `mlir-reduce` which case +you're intersting. For each intermediate module generated during reduction, +`mlir-reduce` will run the command over the intermediate module, return 1 for +interesting case, 0 otherwise. The sample script, + +```shell +mlir-opt -convert-vector-to-spirv $1 | grep "failed to materialize" +if [[ $? -eq 0 ]]; then + exit 1 +else + exit 0 +fi +``` + +The sample command looks like `mlir-reduce $MLIR_MODULE +-reduction-tree='traversal-mode=0 test=$TEST_SCRIPT'` note that the `test` +argument is part of the mode argument. + +### Use with custom dialects + +To run with custom dialects, you need to build your own `mlir-reduce` and load +the desired dialects. You need to 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); + MLIRContext context(registry); + return failed(mlirReduceMain(argc, argv, context)); +} + +``` + +## Future works + +`mlir-reudce` is missing several features, +* `-reduction-tree` now only supports `Single-Path` traversal mode, extends it + with different traveral strategies may reduce the module better. +* Doesn't keep the intermediate optimal reduced module. The reduction process + may take a quite long time, it'll be better to interrupt it and we still can + get a reduced module so far. +* Can't select the reduction patterns through command-line. For different cases, + we may only want to apply the part of reduction patterns.