[llvm-dev] Asking for advice: how to best place the CoroSplit pass

via llvm-dev llvm-dev at lists.llvm.org
Thu Jan 28 13:52:14 PST 2021


Hi,

Do you have to use one CGSCCPipeline? If not, you could run function simplification passes on coroutines in CoroSplit pass like this:

- ModuleInlinerWrapperPass
    - A few global analysis
    - CGSCCPipeline
        - Inliner
        - FunctionSimplificationPipeline
    - CGSCCPipeline
        - CoroSplitPass
          - FunctionSimplificationPipeline (on coroutines)

- Yuanfang

________________________________________
From: llvm-dev <llvm-dev-bounces at lists.llvm.org> on behalf of Xun Li via llvm-dev <llvm-dev at lists.llvm.org>
Sent: Thursday, January 28, 2021 11:17 AM
To: Arthur Eubanks; llvm-dev
Subject: [llvm-dev] Asking for advice: how to best place the CoroSplit pass

Hi,

The current way of scheduling CoroSplit pass is not ideal, and in some
cases can lead to significant slowdown of the compiler.
I would like to ask for advice/feedback on what might be the best way
to structure the passes so that CoroSplit pass is put in the right
place. First of all, let me explain the current situation:

CoroSplit pass is a pass that splits a coroutine function into
multiple functions, in order to implement the semantics of coroutines.
Right now, CoroSplit pass is added in the InlinerPipeline, right after
the Inliner pass (PassBuilder::buildInlinerPipeline). So it looks like
this:
- ModuleInlinerWrapperPass
    - A few global analysis
    - CGSCCPipeline
        - Inliner
        - CoroSplitPass
        - FunctionSimplificationPipeline

It's important to note that when the first time a coroutine function
goes through CoroSplitPass, it will not be split. Instead, it will
just add its belonging SCC back to the pipeline and hence repeat the
entire CGSCC pipeline. The goal for doing so is to allow coroutines to
be optimized twice, first time before splitting, so that it can have
smaller frame size, and second time after splitting, so that the
splitted functions can get cleaned up.
Furthermore, CoroSplitPass needs to be in CGSCC pipeline in order to
enable coroutine elision (an important coroutine optimization to
reduce dynamic memory allocation), that is, we want to walk through
SCCs postorder so that functions can inline fully processed coroutines
and does CoroElision.
A side-effect of this structure, however, is that all the
non-coroutines that are in the same SCC of any coroutine will run
through Inliner twice. This can lead to unexpected slowdown if an
aggressive inlining threshold is used and generates unexpectedly large
functions. There is also not much benefit for coroutines to run
through Inliner pass twice either.

So the ideal goal looks like this:
For coroutine functions, run through:
  Inliner -> function simplification passes -> CoroSplit -> function
simplification passes
For non-coroutine functions, just run through as usual:
  Inliner -> function simplification passes.

The challenge is of course when they are in the same SCC it's hard to
separate them like this. Any thoughts on how we might be able to
achieve that?

--
Xun
_______________________________________________
LLVM Developers mailing list
llvm-dev at lists.llvm.org
https://urldefense.com/v3/__https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!JmoZiZGBv3RvKRSx!qfegBfVYmHpyOeEl2H6-MPpaD8wfAILrhhYIPSUcV-mLi3Xf-iji68ke2VLU56B5sg$


More information about the llvm-dev mailing list