This is an archive of the discontinued LLVM Phabricator instance.

[NPM] Automatic 'opt' pipeline reducer script.
ClosedPublic

Authored by markus on Oct 1 2021, 1:13 AM.

Details

Summary
Script for automatic 'opt' pipeline reduction for when using the new
pass-manager (NPM). Based around the '-print-pipeline-passes' option.

The reduction algorithm consists of several phases (steps).

Step #0: Verify that input fails with the given pipeline and make note of the
error code.

Step #1: Split pipeline in two starting from front and move forward as long as
first pipeline exits normally and the second pipeline fails with the expected
error code. Move on to step #2 with the IR from the split point and the
pipeline from the second invocation.

Step #2: Remove passes from end of the pipeline as long as the pipeline fails
with the expected error code.

Step #3: Make several sweeps over the remaining pipeline trying to remove one
pass at a time. Repeat sweeps until unable to remove any more passes.

Usage example:
./utils/reduce_pipeline.py --opt-binary=./build-all-Debug/bin/opt --input=input.ll --output=output.ll --passes=PIPELINE [EXTRA-OPT-ARGS ...]

Diff Detail

Event Timeline

markus requested review of this revision.Oct 1 2021, 1:13 AM
markus created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptOct 1 2021, 1:13 AM
markus added a comment.Oct 1 2021, 1:24 AM

For testing the following can be tried. First re-introduce a bug in opt by reverting the following revert

commit 1fbdbb559569641f6d509b569966901c8fb02b63
Author: Florian Hahn <flo@fhahn.com>
Date:   Thu Sep 30 18:52:38 2021 +0100

    Revert "Recommit "[SCEV] Look through single value PHIs." (take 2)"

    This reverts commit 764d9aa97905f202385b4f25f8d234630b4feef3.

    This patch exposed a few additional cases where SCEV expressions are not
    properly invalidated.

    See PR52024, PR52023.

then running

./utils/reduce_pipeline.py --opt-binary=../build-debug/bin/opt --input=bbi-60925.ll --output=test2.ll --passes='canonicalize-aliases,objc-arc-apelim,cgscc(require<no-op-cgscc>,argpromotion,invalidate<all>,no-op-cgscc),objc-arc-apelim,function(function(aa-eval,loop-mssa(lnicm,licm,loop-instsimplify,indvars,loop-idiom),loop(indvars,require<iv-users>,loop-unroll-and-jam,simple-loop-unswitch<nontrivial>,loop-unroll-full),invalidate<all>)),function(early-cse<memssa>,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,early-cse<memssa>,verify<memoryssa>,loop-mssa(require<pass-instrumentation>,loop-deletion),alignment-from-assumptions)'


should result in

The following extra args will be passed to opt: []
---Starting step #0---
-passes="canonicalize-aliases,objc-arc-apelim,cgscc(require<no-op-cgscc>,argpromotion,invalidate<all>,no-op-cgscc),objc-arc-apelim,function(function(aa-eval,loop-mssa(lnicm,licm,loop-instsimplify,indvars,loop-idiom),loop(indvars,require<iv-users>,loop-unroll-and-jam,simple-loop-unswitch<nontrivial>,loop-unroll-full),invalidate<all>)),function(early-cse<memssa>,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,early-cse<memssa>,verify<memoryssa>,loop-mssa(require<pass-instrumentation>,loop-deletion),alignment-from-assumptions)"
---Starting step #1---
-passes="function(function(loop-mssa(lnicm,licm,loop-instsimplify,indvars,loop-idiom),loop(indvars,require<iv-users>,loop-unroll-and-jam,simple-loop-unswitch<nontrivial>,loop-unroll-full),invalidate<all>)),function(early-cse<memssa>,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,early-cse<memssa>,verify<memoryssa>,loop-mssa(require<pass-instrumentation>,loop-deletion),alignment-from-assumptions)"
---Starting step #2---
-passes="function(function(loop-mssa(lnicm,licm,loop-instsimplify,indvars,loop-idiom),loop(indvars,require<iv-users>,loop-unroll-and-jam,simple-loop-unswitch<nontrivial>,loop-unroll-full)))"
---Starting step #3---
-passes="function(function(loop-mssa(licm,loop-instsimplify,indvars),loop(indvars,simple-loop-unswitch<nontrivial>,loop-unroll-full)))"
---FINISHED---
Wrote output to 'test2.ll'.
-passes="function(function(loop-mssa(licm,loop-instsimplify,indvars),loop(indvars,simple-loop-unswitch<nontrivial>,loop-unroll-full)))"
markus edited the summary of this revision. (Show Details)Oct 1 2021, 1:29 AM
markus edited the summary of this revision. (Show Details)
markus updated this revision to Diff 376492.Oct 1 2021, 5:38 AM

