Skip to content

Commit 47b4309

Browse files
authored
Merge pull request #7779 from slavapestov/devirt-gardening
Simplify devirtualization and fix a bug
2 parents 3ce7d3e + 2994415 commit 47b4309

File tree

6 files changed

+67
-358
lines changed

6 files changed

+67
-358
lines changed

include/swift/SILOptimizer/Utils/Devirtualize.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ DevirtualizationResult devirtualizeClassMethod(FullApplySite AI,
5454
SILValue ClassInstance);
5555
DevirtualizationResult tryDevirtualizeClassMethod(FullApplySite AI,
5656
SILValue ClassInstance);
57-
DevirtualizationResult tryDevirtualizeWitnessMethod(ApplySite AI);
58-
/// Check if an upcast is legal.
59-
bool isLegalUpcast(SILType FromTy, SILType ToTy);
57+
DevirtualizationResult tryDevirtualizeWitnessMethod(ApplySite AI);
6058
}
6159

6260
#endif

include/swift/SILOptimizer/Utils/Local.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,10 @@ SILValue isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI);
110110
/// - a type of the return value is a subclass of the expected return type.
111111
/// - actual return type and expected return type differ in optionality.
112112
/// - both types are tuple-types and some of the elements need to be casted.
113-
///
114-
/// If CheckOnly flag is set, then this function only checks if the
115-
/// required casting is possible. If it is not possible, then None
116-
/// is returned.
117-
/// If CheckOnly is not set, then a casting code is generated and the final
118-
/// casted value is returned.
119-
Optional<SILValue> castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
120-
SILValue Value,
121-
SILType SrcTy,
122-
SILType DestTy,
123-
bool CheckOnly = false);
124-
125-
/// Check if the optimizer can cast a value into the expected,
126-
/// ABI compatible type if necessary.
127-
bool canCastValueToABICompatibleType(SILModule &M,
128-
SILType SrcTy, SILType DestTy);
113+
SILValue castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
114+
SILValue Value,
115+
SILType SrcTy,
116+
SILType DestTy);
129117

130118
/// Returns a project_box if it is the next instruction after \p ABI and
131119
/// and has \p ABI as operand. Otherwise it creates a new project_box right

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,23 +1875,6 @@ static bool isTryApplyOfConvertFunction(TryApplyInst *TAI,
18751875
if (!TargetFnTy || !TargetFnTy->hasErrorResult())
18761876
return false;
18771877

1878-
// Check if the converted function type has the same number of arguments.
1879-
// Currently this is always the case, but who knows what convert_function can
1880-
// do in the future?
1881-
unsigned numParams = OrigFnTy->getParameters().size();
1882-
if (TargetFnTy->getParameters().size() != numParams)
1883-
return false;
1884-
1885-
// Check that the argument types are matching.
1886-
SILModuleConventions silConv(TAI->getModule());
1887-
for (unsigned Idx = 0; Idx < numParams; Idx++) {
1888-
if (!canCastValueToABICompatibleType(
1889-
TAI->getModule(),
1890-
silConv.getSILType(OrigFnTy->getParameters()[Idx]),
1891-
silConv.getSILType(TargetFnTy->getParameters()[Idx])))
1892-
return false;
1893-
}
1894-
18951878
// Look through the conversions and find the real callee.
18961879
Callee = getActualCallee(CFI->getConverted());
18971880
CalleeType = Callee->getType();
@@ -1936,12 +1919,6 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
19361919
auto ResultTy = calleeConv.getSILResultType();
19371920
auto OrigResultTy = TAI->getNormalBB()->getArgument(0)->getType();
19381921

1939-
// Bail if the cast between the actual and expected return types cannot
1940-
// be handled.
1941-
if (!canCastValueToABICompatibleType(TAI->getModule(),
1942-
ResultTy, OrigResultTy))
1943-
return false;
1944-
19451922
SILBuilderWithScope Builder(TAI);
19461923

19471924
auto TargetFnTy = CalleeFnTy;
@@ -1959,28 +1936,14 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
19591936
}
19601937
SILFunctionConventions origConv(OrigFnTy, TAI->getModule());
19611938

1962-
unsigned numArgs = TAI->getNumArguments();
1963-
1964-
// First check if it is possible to convert all arguments.
1965-
// Currently we believe that castValueToABICompatibleType can handle all
1966-
// cases, so this check should never fail. We just do it to be absolutely
1967-
// sure that we don't crash.
1968-
for (unsigned i = 0; i < numArgs; ++i) {
1969-
if (!canCastValueToABICompatibleType(TAI->getModule(),
1970-
origConv.getSILArgumentType(i),
1971-
targetConv.getSILArgumentType(i))) {
1972-
return false;
1973-
}
1974-
}
1975-
19761939
SmallVector<SILValue, 8> Args;
1940+
unsigned numArgs = TAI->getNumArguments();
19771941
for (unsigned i = 0; i < numArgs; ++i) {
19781942
auto Arg = TAI->getArgument(i);
19791943
// Cast argument if required.
19801944
Arg = castValueToABICompatibleType(&Builder, TAI->getLoc(), Arg,
19811945
origConv.getSILArgumentType(i),
1982-
targetConv.getSILArgumentType(i))
1983-
.getValue();
1946+
targetConv.getSILArgumentType(i));
19841947
Args.push_back(Arg);
19851948
}
19861949

