Skip to content

Commit 3716858

Browse files
author
Harlan Haskins
authored
Merge pull request swiftlang#20936 from harlanhaskins/optimus-prime
[ParseableInterface] Optimize parseable modules
2 parents f8852c9 + 735267d commit 3716858

File tree

7 files changed

+128
-99
lines changed

7 files changed

+128
-99
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,

include/swift/Option/Options.td

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ def module_cache_path : Separate<["-"], "module-cache-path">,
278278
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
279279
HelpText<"Specifies the Clang module cache path">;
280280

281-
def module_name : Separate<["-"], "module-name">, Flags<[FrontendOption, ParseableInterfaceOption]>,
281+
def module_name : Separate<["-"], "module-name">,
282+
Flags<[FrontendOption, ParseableInterfaceOption]>,
282283
HelpText<"Name of the module to build">;
283284
def module_name_EQ : Joined<["-"], "module-name=">, Flags<[FrontendOption]>,
284285
Alias<module_name>;
@@ -464,17 +465,20 @@ def Xlinker : Separate<["-"], "Xlinker">,
464465

465466
def O_Group : OptionGroup<"<optimization level options>">;
466467

467-
def Onone : Flag<["-"], "Onone">, Group<O_Group>, Flags<[FrontendOption]>,
468+
def Onone : Flag<["-"], "Onone">, Group<O_Group>,
469+
Flags<[FrontendOption, ParseableInterfaceOption]>,
468470
HelpText<"Compile without any optimization">;
469-
def O : Flag<["-"], "O">, Group<O_Group>, Flags<[FrontendOption]>,
471+
def O : Flag<["-"], "O">, Group<O_Group>,
472+
Flags<[FrontendOption, ParseableInterfaceOption]>,
470473
HelpText<"Compile with optimizations">;
471-
def Osize : Flag<["-"], "Osize">, Group<O_Group>, Flags<[FrontendOption]>,
474+
def Osize : Flag<["-"], "Osize">, Group<O_Group>,
475+
Flags<[FrontendOption, ParseableInterfaceOption]>,
472476
HelpText<"Compile with optimizations and target small code size">;
473477
def Ounchecked : Flag<["-"], "Ounchecked">, Group<O_Group>,
474-
Flags<[FrontendOption]>,
478+
Flags<[FrontendOption, ParseableInterfaceOption]>,
475479
HelpText<"Compile with optimizations and remove runtime safety checks">;
476480
def Oplayground : Flag<["-"], "Oplayground">, Group<O_Group>,
477-
Flags<[HelpHidden, FrontendOption]>,
481+
Flags<[HelpHidden, FrontendOption, ParseableInterfaceOption]>,
478482
HelpText<"Compile with optimizations appropriate for a playground">;
479483

480484
def RemoveRuntimeAsserts : Flag<["-"], "remove-runtime-asserts">,

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/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ static bool buildSwiftModuleFromSwiftInterface(
307307
return;
308308
}
309309

310+
// Optimize emitted modules. This has to happen after we parse arguments,
311+
// because parseSILOpts would override the current optimization mode.
312+
SubInvocation.getSILOptions().OptMode = OptimizationMode::ForSpeed;
313+
310314
// Build the .swiftmodule; this is a _very_ abridged version of the logic in
311315
// performCompile in libFrontendTool, specialized, to just the one
312316
// module-serialization task we're trying to do here.
@@ -334,17 +338,14 @@ static bool buildSwiftModuleFromSwiftInterface(
334338
SILOptions &SILOpts = SubInvocation.getSILOptions();
335339
auto Mod = SubInstance.getMainModule();
336340
auto SILMod = performSILGeneration(Mod, SILOpts);
337-
if (SILMod) {
338-
LLVM_DEBUG(llvm::dbgs() << "Running SIL diagnostic passes\n");
339-
if (runSILDiagnosticPasses(*SILMod)) {
340-
LLVM_DEBUG(llvm::dbgs() << "encountered errors\n");
341-
SubError = true;
342-
return;
343-
}
344-
SILMod->verify();
341+
if (!SILMod) {
342+
LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n");
343+
SubError = true;
344+
return;
345345
}
346346

347-
LLVM_DEBUG(llvm::dbgs() << "Serializing " << OutPath << "\n");
347+
// Setup the callbacks for serialization, which can occur during the
348+
// optimization pipeline.
348349
FrontendOptions &FEOpts = SubInvocation.getFrontendOptions();
349350
SerializationOptions SerializationOpts;
350351
std::string OutPathStr = OutPath;
@@ -358,9 +359,16 @@ static bool buildSwiftModuleFromSwiftInterface(
358359
}
359360
SerializationOpts.Dependencies = Deps;
360361
SILMod->setSerializeSILAction([&]() {
361-
serialize(Mod, SerializationOpts, SILMod.get());
362-
});
363-
SILMod->serialize();
362+
serialize(Mod, SerializationOpts, SILMod.get());
363+
});
364+
365+
LLVM_DEBUG(llvm::dbgs() << "Running SIL processing passes\n");
366+
if (SubInstance.performSILProcessing(SILMod.get())) {
367+
LLVM_DEBUG(llvm::dbgs() << "encountered errors\n");
368+
SubError = true;
369+
return;
370+
}
371+
364372
SubError = Diags.hadAnyError();
365373
});
366374
return !RunSuccess || SubError;

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