Added some docstrings.

We could have a test by passing a fake --opt-binary that checks the -passes it receives and returns 0 or 1 by checking that some arbitrary set of passes is in the -passes pipeline

markus added a comment.Oct 1 2021, 9:30 AM

I thought about that too but where do we put tests for scripts in llvm/utils?

I've done https://reviews.llvm.org/D107184 before, basically put tests in their own directory.

markus added a comment.Oct 1 2021, 9:57 AM

Ok, cool. I guess it is sufficient to have the tests separated like that since they only need to be run when changes are made to the script.

markus updated this revision to Diff 376856.Oct 4 2021, 4:15 AM

Something like this and then perhaps add a few more tests and documenting them a bit?

fhahn added a subscriber: fhahn.Oct 4 2021, 5:03 AM

Great to see progress on this! For a bit of extra convenience, it might be helpful to accept -passes=defaults<O3> & co and automatically translate that to the explicit pass invocation.

markus added a comment.Oct 4 2021, 5:36 AM

Great to see progress on this! For a bit of extra convenience, it might be helpful to accept -passes=defaults<O3> & co and automatically translate that to the explicit pass invocation.

One can always do e.g. ./utils/reduce_pipeline.py --opt-binary=../build-debug/bin/opt --input=bbi-60925.ll --output=test2.ll --passes=$(../build-debug/bin/opt -passes='default<O3>' -print-pipeline-passes -disable-output bbi-60925.ll) but I agree that is a bit inconvenient and requires a bit of redundant typing.
Maybe it is worth it to have the script automatically invoke opt one time at the start to expand the pipeline with -print-pipeline-passes, if the pipeline is already expanded it should simply be an identity operation.

Great to see progress on this! For a bit of extra convenience, it might be helpful to accept -passes=defaults<O3> & co and automatically translate that to the explicit pass invocation.

One can always do e.g. ./utils/reduce_pipeline.py --opt-binary=../build-debug/bin/opt --input=bbi-60925.ll --output=test2.ll --passes=$(../build-debug/bin/opt -passes='default<O3>' -print-pipeline-passes -disable-output bbi-60925.ll) but I agree that is a bit inconvenient and requires a bit of redundant typing.
Maybe it is worth it to have the script automatically invoke opt one time at the start to expand the pipeline with -print-pipeline-passes, if the pipeline is already expanded it should simply be an identity operation.

+1

markus updated this revision to Diff 377146.Oct 5 2021, 3:57 AM

Added option for automatic expansion of default pipelines. E.g. now one can do

./utils/reduce_pipeline.py --opt-binary=../build-debug/bin/opt --input=bbi-60925.ll --output=test2.ll --passes='default<O3>' --expand-passes

and that will expand the pipeline (using a separate opt invocation with -print-pipeline-passes) before starting the reduction. In this particular case there will be no reduction as the crash does not reproduce with the default pipeline but that is a different matter. One test has been added for the expansion using fake_opt.py.

aeubanks accepted this revision.Oct 5 2021, 5:21 PM

looks good, thanks!

llvm/utils/reduce_pipeline.py
46

I think automatically doing this would be a bit simpler, but not a huge deal

113

very unlikely that this will matter, but perhaps pruning empty pass managers might cause crashes to go away, checking before pruning would be nice

This revision is now accepted and ready to land.Oct 5 2021, 5:21 PM

Thanks for reviewing!

llvm/utils/reduce_pipeline.py
46

I'll negate the option so it is on by default but possible to disable if it breaks for some reason.

113

Agree that seems unlikely but I'll add a second option for disabling the pruning just in case.

This revision was automatically updated to reflect the committed changes.