@@ -1998,8 +1961,7 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
19981961
auto *NormalBB = TAI->getNormalBB();
19991962

20001963
auto CastedResult = castValueToABICompatibleType(&Builder, Loc, NewAI,
2001-
ResultTy, OrigResultTy)
2002-
.getValue();
1964+
ResultTy, OrigResultTy);
20031965

20041966
Builder.createBranch(Loc, NormalBB, { CastedResult });
20051967
TAI->eraseFromParent();

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 6 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -546,31 +546,6 @@ bool swift::canDevirtualizeClassMethod(FullApplySite AI,
546546
return false;
547547
}
548548

549-
// Type of the actual function to be called.
550-
CanSILFunctionType GenCalleeType = F->getLoweredFunctionType();
551-
552-
// Type of the actual function to be called with substitutions applied.
553-
CanSILFunctionType SubstCalleeType = GenCalleeType;
554-
555-
// For polymorphic functions, bail if the number of substitutions is
556-
// not the same as the number of expected generic parameters.
557-
if (GenCalleeType->isPolymorphic()) {
558-
// First, find proper list of substitutions for the concrete
559-
// method to be called.
560-
SmallVector<Substitution, 4> Subs;
561-
getSubstitutionsForCallee(Mod, GenCalleeType,
562-
ClassOrMetatypeType.getSwiftRValueType(),
563-
AI, Subs);
564-
SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Subs);
565-
}
566-
567-
// Check if the optimizer knows how to cast the return type.
568-
SILType ReturnType =
569-
SILFunctionConventions(SubstCalleeType, Mod).getSILResultType();
570-
571-
if (!canCastValueToABICompatibleType(Mod, ReturnType, AI.getType()))
572-
return false;
573-
574549
return true;
575550
}
576551

@@ -612,8 +587,7 @@ DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI,
612587
for (auto ResultTy : substConv.getIndirectSILResultTypes()) {
613588
NewArgs.push_back(
614589
castValueToABICompatibleType(&B, AI.getLoc(), *IndirectResultArgIter,
615-
IndirectResultArgIter->getType(), ResultTy)
616-
.getValue());
590+
IndirectResultArgIter->getType(), ResultTy));
617591
++IndirectResultArgIter;
618592
}
619593

@@ -623,8 +597,7 @@ DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI,
623597
auto paramType = substConv.getSILType(param);
624598
NewArgs.push_back(
625599
castValueToABICompatibleType(&B, AI.getLoc(), *ParamArgIter,
626-
ParamArgIter->getType(), paramType)
627-
.getValue());
600+
ParamArgIter->getType(), paramType));
628601
++ParamArgIter;
629602
}
630603

@@ -634,7 +607,7 @@ DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI,
634607
NewArgs.push_back(castValueToABICompatibleType(&B, AI.getLoc(),
635608
ClassOrMetatype,
636609
ClassOrMetatypeType,
637-
SelfParamTy).getValue());
610+
SelfParamTy));
638611

639612
SILType ResultTy = substConv.getSILResultType();
640613

@@ -707,7 +680,7 @@ DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI,
707680

708681
// Check if any casting is required for the return value.
709682
ResultValue = castValueToABICompatibleType(&B, NewAI.getLoc(), ResultValue,
710-
ResultTy, AI.getType()).getValue();
683+
ResultTy, AI.getType());
711684

712685
DEBUG(llvm::dbgs() << " SUCCESS: " << F->getName() << "\n");
713686
NumClassDevirt++;
@@ -871,75 +844,6 @@ static void getWitnessMethodSubstitutions(ApplySite AI, SILFunction *F,
871844
origSubs, isDefaultWitness, NewSubs);
872845
}
873846

