Skip to content

[inst-simplify] Update for OSSA #34559

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 3 commits into from
Dec 9, 2020
Merged

Conversation

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Nov 3, 2020

I am splitting this out and fixing some issues at atrick's request.

@gottesmm gottesmm requested review from atrick and meg-gupta November 3, 2020 19:15
Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

Reviewed the first half, not including SimplifyInstruction or SILCombine

atrick
atrick previously requested changes Nov 4, 2020
Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

I don't think you should handle .none as an ownership kind with special treatment. Converting to .none can be trivially handled before doing anything fancy. Converting from .none involves deciding the ownership of each use, which should be a trivial lattice join between the new kind and the operand's constraint. Then partitioning those uses uses into two (or three) separate kinds, and for each category reusing the same code "as-if" the original .none value were either owned or guaranteed.

@gottesmm gottesmm force-pushed the ossa-inst-simplify branch 2 times, most recently from 12e298d to 1c03b0d Compare November 5, 2020 01:13
@gottesmm
Copy link
Contributor Author

Going to rebase this.

…nstead of a SILInstructionVisitor.

Our worklist already uses values, so it makes sense to use a SILValueVisitor. It
will also let me throw in a few ARC dead argument elimination optimizations so
clean up a pattern from my ARC RAUW thing. Once we have simplify-cfg it will not
be needed, but I want to know I am good before I flip the switch.
@gottesmm gottesmm requested a review from atrick December 9, 2020 00:19
@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

I upstreamed and slimmed this down. I did it the way we talked about offline.

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

I think I also redid everything that were a problem.

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

@swift-ci test

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

@swift-ci benchmark

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

@swift-ci test source compatibility

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

preset=buildbot,tools=RA,stdlib=RD,test=non_executable
@swift-ci Please test with preset macOS

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

I am going to have to fight a little bit with MSVC looks like.

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

I am really curious what the benchmark results turn out. I diffed the text and there isn't any difference at -O anyways.

@swift-ci
Copy link
Contributor

swift-ci commented Dec 9, 2020

Performance: -O

Regression OLD NEW DELTA RATIO
String.data.LargeUnicode 110 120 +9.1% 0.92x (?)
String.data.Medium 109 118 +8.3% 0.92x (?)

Code size: -O

Performance: -Osize

Improvement OLD NEW DELTA RATIO
DataAppendDataSmallToSmall 4140 3760 -9.2% 1.10x (?)

Code size: -Osize

Performance: -Onone

Code size: -swiftlibs

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: 8-Core Intel Xeon E5
  Processor Speed: 3 GHz
  Number of Processors: 1
  Total Number of Cores: 8
  L2 Cache (per Core): 256 KB
  L3 Cache: 25 MB
  Memory: 16 GB

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

If all of the tests pass, I am going to fix the windows issue and then smoke test this in.

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

Looks good overall. I'm still reviewing the RAUW utility and lifetime extender.

Comment on lines +239 to +243
sil [ossa] @owned_to_unowned_negative_1 : $@convention(thin) (@guaranteed Klass) -> () {
bb0(%0 : @guaranteed $Klass):
%1 = copy_value %0 : $Klass
%2 = unchecked_ownership_conversion %1 : $Klass, @owned to @unowned
destroy_value %1 : $Klass
Copy link
Contributor

@atrick atrick Dec 9, 2020

Choose a reason for hiding this comment

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

I just want to make sure I understand that the original test case is actually valid SIL. By default, I assume all our .sil tests are valid patterns that we need to support in perpetuity.

As I asked about in another comment, if this is valid SIL, then what keeps the optimizer from trashing the unowned value (e.g. after inlining)?

I would like to assume that it's the programmers responsibility to keep the unowned value alive via some sort of fixed lifetime, but I don't know if that's actually how the instruction is used in practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nothing. Unowned means that you have to retain it before you use it as an owned or guaranteed value. Otherwise, you can just pass it off.

bool SemanticARCOptVisitor::visitUncheckedOwnershipConversionInst(
UncheckedOwnershipConversionInst *uoci) {
// Return false if we are supposed to only be running guaranteed opts.
if (ctx.onlyGuaranteedOpts)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a thought: for a microsecond I was confused that onlyGuaranteedOpts referred to the ownership kind. Maybe the nomenclature should be MandatoryOpts (must run for correctness/diagnostics), AlwaysOnOpts (enabled even at -Onone for debug build performance), and PerformanceOpts (-O)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why don't we talk about this offline. I'll do a follow up patch to rename to whatever makes sense.

//===----------------------------------------------------------------------===//

static SILBasicBlock::iterator
replaceAllUsesAndEraseInner(SingleValueInstruction *svi, SILValue newValue,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can there be just one copy of replaceAllUsesAndEraseInner?

… owned/guaranteed -> unowned.

Specifically, we check that all of the unowned's value uses are within the
lifetime of the unchecked_ownership_conversion's operand. If so, we eliminate
it.
…i and enable SimplifyInstruction on OSSA.

This is a generic API that when ownership is enabled allows one to replace all
uses of a value with a value with a differing ownership by transforming/lifetime
extending as appropriate.

This API supports all pairings of ownership /except/ replacing a value with
OwnershipKind::None with a value without OwnershipKind::None. This is a more
complex optimization that we do not support today. As a result, we include on
our state struct a helper routine that callers can use to know if the two values
that they want to process can be handled by the algorithm.

My moticiation is to use this to to update InstSimplify and SILCombiner in a
less bug prone way rather than just turn stuff off.

Noting that this transformation inserts ownership instructions, I have made sure
to test this API in two ways:

1. With Mandatory Combiner alone (to make sure it works period).

2. With Mandatory Combiner + Semantic ARC Opts to make sure that we can
   eliminate the extra ownership instructions it inserts.

As one can see from the tests, the optimizer today is able to handle all of
these transforms except one conditional case where I need to eliminate a dead
phi arg. I have a separate branch that hits that today but I have exposed unsafe
behavior in ClosureLifetimeFixup that I need to fix first before I can land
that. I don't want that to stop this PR since I think the current low level ARC
optimizer may be able to help me here since this is a simple transform it does
all of the time.
@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

@swift-ci smoke test

@gottesmm gottesmm dismissed atrick’s stale review December 9, 2020 20:31

I talked with atrick offline and he is fine with me doing additional changes post-commit.

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 9, 2020

Done... sooo happy!

@gottesmm gottesmm merged commit 1ca5577 into swiftlang:main Dec 9, 2020
@gottesmm gottesmm deleted the ossa-inst-simplify branch December 9, 2020 22:31
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.

4 participants