Skip to content

Commit f5cf517

Browse files
author
Harlan Haskins
committed
[Frontend] Factor out SIL processing code to Frontend
This lets us reuse the logic for running optimization passes between regular frontend invocations and parseable interface compilation.
1 parent be0bdd1 commit f5cf517

File tree

3 files changed

+92
-76
lines changed

3 files changed

+92
-76
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,13 @@ class CompilerInstance {
574574
/// parse-only invocation, module imports will be processed.
575575
void performParseAndResolveImportsOnly();
576576

577+
/// Performs mandatory, diagnostic, and optimization passes over the SIL.
578+
/// \param silModule The SIL module that was generated during SILGen.
579+
/// \param stats A stats reporter that will report optimization statistics.
580+
/// \returns true if any errors occurred.
581+
bool performSILProcessing(SILModule *silModule,
582+
UnifiedStatsReporter *stats = nullptr);
583+
577584
private:
578585
SourceFile *
579586
createSourceFileForMainModule(SourceFileKind FileKind,

lib/Frontend/Frontend.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/Parse/DelayedParsingCallbacks.h"
2727
#include "swift/Parse/Lexer.h"
2828
#include "swift/SIL/SILModule.h"
29+
#include "swift/SILOptimizer/PassManager/Passes.h"
2930
#include "swift/Serialization/SerializationOptions.h"
3031
#include "swift/Serialization/SerializedModuleLoader.h"
3132
#include "swift/Strings.h"
@@ -1078,6 +1079,85 @@ void CompilerInstance::freeASTContext() {
10781079

10791080
void CompilerInstance::freeSILModule() { TheSILModule.reset(); }
10801081

1082+
/// Perform "stable" optimizations that are invariant across compiler versions.
1083+
static bool performMandatorySILPasses(CompilerInvocation &Invocation,
1084+
SILModule *SM) {
1085+
if (Invocation.getFrontendOptions().RequestedAction ==
1086+
FrontendOptions::ActionType::MergeModules) {
1087+
// Don't run diagnostic passes at all.
1088+
} else if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) {
1089+
if (runSILDiagnosticPasses(*SM))
1090+
return true;
1091+
} else {
1092+
// Even if we are not supposed to run the diagnostic passes, we still need
1093+
// to run the ownership evaluator.
1094+
if (runSILOwnershipEliminatorPass(*SM))
1095+
return true;
1096+
}
1097+
1098+
if (Invocation.getSILOptions().MergePartialModules)
1099+
SM->linkAllFromCurrentModule();
1100+
return false;
1101+
}
1102+
1103+
/// Perform SIL optimization passes if optimizations haven't been disabled.
1104+
/// These may change across compiler versions.
1105+
static void performSILOptimizations(CompilerInvocation &Invocation,
1106+
SILModule *SM) {
1107+
SharedTimer timer("SIL optimization");
1108+
if (Invocation.getFrontendOptions().RequestedAction ==
1109+
FrontendOptions::ActionType::MergeModules ||
1110+
!Invocation.getSILOptions().shouldOptimize()) {
1111+
runSILPassesForOnone(*SM);
1112+
return;
1113+
}
1114+
runSILOptPreparePasses(*SM);
1115+
1116+
StringRef CustomPipelinePath =
1117+
Invocation.getSILOptions().ExternalPassPipelineFilename;
1118+
if (!CustomPipelinePath.empty()) {
1119+
runSILOptimizationPassesWithFileSpecification(*SM, CustomPipelinePath);
1120+
} else {
1121+
runSILOptimizationPasses(*SM);
1122+
}
1123+
}
1124+
1125+
static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
1126+
const SILModule& Module) {
1127+
auto &C = Stats.getFrontendCounters();
1128+
// FIXME: calculate these in constant time, via the dense maps.
1129+
C.NumSILOptFunctions += Module.getFunctionList().size();
1130+
C.NumSILOptVtables += Module.getVTableList().size();
1131+
C.NumSILOptWitnessTables += Module.getWitnessTableList().size();
1132+
C.NumSILOptDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
1133+
C.NumSILOptGlobalVariables += Module.getSILGlobalList().size();
1134+
}
1135+
1136+
bool CompilerInstance::performSILProcessing(SILModule *silModule,
1137+
UnifiedStatsReporter *stats) {
1138+
if (performMandatorySILPasses(Invocation, silModule))
1139+
return true;
1140+
1141+
{
1142+
SharedTimer timer("SIL verification, pre-optimization");
1143+
silModule->verify();
1144+
}
1145+
1146+
performSILOptimizations(Invocation, silModule);
1147+
1148+
if (stats)
1149+
countStatsPostSILOpt(*stats, *silModule);
1150+
1151+
{
1152+
SharedTimer timer("SIL verification, post-optimization");
1153+
silModule->verify();
1154+
}
1155+
1156+
performSILInstCountIfNeeded(silModule);
1157+
return false;
1158+
}
1159+
1160+
10811161
const PrimarySpecificPaths &
10821162
CompilerInstance::getPrimarySpecificPathsForWholeModuleOptimizationMode()
10831163
const {

lib/FrontendTool/FrontendTool.cpp

Lines changed: 5 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -515,17 +515,6 @@ static void countStatsPostSILGen(UnifiedStatsReporter &Stats,
515515
C.NumSILGenGlobalVariables += Module.getSILGlobalList().size();
516516
}
517517

518-
static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
519-
const SILModule& Module) {
520-
auto &C = Stats.getFrontendCounters();
521-
// FIXME: calculate these in constant time, via the dense maps.
522-
C.NumSILOptFunctions += Module.getFunctionList().size();
523-
C.NumSILOptVtables += Module.getVTableList().size();
524-
C.NumSILOptWitnessTables += Module.getWitnessTableList().size();
525-
C.NumSILOptDefaultWitnessTables += Module.getDefaultWitnessTableList().size();
526-
C.NumSILOptGlobalVariables += Module.getSILGlobalList().size();
527-
}
528-
529518
static std::unique_ptr<llvm::raw_fd_ostream>
530519
createOptRecordFile(StringRef Filename, DiagnosticEngine &DE) {
531520
if (Filename.empty())
@@ -1038,50 +1027,6 @@ static bool performCompile(CompilerInstance &Instance,
10381027
return false;
10391028
}
10401029

1041-
/// Perform "stable" optimizations that are invariant across compiler versions.
1042-
static bool performMandatorySILPasses(CompilerInvocation &Invocation,
1043-
SILModule *SM,
1044-
FrontendObserver *observer) {
1045-
if (Invocation.getFrontendOptions().RequestedAction ==
1046-
FrontendOptions::ActionType::MergeModules) {
1047-
// Don't run diagnostic passes at all.
1048-
} else if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) {
1049-
if (runSILDiagnosticPasses(*SM))
1050-
return true;
1051-
} else {
1052-
// Even if we are not supposed to run the diagnostic passes, we still need
1053-
// to run the ownership evaluator.
1054-
if (runSILOwnershipEliminatorPass(*SM))
1055-
return true;
1056-
}
1057-
1058-
if (Invocation.getSILOptions().MergePartialModules)
1059-
SM->linkAllFromCurrentModule();
1060-
return false;
1061-
}
1062-
1063-
/// Perform SIL optimization passes if optimizations haven't been disabled.
1064-
/// These may change across compiler versions.
1065-
static void performSILOptimizations(CompilerInvocation &Invocation,
1066-
SILModule *SM) {
1067-
SharedTimer timer("SIL optimization");
1068-
if (Invocation.getFrontendOptions().RequestedAction ==
1069-
FrontendOptions::ActionType::MergeModules ||
1070-
!Invocation.getSILOptions().shouldOptimize()) {
1071-
runSILPassesForOnone(*SM);
1072-
return;
1073-
}
1074-
runSILOptPreparePasses(*SM);
1075-
1076-
StringRef CustomPipelinePath =
1077-
Invocation.getSILOptions().ExternalPassPipelineFilename;
1078-
if (!CustomPipelinePath.empty()) {
1079-
runSILOptimizationPassesWithFileSpecification(*SM, CustomPipelinePath);
1080-
} else {
1081-
runSILOptimizationPasses(*SM);
1082-
}
1083-
}
1084-
10851030
/// Get the main source file's private discriminator and attach it to
10861031
/// the compile unit's flags.
10871032
static void setPrivateDiscriminatorIfNeeded(IRGenOptions &IRGenOpts,
@@ -1255,17 +1200,6 @@ static bool performCompileStepsPostSILGen(
12551200
SM->setOptRecordStream(std::move(Output), std::move(OptRecordFile));
12561201
}
12571202

1258-
if (performMandatorySILPasses(Invocation, SM.get(), observer))
1259-
return true;
1260-
1261-
{
1262-
SharedTimer timer("SIL verification, pre-optimization");
1263-
SM->verify();
1264-
}
1265-
1266-
emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, Invocation,
1267-
moduleIsPublic);
1268-
12691203
// This is the action to be used to serialize SILModule.
12701204
// It may be invoked multiple times, but it will perform
12711205
// serialization only once. The serialization may either happen
@@ -1286,17 +1220,12 @@ static bool performCompileStepsPostSILGen(
12861220
// can be serialized at any moment, e.g. during the optimization pipeline.
12871221
SM->setSerializeSILAction(SerializeSILModuleAction);
12881222

1289-
performSILOptimizations(Invocation, SM.get());
1290-
1291-
if (Stats)
1292-
countStatsPostSILOpt(*Stats, *SM);
1293-
1294-
{
1295-
SharedTimer timer("SIL verification, post-optimization");
1296-
SM->verify();
1297-
}
1223+
// Perform optimizations and mandatory/diagnostic passes.
1224+
if (Instance.performSILProcessing(SM.get(), Stats))
1225+
return true;
12981226

1299-
performSILInstCountIfNeeded(&*SM);
1227+
emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, Invocation,
1228+
moduleIsPublic);
13001229

13011230
setPrivateDiscriminatorIfNeeded(IRGenOpts, MSF);
13021231

0 commit comments

Comments
 (0)