Skip to content

Commit 013387e

Browse files
authored
Update Devirtualizer's analysis invalidation (#31284)
* Update Devirtualizer's analysis invalidation castValueToABICompatibleType can change CFG, Devirtualizer uses this api but doesn't check if it modified the cfg
1 parent 041dfb9 commit 013387e

File tree

5 files changed

+89
-78
lines changed

5 files changed

+89
-78
lines changed

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ FullApplySite findApplyFromDevirtualizedResult(SILValue value);
233233
/// - a type of the return value is a subclass of the expected return type.
234234
/// - actual return type and expected return type differ in optionality.
235235
/// - both types are tuple-types and some of the elements need to be casted.
236-
SILValue castValueToABICompatibleType(SILBuilder *builder, SILLocation Loc,
237-
SILValue value, SILType srcTy,
238-
SILType destTy);
236+
std::pair<SILValue, bool /* changedCFG */>
237+
castValueToABICompatibleType(SILBuilder *builder, SILLocation Loc,
238+
SILValue value, SILType srcTy, SILType destTy);
239239
/// Peek through trivial Enum initialization, typically for pointless
240240
/// Optionals.
241241
///

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,9 +2418,9 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
24182418
for (unsigned i = 0; i < numArgs; ++i) {
24192419
auto Arg = TAI->getArgument(i);
24202420
// Cast argument if required.
2421-
Arg = castValueToABICompatibleType(&Builder, TAI->getLoc(), Arg,
2422-
origConv.getSILArgumentType(i),
2423-
targetConv.getSILArgumentType(i));
2421+
std::tie(Arg, std::ignore) = castValueToABICompatibleType(
2422+
&Builder, TAI->getLoc(), Arg, origConv.getSILArgumentType(i),
2423+
targetConv.getSILArgumentType(i));
24242424
Args.push_back(Arg);
24252425
}
24262426

@@ -2435,8 +2435,9 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
24352435
auto Loc = TAI->getLoc();
24362436
auto *NormalBB = TAI->getNormalBB();
24372437

2438-
auto CastedResult = castValueToABICompatibleType(&Builder, Loc, NewAI,
2439-
ResultTy, OrigResultTy);
2438+
SILValue CastedResult;
2439+
std::tie(CastedResult, std::ignore) = castValueToABICompatibleType(
2440+
&Builder, Loc, NewAI, ResultTy, OrigResultTy);
24402441

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

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,11 @@ getSubstitutionsForCallee(SILModule &module, CanSILFunctionType baseCalleeType,
460460
baseCalleeSig);
461461
}
462462

