@@ -262,8 +262,7 @@ static bool shouldAttemptEvaluation(SILInstruction *inst) {
262
262
SILFunction *calleeFun = apply->getCalleeFunction ();
263
263
if (!calleeFun)
264
264
return false ;
265
- return isKnownConstantEvaluableFunction (calleeFun) ||
266
- isConstantEvaluable (calleeFun);
265
+ return isConstantEvaluable (calleeFun);
267
266
}
268
267
269
268
// / Skip or evaluate the given instruction based on the evaluation policy and
@@ -780,20 +779,11 @@ static SILValue emitCodeForSymbolicValue(SymbolicValue symVal,
780
779
}
781
780
}
782
781
783
- // / Collect the end points of the instructions that are data dependent on \c
784
- // / value. A instruction is data dependent on \c value if its result may
785
- // / transitively depends on \c value. Note that data dependencies through
786
- // / addresses are not tracked by this function.
787
- // /
788
- // / \param value SILValue that is not an address.
789
- // / \param fun SILFunction that defines \c value.
790
- // / \param endUsers buffer for storing the found end points of the data
791
- // / dependence chain.
792
- static void
793
- getEndPointsOfDataDependentChain (SILValue value, SILFunction *fun,
794
- SmallVectorImpl<SILInstruction *> &endUsers) {
795
- assert (!value->getType ().isAddress ());
796
-
782
+ // / Given a SILValue \p value, compute the set of transitive users of the value
783
+ // / (excluding value itself) by following the use-def chain starting at value.
784
+ // / Note that this function does not follow use-def chains though branches.
785
+ static void getTransitiveUsers (SILValue value,
786
+ SmallVectorImpl<SILInstruction *> &users) {
797
787
// Collect the instructions that are data dependent on the value using a
798
788
// fix point iteration.
799
789
SmallPtrSet<SILInstruction *, 16 > visitedUsers;
@@ -810,17 +800,40 @@ getEndPointsOfDataDependentChain(SILValue value, SILFunction *fun,
810
800
llvm::copy (user->getResults (), std::back_inserter (worklist));
811
801
}
812
802
}
813
-
814
803
// At this point, visitedUsers have all the transitive, data-dependent uses.
815
- // Compute the lifetime frontier of all the uses which are the instructions
816
- // following the last uses. Every exit from the last uses will have a
817
- // lifetime frontier.
804
+ users.append (visitedUsers.begin (), visitedUsers.end ());
805
+ }
806
+
807
+ // / Collect the end points of the instructions that are data dependent on \c
808
+ // / value. A instruction is data dependent on \c value if its result may
809
+ // / transitively depends on \c value. Note that data dependencies through
810
+ // / addresses are not tracked by this function.
811
+ // /
812
+ // / \param value SILValue that is not an address.
813
+ // / \param fun SILFunction that defines \c value.
814
+ // / \param endUsers buffer for storing the found end points of the data
815
+ // / dependence chain.
816
+ static void
817
+ getEndPointsOfDataDependentChain (SILValue value, SILFunction *fun,
818
+ SmallVectorImpl<SILInstruction *> &endUsers) {
819
+ assert (!value->getType ().isAddress ());
820
+
821
+ SmallVector<SILInstruction *, 16 > transitiveUsers;
822
+ // Get transitive users of value, ignoring use-def chain going through
823
+ // branches. These transitive users define the end points of the constant
824
+ // evaluation. Igoring use-def chains through branches causes constant
825
+ // evaluation to miss some constant folding opportunities. This can be
826
+ // relaxed in the future, if necessary.
827
+ getTransitiveUsers (value, transitiveUsers);
828
+
829
+ // Compute the lifetime frontier of all the transitive uses which are the
830
+ // instructions following the last uses. Every exit from the last uses will
831
+ // have a lifetime frontier.
818
832
SILInstruction *valueDefinition = value->getDefiningInstruction ();
819
833
SILInstruction *def =
820
834
valueDefinition ? valueDefinition : &(value->getParentBlock ()->front ());
821
835
ValueLifetimeAnalysis lifetimeAnalysis =
822
- ValueLifetimeAnalysis (def, SmallVector<SILInstruction *, 16 >(
823
- visitedUsers.begin (), visitedUsers.end ()));
836
+ ValueLifetimeAnalysis (def, transitiveUsers);
824
837
ValueLifetimeAnalysis::Frontier frontier;
825
838
bool hasCriticlEdges = lifetimeAnalysis.computeFrontier (
826
839
frontier, ValueLifetimeAnalysis::DontModifyCFG);
@@ -936,7 +949,7 @@ static void replaceAllUsesAndFixLifetimes(SILValue foldedVal,
936
949
static void substituteConstants (FoldState &foldState) {
937
950
ConstExprStepEvaluator &evaluator = foldState.constantEvaluator ;
938
951
// Instructions that are possibly dead since their results are folded.
939
- SmallVector<SILInstruction *, 4 > possiblyDeadInsts;
952
+ SmallVector<SILInstruction *, 8 > possiblyDeadInsts;
940
953
941
954
for (SILValue constantSILValue : foldState.getConstantSILValues ()) {
942
955
SymbolicValue constantSymbolicVal =
@@ -980,13 +993,11 @@ static void substituteConstants(FoldState &foldState) {
980
993
replaceAllUsesAndFixLifetimes (foldedSILVal, constantSILValue, fun);
981
994
possiblyDeadInsts.push_back (definingInst);
982
995
}
983
- recursivelyDeleteTriviallyDeadInstructions (possiblyDeadInsts, /* force*/ false ,
984
- [&](SILInstruction *DeadI) {});
985
996
}
986
997
987
998
// / Check whether OSLogMessage and OSLogInterpolation instances and all their
988
999
// / stored properties are constants. If not, it indicates errors that are due to
989
- // / incorrect implementation OSLogMessage either in the overlay or in the
1000
+ // / incorrect implementation of OSLogMessage either in the overlay or in the
990
1001
// / extensions created by users. Detect and emit diagnostics for such errors.
991
1002
// / The diagnostics here are for os log library authors.
992
1003
static bool checkOSLogMessageIsConstant (SingleValueInstruction *osLogMessage,
@@ -1048,6 +1059,37 @@ static bool checkOSLogMessageIsConstant(SingleValueInstruction *osLogMessage,
1048
1059
return errorDetected;
1049
1060
}
1050
1061
1062
+ // / Try to dead-code eliminate the OSLogMessage instance \c oslogMessage passed
1063
+ // / to the os log call and clean up its dependencies. If the instance cannot be
1064
+ // / eliminated, it implies that either the instance is not auto-generated or the
1065
+ // / implementation of the os log overlay is incorrect. Therefore emit
1066
+ // / diagnostics in such cases.
1067
+ static void tryEliminateOSLogMessage (SingleValueInstruction *oslogMessage) {
1068
+ // Collect the set of root instructions that could be dead due to constant
1069
+ // folding. These include the oslogMessage initialzer call and its transitive
1070
+ // users.
1071
+ SmallVector<SILInstruction *, 8 > oslogMessageUsers;
1072
+ getTransitiveUsers (oslogMessage, oslogMessageUsers);
1073
+
1074
+ InstructionDeleter deleter;
1075
+ for (SILInstruction *user : oslogMessageUsers)
1076
+ deleter.trackIfDead (user);
1077
+ deleter.trackIfDead (oslogMessage);
1078
+
1079
+ bool isOSLogMessageDead = false ;
1080
+ deleter.cleanUpDeadInstructions ([&](SILInstruction *deadInst) {
1081
+ if (deadInst == oslogMessage)
1082
+ isOSLogMessageDead = true ;
1083
+ });
1084
+ // At this point, the OSLogMessage instance must be deleted if
1085
+ // the overlay implementation (or its extensions by users) is correct.
1086
+ if (!isOSLogMessageDead) {
1087
+ SILFunction *fun = oslogMessage->getFunction ();
1088
+ diagnose (fun->getASTContext (), oslogMessage->getLoc ().getSourceLoc (),
1089
+ diag::oslog_message_alive_after_opts);
1090
+ }
1091
+ }
1092
+
1051
1093
// / Constant evaluate instructions starting from 'start' and fold the uses
1052
1094
// / of the value 'oslogMessage'. Stop when oslogMessageValue is released.
1053
1095
static bool constantFold (SILInstruction *start,
@@ -1076,6 +1118,8 @@ static bool constantFold(SILInstruction *start,
1076
1118
return false ;
1077
1119
1078
1120
substituteConstants (state);
1121
+
1122
+ tryEliminateOSLogMessage (oslogMessage);
1079
1123
return true ;
1080
1124
}
1081
1125
0 commit comments