Skip to content

[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

Closed
wants to merge 1 commit into from

Conversation

eeckstein
Copy link
Contributor

This is just a prototype.

@eeckstein eeckstein requested review from slavapestov and xedin June 8, 2021 16:24
Copy link
Contributor

@xedin xedin left a 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;
Copy link
Contributor

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 *),
Copy link
Contributor

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?

Copy link
Contributor

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<>)

Copy link
Contributor

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...

Copy link
Contributor

@hamishknight hamishknight Jun 8, 2021

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;
Copy link
Contributor

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)
Copy link
Contributor

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;
Copy link
Contributor

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;
Copy link
Contributor

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;
Copy link
Contributor

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

Copy link
Contributor Author

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

Comment on lines +5523 to +5528
if (fieldIndex < 0) {
NominalTypeDecl *parent = getDeclContext()->getSelfNominalTypeDecl();
evaluateOrDefault(getASTContext().evaluator,
ComputeFieldIndicesRequest{parent}, {});
assert(fieldIndex >= 0);
}
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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,
Copy link
Contributor

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.

Copy link
Contributor Author

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

@eeckstein
Copy link
Contributor Author

Closing in favor of #58933

@eeckstein eeckstein closed this May 16, 2022
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