-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Array related optimization improvements #40291
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
@swift-ci benchmark |
@swift-ci test |
846d066
to
20041be
Compare
@swift-ci benchmark |
@swift-ci test |
Build failed |
Performance (x86_64): -O
Code size: -O
Performance (x86_64): -Osize
Code size: -Osize
Performance (x86_64): -Onone
Code 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
|
20041be
to
b0be31a
Compare
@@ -245,28 +245,60 @@ void LSLocation::reduce(LSLocation Base, SILModule *M, | |||
replaceSubLocations(Base, M, context, Locs, SubLocations); | |||
} | |||
|
|||
void LSLocation::enumerateLSLocation(TypeExpansionContext context, SILModule *M, | |||
std::pair<SILValue, bool> LSLocation::getBaseAddress(SILValue v, |
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.
@eeckstein could you use AccessBase::compute(address)
, AccessBase::isObjectAccess()
, AccessBase::getReference()
(then check for immutability), and AccessBase::getStorageReferenceRoot()
rather than using ad-hoc stripWhateverProjection. This way the possible patterns of object/variable access are well-defined by SIL, verified by the SIL verifier, and the logic used by passes is complete and maintainable.
Note that this version of getBaseAddress
is misleading because it does not always return a "base address" as defined in MemAccessUtils.
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.
Unfortunately it's not that simple. RLE and DSE internally rely on that kind of stripX pattern. When I use AccessBase, I get a crash.
I don't wan't to rewrite and RLE and DSE for this small change - not yet 🙂.
Note that this version of getBaseAddress is misleading
I renamed it to getBaseAddressOrObject
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.
Was the crash inside an AccessBase method? I'd like to fix that before something else hits it
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.
No, it crashed in RLE. There is no problem in AccessBase.
// argument. | ||
// Note that in OSSA, getSingleBorrowIntroducingValue will detect a | ||
// guaranteed argument. | ||
for (;;) { |
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.
This looks like a partial reimplementation of findOwnershipReferenceAggregate
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.
👍 Using findOwnershipReferenceAggregate
now
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'm not sure about LSLocation::getBaseAddress
, presumably it was copied from code in InstOptUtils. I'd strongly prefer the use of APIs in MemAccessUtils in two places. This sort of ad-hoc address/reference cast traversal makes it hard to migrate passes to handle SIL changes like access markers for example, and they contribute to pipeline instability and lack of test coverage.
Otherwise everything looks good to me.
b0be31a
to
6035fcf
Compare
That addition can not possibly overflow. If Array.count would be Int max, the allocation of the array buffer would have failed way before.
* add the IntegerLiteralInst + the Builder function to create it * add Value.nonDebugUses * add a general utility Sequence.isEmpty * add PassContext.replaceAllUses * add a function to erase all `debug_value` uses in PassContext.erase
…ructions * Replace the uniqueness result of a begin_cow_mutation of an empty Array/Set/Dictionary singleton with zero. * Remove empty begin_cow_mutation - end_cow_mutation pairs * Remove empty end_cow_mutation - begin_cow_mutation pairs
…gleton We already do that for Array.count. Now add Array.capacity.
Rerun RLE with cutting off the base address of loads at `ref_element/tail_addr [immutable]`. This increases the chance of catching loads of immutable COW class properties or elements.
In non-OSSA, this is the only case for which we know that if an instruction is within a "borrow-scope".
…y function. This is an end-to-end test to check if the optimization improvements of the previous commits result in good code generation for this function. rdar://83825776 https://bugs.swift.org/browse/SR-15259
6035fcf
to
8e83d5f
Compare
@swift-ci test |
Array.count
begin_cow_mutation
instructionsArray.capacity
with 0 if it's the empty array singletonref_element/tail_addr [immutable]
in redundant load eliminationFor details see the commit messages
rdar://83825776
https://bugs.swift.org/browse/SR-15259