-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Cache struct/class field offsets in SIL. #24717
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 test. |
@swift-ci test source compatibility. |
@swift-ci test compiler performance |
@swift-ci smoke test |
@atrick Can you put in a scale unit test for this with the test program? I think I remember how to do it if you do not. |
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.
Overall looks ok. Some small asks.
StructDecl *getStructDecl() const { | ||
auto s = getOperand()->getType().getStructOrBoundGenericStruct(); | ||
NominalTypeDecl *getParentDecl() const { | ||
auto s = getOperand(0)->getType().getNominalOrBoundGenericNominal(); |
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.
Meta question. Should the base type of this be some sort of unary instruction base or something? Then getOperand() is correct.
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.
Thanks for pointing that out; there should be an assert. There was actually a reason I didn't make this a subclass ofUnary Instruction.
d98cf0c
@gottesmm you can see review feedback in separate commits. I think that's easier to keep track of. I'm still working on the scale test. It's tricky because there's no sil-opt support yet. So I can count the number of calls to getStoredProperties, but that's probably still quadratic somewhere in the compiler. I can count the number of times SIL calls it from the new API, but that's useless as a regression test. |
The field's ordinal value is used by the Projection abstraction, which is the basis of efficiently comparing and sorting access paths in SIL. It must be cached before it is used by any SIL passes, including the verifier, or it causes widespread quadratic complexity. Fixes <rdar://problem/50353228> Swift compile time regression with optimizations enabled In production code, a file that was taking 40 minutes to compile now takes 1 minute, with more than half of the time in LLVM. Here's a short script that reproduces the problem. It used to take 30s and now takes 0.06s: // swift genlazyinit.swift > lazyinit.sil // sil-opt ./lazyinit.sil --access-enforcement-opts var NumProperties = 300 print(""" sil_stage canonical import Builtin import Swift import SwiftShims public class LazyProperties { """) for i in 0..<NumProperties { print(""" // public lazy var i\(i): Int { get set } @_hasStorage @_hasInitialValue final var __lazy_storage__i\(i): Int? { get set } """) } print(""" } // LazyProperties.init() sil @$s4lazy14LazyPropertiesCACycfc : $@convention(method) (@owned LazyProperties) -> @owned LazyProperties { bb0(%0 : $LazyProperties): %enum = enum $Optional<Int>, #Optional.none!enumelt """) for i in 0..<NumProperties { let adr = (i*4) + 2 let access = adr + 1 print(""" %\(adr) = ref_element_addr %0 : $LazyProperties, #LazyProperties.__lazy_storage__i\(i) %\(access) = begin_access [modify] [dynamic] %\(adr) : $*Optional<Int> store %enum to %\(access) : $*Optional<Int> end_access %\(access) : $*Optional<Int> """) } print(""" return %0 : $LazyProperties } // end sil function '$s4lazy14LazyPropertiesCACycfc' """)
I'm not sure how anyone debugs these tests otherwise.
Adds a NumStoredPropertiesQueries stat. Adds a test case for an increasing number of lazy stored class properties. Each property requires a formal access within the initializer. This would manifest as cubic behavior in AccessEnforcementOpts, which scales as O(1.5) in the above stat.
@gottesmm I squashed the review feedback and added the scale test so it's ready to merge. |
@swift-ci test. |
Build failed |
Build failed |
[5.1] Merge pull request #24717 from atrick/cache-field-number
The field's ordinal value is used by the Projection abstraction, which is
the basis of efficiently comparing and sorting access paths in SIL. It must
be cached before it is used by any SIL passes, including the verifier, or it
causes widespread quadratic complexity.
Fixes rdar://problem/50353228 Swift compile time regression with optimizations enabled
In production code, a file that was taking 40 minutes to compile now
takes 1 minute, with more than half of the time in LLVM.
Here's a short script that reproduces the problem. It used to take 30s and now takes 0.06s: