-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[DNM] compute the field index with a request instead of caching it in the instruction #37831
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
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.
Mostly looks good to me, there is a mismatch between std::tuple
and void
in the declaration.
NamedPattern *NamingPattern = nullptr; | ||
|
||
int fieldIndex = -1; |
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.
It's unfortunate that we'd still need to cache index in the decl but it would be expensive to compute indexes with request for an individual property since there could be quite a few stored properties...
@@ -87,6 +87,20 @@ class LoweredSILRequest | |||
ASTLoweringDescriptor desc) const; | |||
}; | |||
|
|||
class ComputeFieldIndicesRequest : | |||
public SimpleRequest<ComputeFieldIndicesRequest, | |||
std::tuple<>(NominalTypeDecl *), |
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 think this has to be void
?
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.
IIRC the evaluator doesn't currently support void
return types, we usually use evaluator::SideEffect
for that (which is an alias for std::tuple<>
)
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.
Ah interesting, since the definition accepted void I got confused...
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.
Yeah I believe the signature written in the SWIFT_REQUEST
macro isn't actually used for anything, so isn't currently checked for consistency 😬
friend SimpleRequest; | ||
|
||
// Evaluation. | ||
std::tuple<> evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const; |
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.
Here as well?
@@ -20,3 +20,6 @@ SWIFT_REQUEST(SILOptimizer, ExecuteSILPipelineRequest, | |||
SWIFT_REQUEST(SILOptimizer, LoweredSILRequest, | |||
std::unique_ptr<SILModule>(ASTLoweringDescriptor), | |||
Uncached, NoLocationInfo) | |||
SWIFT_REQUEST(SILOptimizer, ComputeFieldIndicesRequest, | |||
void(NominalTypeDecl *), | |||
Cached, NoLocationInfo) |
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 think you can make it Uncached
since it doesn't return anything?
@@ -4821,6 +4825,8 @@ class VarDecl : public AbstractStorageDecl { | |||
return hasName() ? getBaseIdentifier().str() : "_"; | |||
} | |||
|
|||
int getFieldIndex() const; |
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 feel like this should probably have a slightly scarier name to convey it might entail a non-trivial amount of work (such as synthesising backing storage vars) – something like getABIStoredPropertyIndex
perhaps? Or even just getABIFieldIndex
? I'd be interested to hear what others think.
NamedPattern *NamingPattern = nullptr; | ||
|
||
int fieldIndex = -1; |
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 used to be cached as an unsigned
, are there any issues here in halving the range of values it can store?
It might also be worth moving into the inline bitfield for VarDecl
, though that would mean you'd likely have to add a private getter and setter for the cached value so the request can access it.
@@ -4788,8 +4788,12 @@ enum class PropertyWrapperSynthesizedPropertyKind { | |||
/// VarDecl - 'var' and 'let' declarations. | |||
class VarDecl : public AbstractStorageDecl { | |||
friend class NamingPatternRequest; | |||
friend class GetFieldIndexRequest; |
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.
GetFieldIndexRequest
doesn't appear to be defined
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.
good catch. I'll remove it
if (fieldIndex < 0) { | ||
NominalTypeDecl *parent = getDeclContext()->getSelfNominalTypeDecl(); | ||
evaluateOrDefault(getASTContext().evaluator, | ||
ComputeFieldIndicesRequest{parent}, {}); | ||
assert(fieldIndex >= 0); | ||
} |
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.
We generally want to try and avoid having side-effecting requests like this. Ideally ComputeFieldIndicesRequest
would be a SeparatelyCached
cached request, and get and set the cached value in its getCachedResult
/cacheResult
methods.
You could also fill in the other field indices for the other properties as you iterate by calling cacheOutput
on the evaluator for those properties, similar to what DefaultArgumentInitContextRequest
does.
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.
Hm, would a better approach here be to remove field
from the decl and just store everything in a cached DenseMap
instead? That would use more memory but at least wouldn't have any side-effects.
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.
If it's going into a DenseMap then that would basically be more or less equivalent to just using the evaluator's internal cache, which we could possibly do here.
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.
Well, I could also add a DenseMap for this in SILModule without using the evaluator machinery. But the field indices are something which are used in a critical path in the optimizer (for computing projections). So the purpose of this exercise is to avoid the overhead of a hash lookup.
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.
Ideally, the index of all stored properties should be computed and cached for a type during a single request. This should result in a unique index for each property in an object. This is something that we can't currently rely on but would greatly simplify analysis because the index would have meaning independent of the address type.
@eeckstein is right that the index should be directly loadable from an instruction without any hash lookup. That was the point of the instruction cache, although I'm happy to see it go.
@@ -20,3 +20,6 @@ SWIFT_REQUEST(SILOptimizer, ExecuteSILPipelineRequest, | |||
SWIFT_REQUEST(SILOptimizer, LoweredSILRequest, | |||
std::unique_ptr<SILModule>(ASTLoweringDescriptor), | |||
Uncached, NoLocationInfo) | |||
SWIFT_REQUEST(SILOptimizer, ComputeFieldIndicesRequest, |
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.
Hmm, ideally we'd have a SIL request evaluator zone for this. I think for now at least it might be better off placed in the TypeChecker
zone, as it shouldn't depend on anything outside of Sema.
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.
ok. I can move it to the type checker
Closing in favor of #58933 |
This is just a prototype.