Skip to content

SILGen: simplify cleanups and avoid critical edges. #19886

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 20, 2018
Merged

SILGen: simplify cleanups and avoid critical edges. #19886

merged 9 commits into from
Oct 20, 2018

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Oct 15, 2018

Keep the CFG in a valid, critical-edge free state that the SIL passes can handle.
Replace the ad-hoc on-the-fly cleanup block optimization with a more general block merging.

This simplifies SILGen now and will in subsequent commits allow massive simplification of SIL APIs and SIL passes.

Note that there's no downside to avoiding critical edges since they will be split anyway any various points in the SIL pipeline. However, there are many passes and utilities that can be made much simpler and more compute time and memory efficient.

@atrick
Copy link
Contributor Author

atrick commented Oct 15, 2018

@swift-ci test.

@atrick atrick requested a review from gottesmm October 15, 2018 18:26
@atrick
Copy link
Contributor Author

atrick commented Oct 15, 2018

@swift-ci benchmark.

@atrick
Copy link
Contributor Author

atrick commented Oct 15, 2018

@swift-ci test source compatibility.

@swift-ci
Copy link
Contributor

Build comment file:

Performance: -O

TEST OLD NEW DELTA RATIO
Regression
IterateData 1617 1782 +10.2% 0.91x
Improvement
StringHashing_abnormal 1461 1350 -7.6% 1.08x

Performance: -Osize

TEST OLD NEW DELTA RATIO
Regression
IterateData 1580 1807 +14.4% 0.87x
RemoveWhereFilterString 254 278 +9.4% 0.91x
CStringLongAscii 3278 3532 +7.7% 0.93x
Improvement
StringHashing_abnormal 1479 1359 -8.1% 1.09x

Performance: -Onone

TEST OLD NEW DELTA RATIO
Regression
ArrayOfPOD 781 859 +10.0% 0.91x (?)
How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false alarms. Unexpected regressions which are marked with '(?)' are probably noise. If you see regressions which you cannot explain you can try to run the benchmarks again. If regressions still show up, please consult with the performance team (@eeckstein).

Hardware Overview
  Model Name: Mac Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 64 GB

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 4b8d211c4a911e1cc0b39a8fb2b78d67ff2d7691

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 4b8d211c4a911e1cc0b39a8fb2b78d67ff2d7691

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you are dicing/splicing. I think I found some nice feedback. Want to give it to you before you slice and dice more.


SGF.B.emitBlock(TrueBB);
void Condition::enter(SILGenFunction &SGF, SILBasicBlock *destBB) {
assert(destBB && "Cannot enter a finished branch.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

branch => block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last one.

@atrick
Copy link
Contributor Author

atrick commented Oct 16, 2018

@gottesmm thanks for looking at this. I'd like to add feedback from review as separate commits so you don't need to re-review anything, but in this case, you hadn't finished the first round, and rebasing was part of the feedback. So the commits are all new, but nothing has changed functionally. Unfortunately, github isn't listing the commits in the right order anymore--trust that they are in the right order on the branch. Incidentally, I think it's better to clone-for-review for anything non-trivial.

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think 66bc68151dcfcc9c45869f08fab4220054adf12e should be before the previous one. What you would do is do the same change but make it so that you can pass false in that place. Then all usages of Condition pass false and we can eliminate that unfortunate code... no? I think together the end state is fine though.

Also:

  1. I wanted to give a +1 on a particular comment. It reads awesome!
  2. Found a typo.

Beyond that LGTM.

@@ -32,10 +32,12 @@ namespace Lowering {

/// A condition is the result of evaluating a boolean expression as
/// control flow.
///
/// For each Condition instance, `enterTrue` must be called before `complete`.
/// If `enterFalse` is skipped, then an empty fall-through block is created.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice comment!

/// complete - Complete this conditional execution. This should be called
/// only after all other calls on this Condition have been made.
/// This leaves SGF's SILGenBuilder at the continution block.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continution => continuation

@atrick
Copy link
Contributor Author

atrick commented Oct 16, 2018

@swift-ci benchmark.

@atrick
Copy link
Contributor Author

atrick commented Oct 16, 2018

Rerunning benchmarks to see if the few changes were spurious. Locally, I see only improvements. In particular, CI reported a 10% regression on IterateData, but I see a 10% improvement (although it seems very flaky). The only reason for regression would be incidental change to inlining because the cost model doesn't handle unconditional branches sensibly.

For code size, there is a 0.1% decrease in the benchmark suite and 0.1% increase in the stdlib.

@atrick
Copy link
Contributor Author

atrick commented Oct 16, 2018

@swift-ci benchmark.

@atrick
Copy link
Contributor Author

atrick commented Oct 16, 2018

I see no measurable impact on compile time.

@swift-ci
Copy link
Contributor

Build comment file:

Performance: -O

TEST OLD NEW DELTA RATIO
Improvement
CStringLongAscii 3533 3290 -6.9% 1.07x

Performance: -Osize

TEST OLD NEW DELTA RATIO
Regression
IterateData 1588 1770 +11.5% 0.90x (?)
Improvement
CStringLongAscii 3528 3276 -7.1% 1.08x
How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false alarms. Unexpected regressions which are marked with '(?)' are probably noise. If you see regressions which you cannot explain you can try to run the benchmarks again. If regressions still show up, please consult with the performance team (@eeckstein).

Hardware Overview
  Model Name: Mac Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 64 GB

@atrick
Copy link
Contributor Author

atrick commented Oct 19, 2018

@swift-ci test.

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Oct 19, 2018

@swift-ci test.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - e889f15b3f1068c074de88862a71ef16810959ee

This avoids critical edges, which will be split in the optimizer
anyway.
Allow a new SILBuilder to be created for an insertion point, while
providing all of its necessary context.

Ultimately, the builder's constructor should take an insertion point,
DebugLocation, and context. Then we won't need to pass SILLocation to
all of its methods.

This makes much more sense and is much safer than saving the insertion
point via an RAII object or defining a separate
SILBuilderWithScope. Those broken abstractions should go away.
This is the best way to inherit the provided SILGenBuilder's debug
scope and context, but insert at a different SIL location.
This code was attempting to generate a critical edge on one side of a
condition. Not only is that undesirable, but it breaks the abstraction
and results an a lot of complexity.

As usual, fixing critical edges simply means removing unnecessary complexity.
This is the one place in SILGen where we need to explicitly split the
critical edge. createBasicBlockAndBranch is a simply utility for that.
Avoid emitting unnecessary basic block for cleanup chains. This is a
general approach that handles all cases while simplifying SILGen
emission and keeping the CFG in a valid state during SILGen.
@atrick
Copy link
Contributor Author

atrick commented Oct 20, 2018

@swift-ci test.

@atrick
Copy link
Contributor Author

atrick commented Oct 20, 2018

@swift-ci test.

@atrick atrick merged commit c3fed98 into swiftlang:master Oct 20, 2018
@atrick atrick deleted the silgen-critedge branch September 3, 2019 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants