@@ -822,12 +822,12 @@ static SILInstruction *tryDevirtualizeApplyHelper(FullApplySite InnerAI,
822822// /
823823// / \returns true if successful, false if failed due to circular inlining.
824824static bool
825- runOnFunctionRecursively (SILOptFunctionBuilder &FuncBuilder,
826- SILFunction *F, FullApplySite AI,
827- DenseFunctionSet &FullyInlinedSet,
825+ runOnFunctionRecursively (SILOptFunctionBuilder &FuncBuilder, SILFunction *F,
826+ FullApplySite AI, DenseFunctionSet &FullyInlinedSet,
828827 ImmutableFunctionSet::Factory &SetFactory,
829828 ImmutableFunctionSet CurrentInliningSet,
830- ClassHierarchyAnalysis *CHA) {
829+ ClassHierarchyAnalysis *CHA,
830+ DenseFunctionSet &changedFunctions) {
831831 // Avoid reprocessing functions needlessly.
832832 if (FullyInlinedSet.count (F))
833833 return true ;
@@ -874,6 +874,10 @@ runOnFunctionRecursively(SILOptFunctionBuilder &FuncBuilder,
874874 // but a casted result of InnerAI or even a block argument due to
875875 // abstraction changes when calling the witness or class method.
876876 auto *devirtInst = tryDevirtualizeApplyHelper (InnerAI, CHA);
877+ // If devirtualization succeeds, make sure we record that this function
878+ // changed.
879+ if (devirtInst != InnerAI.getInstruction ())
880+ changedFunctions.insert (F);
877881 // Restore II to the current apply site.
878882 II = devirtInst->getReverseIterator ();
879883 // If the devirtualized call result is no longer a invalid FullApplySite,
@@ -892,9 +896,9 @@ runOnFunctionRecursively(SILOptFunctionBuilder &FuncBuilder,
892896 continue ;
893897
894898 // Then recursively process it first before trying to inline it.
895- if (!runOnFunctionRecursively (FuncBuilder, CalleeFunction, InnerAI,
896- FullyInlinedSet, SetFactory,
897- CurrentInliningSet, CHA)) {
899+ if (!runOnFunctionRecursively (
900+ FuncBuilder, CalleeFunction, InnerAI, FullyInlinedSet, SetFactory,
901+ CurrentInliningSet, CHA, changedFunctions )) {
898902 // If we failed due to circular inlining, then emit some notes to
899903 // trace back the failure if we have more information.
900904 // FIXME: possibly it could be worth recovering and attempting other
@@ -984,6 +988,10 @@ runOnFunctionRecursively(SILOptFunctionBuilder &FuncBuilder,
984988 closureCleanup.cleanupDeadClosures (F);
985989 invalidatedStackNesting |= closureCleanup.invalidatedStackNesting ;
986990
991+ // Record that we inlined into this function so that we can invalidate it
992+ // later.
993+ changedFunctions.insert (F);
994+
987995 // Resume inlining within nextBB, which contains only the inlined
988996 // instructions and possibly instructions in the original call block that
989997 // have not yet been visited.
@@ -993,6 +1001,7 @@ runOnFunctionRecursively(SILOptFunctionBuilder &FuncBuilder,
9931001
9941002 if (invalidatedStackNesting) {
9951003 StackNesting ().correctStackNesting (F);
1004+ changedFunctions.insert (F);
9961005 }
9971006
9981007 // Keep track of full inlined functions so we don't waste time recursively
@@ -1012,10 +1021,10 @@ class MandatoryInlining : public SILModuleTransform {
10121021 void run () override {
10131022 ClassHierarchyAnalysis *CHA = getAnalysis<ClassHierarchyAnalysis>();
10141023 SILModule *M = getModule ();
1015- bool ShouldCleanup = !getOptions ().DebugSerialization ;
10161024 bool SILVerifyAll = getOptions ().VerifyAll ;
10171025 DenseFunctionSet FullyInlinedSet;
10181026 ImmutableFunctionSet::Factory SetFactory;
1027+ DenseFunctionSet changedFunctions;
10191028
10201029 SILOptFunctionBuilder FuncBuilder (*this );
10211030 for (auto &F : *M) {
@@ -1027,13 +1036,15 @@ class MandatoryInlining : public SILModuleTransform {
10271036 if (F.wasDeserializedCanonical ())
10281037 continue ;
10291038
1030- runOnFunctionRecursively (FuncBuilder, &F,
1031- FullApplySite (), FullyInlinedSet, SetFactory,
1032- SetFactory.getEmptySet (), CHA);
1039+ runOnFunctionRecursively (FuncBuilder, &F, FullApplySite (),
1040+ FullyInlinedSet, SetFactory,
1041+ SetFactory.getEmptySet (), CHA, changedFunctions );
10331042
10341043 // The inliner splits blocks at call sites. Re-merge trivial branches
10351044 // to reestablish a canonical CFG.
1036- mergeBasicBlocks (&F);
1045+ if (mergeBasicBlocks (&F)) {
1046+ changedFunctions.insert (&F);
1047+ }
10371048
10381049 // If we are asked to perform SIL verify all, perform that now so that we
10391050 // can discover the immediate inlining trigger of the problematic
@@ -1043,38 +1054,10 @@ class MandatoryInlining : public SILModuleTransform {
10431054 }
10441055 }
10451056
1046- if (!ShouldCleanup )
1057+ if (getOptions (). DebugSerialization )
10471058 return ;
1048-
1049- // Now that we've inlined some functions, clean up. If there are any
1050- // transparent functions that are deserialized from another module that are
1051- // now unused, just remove them from the module.
1052- //
1053- // We do this with a simple linear scan, because transparent functions that
1054- // reference each other have already been flattened.
1055- for (auto FI = M->begin (), E = M->end (); FI != E; ) {
1056- SILFunction &F = *FI++;
1057-
1058- invalidateAnalysis (&F, SILAnalysis::InvalidationKind::Everything);
1059-
1060- if (F.getRefCount () != 0 ) continue ;
1061-
1062- // Leave non-transparent functions alone.
1063- if (!F.isTransparent ())
1064- continue ;
1065-
1066- // We discard functions that don't have external linkage,
1067- // e.g. deserialized functions, internal functions, and thunks.
1068- // Being marked transparent controls this.
1069- if (F.isPossiblyUsedExternally ()) continue ;
1070-
1071- // ObjC functions are called through the runtime and are therefore alive
1072- // even if not referenced inside SIL.
1073- if (F.getRepresentation () == SILFunctionTypeRepresentation::ObjCMethod)
1074- continue ;
1075-
1076- // Okay, just erase the function from the module.
1077- FuncBuilder.eraseFunction (&F);
1059+ for (auto *F : changedFunctions) {
1060+ invalidateAnalysis (F, SILAnalysis::InvalidationKind::Everything);
10781061 }
10791062 }
10801063
0 commit comments