-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Perform ExistentialSpecializer when SoleConformingType is known #20977
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
Perform ExistentialSpecializer when SoleConformingType is known #20977
Conversation
/// Perform specialization. | ||
specializeExistentialArgsInAppliesWithinFunction(*F); | ||
} | ||
}; | ||
} // namespace | ||
|
||
/// Find concrete type from Sole Conforming Type. | ||
bool ExistentialSpecializer::findConcreteTypeFromSoleConformingType( |
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 method checks if a SoleConformingType can be determined for the argument. Some parts of code (5-6 lines) overlap with what was done in SILCombiner, but there are lot of disparities to make it a new APi in Existential.h altogether.
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.
@atrick You had a similar concern from SILCombiner, but the overlap is minor to warrant a new API?
@@ -158,6 +208,14 @@ findIfCalleeUsesArgInDestroyUse(SILValue Arg, | |||
} | |||
} | |||
|
|||
/// Helper function to ensure that the argument is not InOut or InOut_Aliasable |
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.
Added to filter out inout args, which otherwise would be fed to openExistentialRef as non-objects!
CanType ConcreteType; | ||
if (!findConcreteType(Apply, Idx, ConcreteType)) { | ||
if (!((F->getModule().isWholeModule() && |
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.
First tries to check if there is a SoleConformingType, if not, then tries findConcreteTypeUsingInitExistential.
@@ -417,6 +417,8 @@ void ExistentialTransform::populateThunkBody() { | |||
break; | |||
} | |||
case ExistentialRepresentation::Class: { | |||
/// If the operand is not object type, we would need an explicit load. | |||
assert(OrigOperand->getType().isObject()); |
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.
Extra check for accidental non-object operand type being passed to OEI.
4974abc
to
6b0d1a1
Compare
// CHECK: return | ||
// CHECK-LABEL: } // end sil function '$s30existential_transform_soletype4opt11bs5Int32VAA3SPP_p_tF' | ||
|
||
// CHECK-LABEL: sil shared [noinline] @$s30existential_transform_soletype4opt21bs5Int32VAA3SPP_p_tFTf4e_n : $@convention(thin) <τ_0_0 where τ_0_0 : SPP> (@in_guaranteed τ_0_0) -> Int32 { |
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.
opt1 does not get optimized since the caller foo is under @_optimize(none).
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 generally better to use .sil
test cases for individual passes, but not an absolute requirement. The source is definitely helpful, but that can be included as a comment.
@slavapestov @atrick Can you review this small PR? This one extends ExistentialSpecializer to also perform the optimization when SoleConformingType can be found. |
if (!findConcreteType(Apply, Idx, ConcreteType)) { | ||
if (!((F->getModule().isWholeModule() && | ||
isNonInoutIndirectArgument(Arg, ArgConvention) && | ||
findConcreteTypeFromSoleConformingType(Arg, ConcreteType)) || |
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.
@atrick fyi
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.
Otherwise, LGTM.
(CD->getEffectiveAccess() == AccessLevel::Open || | ||
CHA->hasKnownDirectSubclasses(CD))) { | ||
return false; | ||
} |
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 should be a standalone API because it has special logic to reason about possible conformances. That logic should only exist in one place in the compiler.
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.
Originally I had this in findSoleConformingType function of ProtocolConformanceAnalysis, however since this also required ClassHierarchyAnalysis, we had to split. I can put this in Existential.cpp in Utils. This would be a wrapper for findSoleConformingType.
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 just trying to avoid duplicating logic that reasons about the type system in multiple places in the SILOptimizer. As an alternative, we could just have a CHA->mayHaveSubclasses
query.
// CHECK: return | ||
// CHECK-LABEL: } // end sil function '$s30existential_transform_soletype4opt11bs5Int32VAA3SPP_p_tF' | ||
|
||
// CHECK-LABEL: sil shared [noinline] @$s30existential_transform_soletype4opt21bs5Int32VAA3SPP_p_tFTf4e_n : $@convention(thin) <τ_0_0 where τ_0_0 : SPP> (@in_guaranteed τ_0_0) -> Int32 { |
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 generally better to use .sil
test cases for individual passes, but not an absolute requirement. The source is definitely helpful, but that can be included as a comment.
6b0d1a1
to
1f4c6ca
Compare
@atrick please check. I extracted out the common code between SILCombiner and ExistentialSpecializer to ProtocolConformanceAnalysis. Have a look. |
@atrick, fyi, this needs your approval. thanks. |
@rajbarik it looks like I already approved this, but I think you need to add a commit message. |
@swift-ci Please test |
@swift-ci Please test source compatibility |
@swift-ci Please benchmark |
Build failed |
Build failed |
Build comment file:No performance and code size changes |
1f4c6ca
to
0070730
Compare
@swift-ci test. |
Build failed |
Build failed |
@rajbarik Are you able to build and test Swift on Linux?
|
@slavapestov I do not have a Linux Box. Other means? |
Update: Found a linux box and installed Swift on it. It built fine. When I run tests, I get a lot of precompiled header errors, nothing like Foundation SEGFAULT. |
@atrick //cc @airspeedswift @eeckstein could you please look at this one when you get time? I am unable to reproduce this on a linux box at my end. I am in the process of writing a benchmark for #19820 -- this one needs to be committed before I commit the benchmark. |
@swift-ci test linux platform. |
I don't think I'll have time to debug this week. Let's get the results again. Maybe it's unrelated to this PR. |
The criteria for ExistentialSpecializer is now based on an argument having "findInitExistential or SoleConformingType".