[llvm-dev] Unwanted execution of pass

23 views
Skip to first unread message

Kai Plociennik via llvm-dev

unread,
Jan 19, 2022, 5:14:24 AM1/19/22
to llvm...@lists.llvm.org
Dear all,

since updating our downstream LLVM with the changes from llvm-project
made since may 2021, compiling code for our target crashes, since a pass
which was previously executed much later is now executed earlier. I do
not know how to figure out why this is the case, so I would like to ask
for hints on this.

Previously, the relevant part of the pass structure was as follows:

...
Call Graph SCC Pass Manager
Function Integration/Inlining
FunctionPass Manager
Dominator Tree Construction
Natural Loop Information
Scalar Evolution Analysis
SPU Arithmetic Instruction Validator
SPU offloading function dumper
Module Verifier
Lower Garbage Collection Instructions
Shadow Stack GC Lowering
Lower constant intrinsics
Remove unreachable blocks from the CFG
Expand vector predication intrinsics
Scalarize Masked Memory Intrinsics
Expand reduction intrinsics
Rewrite Symbols
FunctionPass Manager
Exception handling preparation
Safe Stack instrumentation pass
Insert stack protectors
Module Verifier
Dominator Tree Construction
Basic Alias Analysis (stateless AA impl)
Function Alias Analysis Results
Natural Loop Information
Post-Dominator Tree Construction
Branch Probability Analysis
Lazy Branch Probability Analysis
Lazy Block Frequency Analysis
SPU DAG->DAG Pattern Instruction Selection (X)
...

The pass marked with (X) is added via PassConfig::addInstSelector() and
is a MachineFunctionPass that depends on the fact that for all
functions, inlining has been executed successfully.

With the latest changes from llvm-project, the pass structure looks as
follows:

...
Call Graph SCC Pass Manager
Function Integration/Inlining
FunctionPass Manager
Dominator Tree Construction
Basic Alias Analysis (stateless AA impl)
Function Alias Analysis Results
Natural Loop Information
Lazy Branch Probability Analysis
Lazy Block Frequency Analysis
Optimization Remark Emitter
Combine redundant instructions
Simplify the CFG
Dominator Tree Construction
Natural Loop Information
Canonicalize natural loops
LCSSA Verifier
Loop-Closed SSA Form Pass
Basic Alias Analysis (stateless AA impl)
Function Alias Analysis Results
Scalar Evolution Analysis
Loop Pass Manager
Induction Variable Simplification
Simplify the CFG
Dead Code Elimination
Dominator Tree Construction
Natural Loop Information
Scalar Evolution Analysis
SPU IR Loop Info Extractor
Dominator Tree Construction
Natural Loop Information
Scalar Evolution Analysis
SPU Arithmetic Instruction Validator
SPU offloading function dumper
Module Verifier
Lower Garbage Collection Instructions
Shadow Stack GC Lowering
Lower constant intrinsics
Remove unreachable blocks from the CFG
Expand vector predication intrinsics
Scalarize Masked Memory Intrinsics
Expand reduction intrinsics
Exception handling preparation
Safe Stack instrumentation pass
Insert stack protectors
Module Verifier
Basic Alias Analysis (stateless AA impl)
Function Alias Analysis Results
Natural Loop Information
Post-Dominator Tree Construction
Branch Probability Analysis
Lazy Branch Probability Analysis
Lazy Block Frequency Analysis
SPU DAG->DAG Pattern Instruction Selection (X)
...

Notice that in contrast to before, looking at the indentation of the
passes, a lot more passes are now executed in the "FunctionPass Manager"
execution directly following "Function Integration/Inlining".
Especially, our (X) marked pass is now executed there.

I debugged into the execution of the passes. Previously, inlining was
run for a certain function A, which is called from B, and then for B
which successfully inlined A into B. Only after that, (X) was executed.
Now, inlining is run for A, and before inlining is run for B, our (X)
pass is run so that a crash results.

I would like to know why the structure changed, or how I can find out
exactly what causes the structure to be as it is, e.g., find out why a
certain pass is scheduled. I know that in principle this is because of
the analysis usage of the passes, but this did not change for our passes
so I am lost in finding out what happens here, because I don't
understand how the analysis usage of the many standard LLVM passes we
did not touch leads to the given structure at runtime.

Any help would be greatly appreciated.

Best regards,

Kai


--
Dr. Kai Plociennik
Fraunhofer-Institut für Techno- und Wirtschaftsmathematik ITWM
Competence Center High Performance Computing
Fraunhofer-Platz 1
67663 Kaiserslautern
Tel: +49 (0)631 31600 4081
mail: kai.plo...@itwm.fraunhofer.de
www.itwm.fraunhofer.de
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Arthur Eubanks via llvm-dev

unread,
Jan 19, 2022, 5:14:37 PM1/19/22
to Kai Plociennik, llvm...@lists.llvm.org
That would be due to https://reviews.llvm.org/D99707.
I'm not sure how that pipeline worked for you before. There should be a separation between the optimization and the codegen pipeline or else we'd be doing codegen passes while IR passes will run later. For an example see https://github.com/llvm/llvm-project/blob/a767ae2c5ce7615c188baabd3b6a52bb880de234/clang/lib/CodeGen/BackendUtil.cpp#L986 where the two pipelines are in two separate pass managers.

With the new pass manager, the two pipelines can't be in the same pass manager which makes the problem go away (and the new pass manager makes this sort of nesting explicit and thus harder to mess up even if we ever do get the codegen pipeline to run on the new pass manager).
Reply all
Reply to author
Forward
0 new messages