874-
/// Check if an upcast is legal.
875-
/// The logic in this function is heavily based on the checks in
876-
/// the SILVerifier.
877-
bool swift::isLegalUpcast(SILType FromTy, SILType ToTy) {
878-
if (ToTy.is<MetatypeType>()) {
879-
CanType InstTy(ToTy.castTo<MetatypeType>()->getInstanceType());
880-
if (!FromTy.is<MetatypeType>())
881-
return false;
882-
CanType OpInstTy(FromTy.castTo<MetatypeType>()->getInstanceType());
883-
auto InstClass = InstTy->getClassOrBoundGenericClass();
884-
if (!InstClass)
885-
return false;
886-
887-
bool CanBeUpcasted =
888-
InstClass->usesObjCGenericsModel()
889-
? InstClass->getDeclaredTypeInContext()->isBindableToSuperclassOf(
890-
OpInstTy, nullptr)
891-
: InstTy->isExactSuperclassOf(OpInstTy, nullptr);
892-
893-
return CanBeUpcasted;
894-
}
895-
896-
// Upcast from Optional<B> to Optional<A> is legal as long as B is a
897-
// subclass of A.
898-
if (ToTy.getSwiftRValueType().getAnyOptionalObjectType() &&
899-
FromTy.getSwiftRValueType().getAnyOptionalObjectType()) {
900-
ToTy = SILType::getPrimitiveObjectType(
901-
ToTy.getSwiftRValueType().getAnyOptionalObjectType());
902-
FromTy = SILType::getPrimitiveObjectType(
903-
FromTy.getSwiftRValueType().getAnyOptionalObjectType());
904-
}
905-
906-
auto ToClass = ToTy.getClassOrBoundGenericClass();
907-
if (!ToClass)
908-
return false;
909-
bool CanBeUpcasted =
910-
ToClass->usesObjCGenericsModel()
911-
? ToClass->getDeclaredTypeInContext()->isBindableToSuperclassOf(
912-
FromTy.getSwiftRValueType(), nullptr)
913-
: ToTy.isExactSuperclassOf(FromTy);
914-
915-
return CanBeUpcasted;
916-
}
917-
918-
/// Check if we can pass/convert all arguments of the original apply
919-
/// as required by the found devirtualized method.
920-
/// FIXME: This method was introduced as a workaround. We need to
921-
/// revisit it and check if it is still needed.
922-
static bool
923-
canPassOrConvertAllArguments(ApplySite AI,
924-
CanSILFunctionType SubstCalleeCanType) {
925-
SILFunctionConventions substConv(SubstCalleeCanType, AI.getModule());
926-
unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
927-
for (auto arg : AI.getArguments()) {
928-
// Check if we can cast the provided argument into the required
929-
// parameter type.
930-
auto FromTy = arg->getType();
931-
auto ToTy = substConv.getSILArgumentType(substArgIdx++);
932-
// If types are the same, no conversion will be required.
933-
if (FromTy == ToTy)
934-
continue;
935-
// Otherwise, it should be possible to upcast the arguments.
936-
if (!isLegalUpcast(FromTy, ToTy))
937-
return false;
938-
}
939-
assert(substArgIdx == substConv.getNumSILArguments());
940-
return true;
941-
}
942-
943847
/// Generate a new apply of a function_ref to replace an apply of a
944848
/// witness_method when we've determined the actual function we'll end
945849
/// up calling.
@@ -963,11 +867,6 @@ static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
963867
auto CalleeCanType = F->getLoweredFunctionType();
964868
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
965869

966-
// Bail if some of the arguments cannot be converted into
967-
// types required by the found devirtualized method.
968-
if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
969-
return ApplySite();
970-
971870
// Collect arguments from the apply instruction.
972871
auto Arguments = SmallVector<SILValue, 4>();
973872

@@ -979,7 +878,8 @@ static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
979878
for (auto arg : AI.getArguments()) {
980879
auto paramType = substConv.getSILArgumentType(substArgIdx++);
981880
if (arg->getType() != paramType)
982-
arg = B.createUpcast(AI.getLoc(), arg, paramType);
881+
arg = castValueToABICompatibleType(&B, AI.getLoc(), arg,
882+
arg->getType(), paramType);
983883
Arguments.push_back(arg);
984884
}
985885
assert(substArgIdx == substConv.getNumSILArguments());
@@ -1030,26 +930,6 @@ static bool canDevirtualizeWitnessMethod(ApplySite AI) {
1030930
return false;
1031931
}
1032932

1033-
// Collect all the required substitutions.
1034-
//
1035-
// The complete set of substitutions may be different, e.g. because the found
1036-
// witness thunk F may have been created by a specialization pass and have
1037-
// additional generic parameters.
1038-
SmallVector<Substitution, 4> NewSubs;
1039-
1040-
getWitnessMethodSubstitutions(AI, F, WMI->getConformance(), NewSubs);
1041-
1042-
// Figure out the exact bound type of the function to be called by
1043-
// applying all substitutions.
1044-
auto &Module = AI.getModule();
1045-
auto CalleeCanType = F->getLoweredFunctionType();
1046-
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
1047-
1048-
// Bail if some of the arguments cannot be converted into
1049-
// types required by the found devirtualized method.
1050-
if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
1051-
return false;
1052-
1053933
return true;
1054934
}
1055935

0 commit comments

Comments
 (0)