-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Propagate concrete types of arguments to apply #17370
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
@slavapestov @atrick This PR is part of #13991 and just focuses on concrete type propagation for all arguments of an Apply. |
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.
New SILCombine-like optimizations should have SIL level unit tests. Those unit tests should cover any special cases that pass the SIL verifier but aren't currently generated with source-level tests.
Much of the code that you're adding is handled by ConcreteExistentialInfo from
#17315. I'd prefer these correctness fixes be merged first, with additional optimization expressed in terms of what I think is now a correct API.
return ConcreteType; | ||
return type; | ||
}, | ||
LookUpConformanceInSignature(*(FnTy->getGenericSignature()))); |
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're not supposed to call this in the optimizer because all conformances should already be present, type checked, and available from SIL instructions. (This is one area where the interface between the type system an compiler is seriously broken). You should use ConcreteExistentialInfo.lookupConformance() from PR17315 instead.
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.
Indeed, you need one ConcreteExistentialInfo for each argument being replaced
SILCombiner::propagateConcreteTypeOfInitExistentialsToAllApplyArgs( | ||
FullApplySite AI) { | ||
/// Check if legal to perform propagation. | ||
if (!AI.hasSubstitutions()) |
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.
Remove this because you check for a polymorphic callee below already
Type ContextTy; | ||
bool isCopied = false; | ||
|
||
InitExistential = findInitExistential(AI, OrigApplyArg, OpenedArchetype, |
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.
Refactor this as discussed
if (!FnTy->isPolymorphic()) | ||
return nullptr; | ||
|
||
auto Args = Callee->begin()->getFunctionArguments(); |
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.
What if the callee does not have a body?
if (!AI.hasSubstitutions()) | ||
return nullptr; | ||
auto *Callee = AI.getReferencedFunction(); | ||
if (!Callee || !Callee->shouldOptimize() || Callee->empty()) |
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 restricts the optimization unnecessarily. It should work even if the callee of the apply is not a static function_ref
. You should be looking at the operand of the apply's SILFunctionType
, and walk the parameters of the function type. The arguments of the callee should not be needed.
@@ -1027,6 +1053,124 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI) { | |||
return propagateConcreteTypeOfInitExistential(AI, PD, PropagateIntoOperand); | |||
} | |||
|
|||
/// A peephole optimizer that propagates concrete types of all arguments to | |||
/// Apply instruction. It handles all the arguments of an apply including self. |
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.
Add a comment describing the transformation
Reminder: check for inout |
9853879
to
9452e0f
Compare
@atrick can you review this PR? This PR propagates concrete types to all archetype args, not just self so that generic specializer can create a specialized version. @slavapestov fyi. |
7ec3892
to
728297c
Compare
unsigned ArgIdx); | ||
SILInstruction *createApplyWithConcreteType( | ||
FullApplySite Apply, | ||
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *, 8> &CEIs, |
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.
Passing SmallDenseMapImpl instead would allow you to avoid hard-coding the size here. Also you should make it '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.
Which header file has this SmallDenseMapImpl?
for (unsigned ArgIdx = 0; ArgIdx < NumApplyArgs; ArgIdx++) { | ||
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *, 8>::iterator | ||
ArgIt = CEIs.find(ArgIdx); | ||
if (ArgIt != CEIs.end()) { |
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 the == case should come first, with a 'continue' at the end. Then the rest does not need a whole level of indent.
// Do a conformance lookup on this witness requirement using the | ||
// existential's conformances. The witness requirement may be a | ||
// base type of the existential's requirements. | ||
return CEI->lookupExistentialConformance(proto).getValue(); |
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 callback returns an Optional already, I don't think you need to do getValue() here.
32baa7a
to
d7e59db
Compare
@atrick find sometime to review this? |
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.
LGMT other than a couple comments below.
// Construct the map for Self to be used for createApplyWithConcreteType. | ||
llvm::SmallDenseMap<unsigned, const ConcreteExistentialInfo *> CEIs; | ||
CEIs.insert(std::pair<unsigned, const ConcreteExistentialInfo *>( | ||
Apply.getNumArguments() - 1, &CEI)); |
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 do this operand index hard-coding all over, but I would prefer Apply.getCalleeArgIndex(Apply.getSelfArgumentOperand())
.
// of OpenedArchetype in the function signature, but will only rewrite the | ||
// Arg operand. | ||
// | ||
// Note that the language does not allow Arg to occur in contravariant |
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 comment only applies to Self
not Arg
. I think we should now say that this bailout check is needed for non-Self arguments, and also needed for Self
because even though the language does not allow Self
to occur in contravariant position ...
So, I think this bailout is still sufficient. Essentially, for now we only allow specialization on a single generic argument. @slavapestov does it make sense to you?
d7e59db
to
0cdcc40
Compare
Thanks @atrick . I pushed a new commit. |
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.
LGTM
// references to OpenedArchetype will be substituted. So walk to type to | ||
// find all possible references, such as returning Optional<Arg>. | ||
if (Apply.getType().getASTType().findIf( | ||
[&CEI](Type t) -> bool { return t->isEqual(CEI.OpenedArchetype); })) { |
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 snippet appears in a few places -- extract a new static function?
@swift-ci Please test |
@swift-ci Please test source compatibility |
Build failed |
Build failed |
@rajbarik Unfortunately this broke the asan bot. I reverted it. |
@eeckstein Anything I can do to help? |
That's (most likely) caused by a bug in your code. I recommend to reproduce the issue locally with that asan configuration. |
@eeckstein @rajbarik normally the log file from the ASAN bot has enough information to give you a clue where to look in the code. |
I see. I never did this before. Could you either point me to the log of
ASAN bot or steps to reproduce it at my end?
…On Tue, Sep 11, 2018 at 5:34 PM Andrew Trick ***@***.***> wrote:
@eeckstein <https://github.com/eeckstein> @rajbarik
<https://github.com/rajbarik> normally the log file from the ASAN bot has
enough information to give you a clue where to look in the code.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#17370 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AFBwaVCTmSsqLQ_TuqItP8IKC1kNdglRks5uaFaUgaJpZM4Uv6d2>
.
|
Never mind. I found it at:
https://ci.swift.org/job/oss-lldb-asan-osx/11/consoleFull#5770858633122a513-f36a-4c87-8ed7-cbc36a1ec144
…On Wed, Sep 12, 2018 at 10:04 AM Raj Barik ***@***.***> wrote:
I see. I never did this before. Could you either point me to the log of
ASAN bot or steps to reproduce it at my end?
On Tue, Sep 11, 2018 at 5:34 PM Andrew Trick ***@***.***>
wrote:
> @eeckstein <https://github.com/eeckstein> @rajbarik
> <https://github.com/rajbarik> normally the log file from the ASAN bot
has
> enough information to give you a clue where to look in the code.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#17370 (comment)>, or
mute
> the thread
> <
https://github.com/notifications/unsubscribe-auth/AFBwaVCTmSsqLQ_TuqItP8IKC1kNdglRks5uaFaUgaJpZM4Uv6d2
>
> .
>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#17370 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AFBwaXiMCGl5oPbi9DrRj8FakmM8_WEmks5uaT64gaJpZM4Uv6d2>
.
|
@atrick I think I narrowed down the problem. I was storing stack allocated CEI structs in a loop using a map and then was using the map outside the loop later:
I can think of two ways of fixing this:
be removed and CEIs are copied around. Is there any particular reason you disabled the copy constructor? Any recommendations? |
Deleting the copy constructor just signals the original intention that's it's a grouping of local variables that we don't want to accidentally pass-by-copy or store beyond its caller's scope. In general, you can migrate something like this to a collection of multiple elements using |
@atrick @slavapestov could you review #19287 now? |
Final Part of #13991 that propagates concrete types of arguments to apply. This handles non-self arguments as well.