Tips for debugging interactions between optimization passes


(Ben Ng) #1

I noticed that adding any semantic attribute to the two Array.append functions causes performance regressions in the Array benchmark. I think that it’s because the delayed inlining is blocking some array optimizations from happening.

What are some tips for debugging this sort of issue? There are a whole bunch of passes, and it’s difficult to figure out how they all interact. Reading the SIL generated after all optimizations have been run is pretty tedious, and I’m hoping that there’s a smarter way to go about this.

Can I get debug output that tells me what optimizations happened, and then diff the two outputs to find out what changed?

I also see a “Pass Pipeline” utility that looks useful, but it’s not obvious to me how to use it.

Thanks,

Ben Ng


(Arnold Schwaighofer) #2

Some documentation about debugging the swift compiler:

https://github.com/apple/swift/blob/master/docs/DebuggingTheCompiler.rst

Possibly, not all flags are documented:

https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassManager.cpp

To your specific question: We run several stages of the PerformanceInliner (https://github.com/apple/swift/blob/master/lib/SILOptimizer/Transforms/PerformanceInliner.cpp#L866) during our PassPipeline (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L221) . One stage — “the high-level stage” — inlines everything up to “@_semantics” functions. The next stage also inlines those.

- Run PerformanceInliner without-semantic-inlining (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L445)
- Run Optimizations that rely on seeing @semantics calls
- …
- Run PerformanceInline with-semantic-inlining (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L449)
- …

If you mark a function like append with @_semantics which internally has calls to @_semantics functions you prevent the optimizations that rely on having those calls exposed/inlined from working since those calls are now hidden behind an @_semantics function that did not get inlined.

The file https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp contains the code that sets up the pass pipeline. You can see which optimizations are scheduled in which order.

If you want to see a list of passes being run dynamically "-Xllvm -sil-print-pass-name" would be the flag to add, I think.

···

On Mar 3, 2017, at 9:58 AM, Ben Ng via swift-dev <swift-dev@swift.org> wrote:

I noticed that adding any semantic attribute to the two Array.append functions causes performance regressions in the Array benchmark. I think that it’s because the delayed inlining is blocking some array optimizations from happening.

What are some tips for debugging this sort of issue? There are a whole bunch of passes, and it’s difficult to figure out how they all interact. Reading the SIL generated after all optimizations have been run is pretty tedious, and I’m hoping that there’s a smarter way to go about this
.

Can I get debug output that tells me what optimizations happened, and then diff the two outputs to find out what changed?

I also see a “Pass Pipeline” utility that looks useful, but it’s not obvious to me how to use it.


(Ben Ng) #3

Arnold,

Thanks for the explanation of what’s going on here. Has the “optimizing a semantic function called from a semantic function” issue happened before, and is there a standard workaround?

I feel like adding an earlier optimization pipeline, and adding a new InlineSelection to the performance inliner, is a clunky solution to the problem.

Ben Ng

···

On Mar 3, 2017, 5:24 PM -0500, Arnold Schwaighofer <aschwaighofer@apple.com>, wrote:

Some documentation about debugging the swift compiler:

https://github.com/apple/swift/blob/master/docs/DebuggingTheCompiler.rst

Possibly, not all flags are documented:

https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassManager.cpp

To your specific question: We run several stages of the PerformanceInliner (https://github.com/apple/swift/blob/master/lib/SILOptimizer/Transforms/PerformanceInliner.cpp#L866) during our PassPipeline (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L221) . One stage — “the high-level stage” — inlines everything up to “@_semantics” functions. The next stage also inlines those.

- Run PerformanceInliner without-semantic-inlining (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L445)
- Run Optimizations that rely on seeing @semantics calls
- …
- Run PerformanceInline with-semantic-inlining (https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp#L449)
- …

If you mark a function like append with @_semantics which internally has calls to @_semantics functions you prevent the optimizations that rely on having those calls exposed/inlined from working since those calls are now hidden behind an @_semantics function that did not get inlined.

The file https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/PassPipeline.cpp contains the code that sets up the pass pipeline. You can see which optimizations are scheduled in which order.

If you want to see a list of passes being run dynamically "-Xllvm -sil-print-pass-name" would be the flag to add, I think.

> On Mar 3, 2017, at 9:58 AM, Ben Ng via swift-dev <swift-dev@swift.org> wrote:
>
> I noticed that adding any semantic attribute to the two Array.append functions causes performance regressions in the Array benchmark. I think that it’s because the delayed inlining is blocking some array optimizations from happening.
>
> What are some tips for debugging this sort of issue? There are a whole bunch of passes, and it’s difficult to figure out how they all interact. Reading the SIL generated after all optimizations have been run is pretty tedious, and I’m hoping that there’s a smarter way to go about this
> .
>
> Can I get debug output that tells me what optimizations happened, and then diff the two outputs to find out what changed?
>
> I also see a “Pass Pipeline” utility that looks useful, but it’s not obvious to me how to use it.