-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[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
Conversation
4864f57
to
db188f3
Compare
There was a problem hiding this 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
There was a problem hiding this 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.
12e298d
to
1c03b0d
Compare
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.
1c03b0d
to
802f93f
Compare
I upstreamed and slimmed this down. I did it the way we talked about offline. |
802f93f
to
ec86fee
Compare
I think I also redid everything that were a problem. |
@swift-ci test |
@swift-ci benchmark |
@swift-ci test source compatibility |
preset=buildbot,tools=RA,stdlib=RD,test=non_executable |
I am going to have to fight a little bit with MSVC looks like. |
I am really curious what the benchmark results turn out. I diffed the text and there isn't any difference at -O anyways. |
Performance: -O
Code size: -OPerformance: -Osize
Code size: -OsizePerformance: -OnoneCode size: -swiftlibsHow to read the dataThe 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 Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
If all of the tests pass, I am going to fix the windows issue and then smoke test this in. |
There was a problem hiding this 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.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
lib/SILOptimizer/SemanticARC/OwnershipConversionElimination.cpp
Outdated
Show resolved
Hide resolved
//===----------------------------------------------------------------------===// | ||
|
||
static SILBasicBlock::iterator | ||
replaceAllUsesAndEraseInner(SingleValueInstruction *svi, SILValue newValue, |
There was a problem hiding this comment.
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.
ec86fee
to
e2c3d87
Compare
…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.
e2c3d87
to
259d2bb
Compare
@swift-ci smoke test |
I talked with atrick offline and he is fine with me doing additional changes post-commit.
Done... sooo happy! |
I am splitting this out and fixing some issues at atrick's request.