test/ParseableInterface/ModuleCache/module-cache-init.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
// RUN: llvm-bcanalyzer -dump %t/modulecache/LeafModule-*.swiftmodule | %FileCheck %s -check-prefix=CHECK-LEAFMODULE
2626
// CHECK-LEAFMODULE: {{MODULE_NAME.*blob data = 'LeafModule'}}
2727
// CHECK-LEAFMODULE: {{FILE_DEPENDENCY.*Swift.swiftmodule'}}
28-
// CHECK-LEAFMODULE: {{FILE_DEPENDENCY.*SwiftOnoneSupport.swiftmodule'}}
2928
// CHECK-LEAFMODULE: {{FILE_DEPENDENCY.*LeafModule.swiftinterface'}}
3029
// CHECK-LEAFMODULE: FUNC_DECL
3130
//
@@ -39,7 +38,6 @@
3938
// RUN: llvm-bcanalyzer -dump %t/modulecache/OtherModule-*.swiftmodule | %FileCheck %s -check-prefix=CHECK-OTHERMODULE
4039
// CHECK-OTHERMODULE: {{MODULE_NAME.*blob data = 'OtherModule'}}
4140
// CHECK-OTHERMODULE: {{FILE_DEPENDENCY.*Swift.swiftmodule'}}
42-
// CHECK-OTHERMODULE: {{FILE_DEPENDENCY.*SwiftOnoneSupport.swiftmodule'}}
4341
// CHECK-OTHERMODULE: {{FILE_DEPENDENCY.*LeafModule.swiftinterface'}}
4442
// CHECK-OTHERMODULE: {{FILE_DEPENDENCY.*LeafModule-.*.swiftmodule'}}
4543
// CHECK-OTHERMODULE: {{FILE_DEPENDENCY.*OtherModule.swiftinterface'}}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend -enable-resilience -emit-parseable-module-interface-path %t.swiftinterface -module-name t %s -emit-module -o /dev/null
3+
// RUN: %target-swift-frontend -enable-resilience -emit-parseable-module-interface-path %t.swiftinterface -module-name t %s -emit-module -o /dev/null -Onone
44
// RUN: %FileCheck %s < %t.swiftinterface -check-prefix=CHECK-SWIFTINTERFACE
55
//
6-
// CHECK-SWIFTINTERFACE: {{swift-module-flags:.* -enable-resilience}}
6+
// CHECK-SWIFTINTERFACE: swift-module-flags:
7+
// CHECK-SWIFTINTERFACE-SAME: -enable-resilience
8+
// CHECK-SWIFTINTERFACE-SAME: -Onone
79

810
// Make sure flags show up when filelists are enabled
911

10-
// RUN: %target-build-swift %s -driver-filelist-threshold=0 -emit-parseable-module-interface -o %t/foo -module-name foo -module-link-name fooCore -force-single-frontend-invocation 2>&1
12+
// RUN: %target-build-swift %s -driver-filelist-threshold=0 -emit-parseable-module-interface -o %t/foo -module-name foo -module-link-name fooCore -force-single-frontend-invocation -Ounchecked 2>&1
1113
// RUN: %FileCheck %s < %t/foo.swiftinterface --check-prefix CHECK-FILELIST-INTERFACE
1214

1315
// CHECK-FILELIST-INTERFACE: swift-module-flags:
1416
// CHECK-FILELIST-INTERFACE-SAME: -target
1517
// CHECK-FILELIST-INTERFACE-SAME: -module-link-name fooCore
18+
// CHECK-FILELIST-INTERFACE-SAME: -Ounchecked
1619
// CHECK-FILELIST-INTERFACE-SAME: -module-name foo
1720

1821
public func foo() { }

0 commit comments

Comments
 (0)