463-
static ApplyInst *replaceApplyInst(SILBuilder &builder, SILLocation loc,
464-
ApplyInst *oldAI, SILValue newFn,
465-
SubstitutionMap newSubs,
466-
ArrayRef<SILValue> newArgs,
467-
ArrayRef<SILValue> newArgBorrows) {
463+
// Return the new apply and true if a cast required CFG modification.
464+
static std::pair<ApplyInst *, bool /* changedCFG */>
465+
replaceApplyInst(SILBuilder &builder, SILLocation loc, ApplyInst *oldAI,
466+
SILValue newFn, SubstitutionMap newSubs,
467+
ArrayRef<SILValue> newArgs, ArrayRef<SILValue> newArgBorrows) {
468468
auto *newAI =
469469
builder.createApply(loc, newFn, newSubs, newArgs, oldAI->isNonThrowing());
470470

@@ -475,15 +475,15 @@ static ApplyInst *replaceApplyInst(SILBuilder &builder, SILLocation loc,
475475
}
476476

477477
// Check if any casting is required for the return value.
478-
SILValue resultValue = castValueToABICompatibleType(
478+
auto castRes = castValueToABICompatibleType(
479479
&builder, loc, newAI, newAI->getType(), oldAI->getType());
480480

481-
oldAI->replaceAllUsesWith(resultValue);
482-
return newAI;
481+
oldAI->replaceAllUsesWith(castRes.first);
482+
return {newAI, castRes.second};
483483
}
484484

485485
// Return the new try_apply and true if a cast required CFG modification.
486-
static std::pair<TryApplyInst *, bool>
486+
static std::pair<TryApplyInst *, bool /* changedCFG */>
487487
replaceTryApplyInst(SILBuilder &builder, SILLocation loc, TryApplyInst *oldTAI,
488488
SILValue newFn, SubstitutionMap newSubs,
489489
ArrayRef<SILValue> newArgs, SILFunctionConventions conv,
@@ -531,20 +531,22 @@ replaceTryApplyInst(SILBuilder &builder, SILLocation loc, TryApplyInst *oldTAI,
531531
builder.setInsertionPoint(resultBB);
532532

533533
SILValue resultValue = resultBB->getArgument(0);
534-
resultValue = castValueToABICompatibleType(&builder, loc, resultValue,
535-
newResultTy, oldResultTy);
534+
std::tie(resultValue, std::ignore) = castValueToABICompatibleType(
535+
&builder, loc, resultValue, newResultTy, oldResultTy);
536536
builder.createBranch(loc, normalBB, {resultValue});
537537
}
538538

539539
builder.setInsertionPoint(normalBB->begin());
540540
return {newTAI, resultCastRequired};
541541
}
542542

543-
static BeginApplyInst *
543+
// Return the new begin_apply and true if a cast required CFG modification.
544+
static std::pair<BeginApplyInst *, bool /* changedCFG */>
544545
replaceBeginApplyInst(SILBuilder &builder, SILLocation loc,
545546
BeginApplyInst *oldBAI, SILValue newFn,
546547
SubstitutionMap newSubs, ArrayRef<SILValue> newArgs,
547548
ArrayRef<SILValue> newArgBorrows) {
549+
bool changedCFG = false;
548550
auto *newBAI = builder.createBeginApply(loc, newFn, newSubs, newArgs,
549551
oldBAI->isNonThrowing());
550552

@@ -558,13 +560,14 @@ replaceBeginApplyInst(SILBuilder &builder, SILLocation loc,
558560
for (auto i : indices(oldYields)) {
559561
auto oldYield = oldYields[i];
560562
auto newYield = newYields[i];
561-
newYield = castValueToABICompatibleType(
563+
auto yieldCastRes = castValueToABICompatibleType(
562564
&builder, loc, newYield, newYield->getType(), oldYield->getType());
563-
oldYield->replaceAllUsesWith(newYield);
565+
oldYield->replaceAllUsesWith(yieldCastRes.first);
566+
changedCFG |= yieldCastRes.second;
564567
}
565568

566569
if (newArgBorrows.empty())
567-
return newBAI;
570+
return {newBAI, changedCFG};
568571

569572
SILValue token = newBAI->getTokenResult();
570573

@@ -579,10 +582,11 @@ replaceBeginApplyInst(SILBuilder &builder, SILLocation loc,
579582
}
580583
}
581584

582-
return newBAI;
585+
return {newBAI, changedCFG};
583586
}
584587

585-
static PartialApplyInst *
588+
// Return the new partial_apply and true if a cast required CFG modification.
589+
static std::pair<PartialApplyInst *, bool /* changedCFG */>
586590
replacePartialApplyInst(SILBuilder &builder, SILLocation loc,
587591
PartialApplyInst *oldPAI, SILValue newFn,
588592
SubstitutionMap newSubs, ArrayRef<SILValue> newArgs) {
@@ -592,25 +596,24 @@ replacePartialApplyInst(SILBuilder &builder, SILLocation loc,
592596
builder.createPartialApply(loc, newFn, newSubs, newArgs, convention);
593597

594598
// Check if any casting is required for the partially-applied function.
595-
SILValue resultValue = castValueToABICompatibleType(
599+
auto castRes = castValueToABICompatibleType(
596600
&builder, loc, newPAI, newPAI->getType(), oldPAI->getType());
597-
oldPAI->replaceAllUsesWith(resultValue);
601+
oldPAI->replaceAllUsesWith(castRes.first);
598602

599-
return newPAI;
603+
return {newPAI, castRes.second};
600604
}
601605

602606
// Return the new apply and true if the CFG was also modified.
603-
static std::pair<ApplySite, bool>
607+
static std::pair<ApplySite, bool /* changedCFG */>
604608
replaceApplySite(SILBuilder &builder, SILLocation loc, ApplySite oldAS,
605609
SILValue newFn, SubstitutionMap newSubs,
606610
ArrayRef<SILValue> newArgs, SILFunctionConventions conv,
607611
ArrayRef<SILValue> newArgBorrows) {
608612
switch (oldAS.getKind()) {
609613
case ApplySiteKind::ApplyInst: {
610614
auto *oldAI = cast<ApplyInst>(oldAS);
611-
return {replaceApplyInst(builder, loc, oldAI, newFn, newSubs, newArgs,
612-
newArgBorrows),
613-
false};
615+
return replaceApplyInst(builder, loc, oldAI, newFn, newSubs, newArgs,
616+
newArgBorrows);
614617
}
615618
case ApplySiteKind::TryApplyInst: {
616619
auto *oldTAI = cast<TryApplyInst>(oldAS);
@@ -619,16 +622,14 @@ replaceApplySite(SILBuilder &builder, SILLocation loc, ApplySite oldAS,
619622
}
620623
case ApplySiteKind::BeginApplyInst: {
621624
auto *oldBAI = dyn_cast<BeginApplyInst>(oldAS);
622-
return {replaceBeginApplyInst(builder, loc, oldBAI, newFn, newSubs, newArgs,
623-
newArgBorrows),
624-
false};
625+
return replaceBeginApplyInst(builder, loc, oldBAI, newFn, newSubs, newArgs,
626+
newArgBorrows);
625627
}
626628
case ApplySiteKind::PartialApplyInst: {
627629
assert(newArgBorrows.empty());
628630
auto *oldPAI = cast<PartialApplyInst>(oldAS);
629-
return {
630-
replacePartialApplyInst(builder, loc, oldPAI, newFn, newSubs, newArgs),
631-
false};
631+
return replacePartialApplyInst(builder, loc, oldPAI, newFn, newSubs,
632+
newArgs);
632633
}
633634
}
634635
llvm_unreachable("covered switch");
@@ -734,10 +735,11 @@ bool swift::canDevirtualizeClassMethod(FullApplySite applySite, ClassDecl *cd,
734735
/// return the result value of the new ApplyInst if created one or null.
735736
///
736737
/// Return the new apply and true if the CFG was also modified.
737-
std::pair<FullApplySite, bool>
738+
std::pair<FullApplySite, bool /* changedCFG */>
738739
swift::devirtualizeClassMethod(FullApplySite applySite,
739740
SILValue classOrMetatype, ClassDecl *cd,
740741
OptRemark::Emitter *ore) {
742+
bool changedCFG = false;
741743
LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize : "
742744
<< *applySite.getInstruction());
743745

@@ -775,9 +777,11 @@ swift::devirtualizeClassMethod(FullApplySite applySite,
775777

776778
auto indirectResultArgIter = applySite.getIndirectSILResults().begin();
777779
for (auto resultTy : substConv.getIndirectSILResultTypes()) {
778-
newArgs.push_back(castValueToABICompatibleType(
780+
auto castRes = castValueToABICompatibleType(
779781
&builder, loc, *indirectResultArgIter, indirectResultArgIter->getType(),
780-
resultTy));
782+
resultTy);
783+
newArgs.push_back(castRes.first);
784+
changedCFG |= castRes.second;
781785
++indirectResultArgIter;
782786
}
783787

@@ -793,15 +797,18 @@ swift::devirtualizeClassMethod(FullApplySite applySite,
793797
arg = borrowBuilder.createBeginBorrow(loc, arg);
794798
newArgBorrows.push_back(arg);
795799
}
796-
arg = castValueToABICompatibleType(&builder, loc, arg,
800+
auto argCastRes = castValueToABICompatibleType(&builder, loc, arg,
797801
paramArgIter->getType(), paramType);
798-
newArgs.push_back(arg);
802+
803+
newArgs.push_back(argCastRes.first);
804+
changedCFG |= argCastRes.second;
799805
++paramArgIter;
800806
}
801807
ApplySite newAS;
802-
bool modifiedCFG;
803-
std::tie(newAS, modifiedCFG) = replaceApplySite(
808+
bool neededCFGChange;
809+
std::tie(newAS, neededCFGChange) = replaceApplySite(
804810
builder, loc, applySite, fri, subs, newArgs, substConv, newArgBorrows);
811+
changedCFG |= neededCFGChange;
805812
FullApplySite newAI = FullApplySite::isa(newAS.getInstruction());
806813
assert(newAI);
807814

@@ -815,7 +822,7 @@ swift::devirtualizeClassMethod(FullApplySite applySite,
815822
});
816823
NumClassDevirt++;
817824

818-
return {newAI, modifiedCFG};
825+
return {newAI, changedCFG};
819826
}
820827

821828
std::pair<FullApplySite, bool> swift::tryDevirtualizeClassMethod(
@@ -971,6 +978,7 @@ static std::pair<ApplySite, bool>
971978
devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f,
972979
ProtocolConformanceRef cRef,
973980
OptRemark::Emitter *ore) {
981+
bool changedCFG = false;
974982
// We know the witness thunk and the corresponding set of substitutions
975983
// required to invoke the protocol method at this point.
976984
auto &module = applySite.getModule();
@@ -1012,8 +1020,10 @@ devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f,
10121020
arg = borrowBuilder.createBeginBorrow(applySite.getLoc(), arg);
10131021
borrowedArgs.push_back(arg);
10141022
}
1015-
arg = castValueToABICompatibleType(&argBuilder, applySite.getLoc(), arg,
1016-
arg->getType(), paramType);
1023+
auto argCastRes = castValueToABICompatibleType(
1024+
&argBuilder, applySite.getLoc(), arg, arg->getType(), paramType);
1025+
arg = argCastRes.first;
1026+
changedCFG |= argCastRes.second;
10171027
}
10181028
arguments.push_back(arg);
10191029
}
@@ -1026,10 +1036,11 @@ devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f,
10261036
auto *fri = applyBuilder.createFunctionRefFor(loc, f);
10271037

10281038
ApplySite newApplySite;
1029-
bool modifiedCFG;
1030-
std::tie(newApplySite, modifiedCFG) =
1039+
bool neededCFGChange = false;
1040+
std::tie(newApplySite, neededCFGChange) =
10311041
replaceApplySite(applyBuilder, loc, applySite, fri, subMap, arguments,
10321042
substConv, borrowedArgs);
1043+
changedCFG |= neededCFGChange;
10331044

10341045
if (ore)
10351046
ore->emit([&]() {
@@ -1039,7 +1050,7 @@ devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f,
10391050
<< "Devirtualized call to " << NV("Method", f);
10401051
});
10411052
NumWitnessDevirt++;
1042-
return {newApplySite, modifiedCFG};
1053+
return {newApplySite, changedCFG};
10431054
}
10441055

10451056
static bool canDevirtualizeWitnessMethod(ApplySite applySite) {

0 commit comments

Comments
 (0)