Skip to content

Commit baee1cd

Browse files
authored
Merge pull request #14074 from graydon/batch-mode-driver-work
More batch mode driver work
2 parents 1c88937 + d139ab2 commit baee1cd

File tree

10 files changed

+182
-84
lines changed

10 files changed

+182
-84
lines changed

include/swift/Driver/Compilation.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ class Compilation {
7070
/// The DiagnosticEngine to which this Compilation should emit diagnostics.
7171
DiagnosticEngine &Diags;
7272

73+
/// The ToolChain this Compilation was built with, that it may reuse to build
74+
/// subsequent BatchJobs.
75+
const ToolChain &TheToolChain;
76+
7377
/// The OutputLevel at which this Compilation should generate output.
7478
OutputLevel Level;
7579

@@ -172,7 +176,8 @@ class Compilation {
172176
ArrayRefView<std::unique_ptr<T>, T *, Compilation::unwrap<T>>;
173177

174178
public:
175-
Compilation(DiagnosticEngine &Diags, OutputLevel Level,
179+
Compilation(DiagnosticEngine &Diags, const ToolChain &TC,
180+
OutputLevel Level,
176181
std::unique_ptr<llvm::opt::InputArgList> InputArgs,
177182
std::unique_ptr<llvm::opt::DerivedArgList> TranslatedArgs,
178183
InputFileList InputsWithTypes,

include/swift/Driver/Driver.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class OutputInfo {
6565
/// A compilation using a single frontend invocation without -primary-file.
6666
SingleCompile,
6767

68+
/// A single process that batches together multiple StandardCompile jobs.
69+
BatchModeCompile,
70+
6871
/// Invoke the REPL
6972
REPL,
7073

@@ -175,13 +178,28 @@ class Driver {
175178

176179
void setCheckInputFilesExist(bool Value) { CheckInputFilesExist = Value; }
177180

178-
/// Construct a compilation object for a command line argument vector.
181+
/// Creates an appropriate ToolChain for a given driver, given the target
182+
/// specified in \p Args (or the default target). Sets the value of \c
183+
/// DefaultTargetTriple from \p Args as a side effect.
184+
///
185+
/// \return A ToolChain, or nullptr if an unsupported target was specified
186+
/// (in which case a diagnostic error is also signalled).
187+
///
188+
/// This uses a std::unique_ptr instead of returning a toolchain by value
189+
/// because ToolChain has virtual methods.
190+
std::unique_ptr<ToolChain>
191+
buildToolChain(const llvm::opt::InputArgList &ArgList);
192+
193+
/// Construct a compilation object for a given ToolChain and command line
194+
/// argument vector.
179195
///
180196
/// \return A Compilation, or nullptr if none was built for the given argument
181197
/// vector. A null return value does not necessarily indicate an error
182198
/// condition; the diagnostics should be queried to determine if an error
183199
/// occurred.
184-
std::unique_ptr<Compilation> buildCompilation(ArrayRef<const char *> Args);
200+
std::unique_ptr<Compilation>
201+
buildCompilation(const ToolChain &TC,
202+
std::unique_ptr<llvm::opt::InputArgList> ArgList);
185203

186204
/// Parse the given list of strings into an InputArgList.
187205
std::unique_ptr<llvm::opt::InputArgList>
@@ -296,9 +314,9 @@ class Driver {
296314
llvm::SmallString<128> &Buf,
297315
CommandOutput *Output) const;
298316

299-
void chooseSaveOptimizationPath(Compilation &C, const OutputInfo &OI,
300-
llvm::SmallString<128> &Buf,
301-
CommandOutput *Output) const;
317+
void chooseOptimizationRecordPath(Compilation &C, const OutputInfo &OI,
318+
llvm::SmallString<128> &Buf,
319+
CommandOutput *Output) const;
302320

303321
void chooseObjectiveCHeaderOutputPath(Compilation &C, const OutputInfo &OI,
304322
const TypeToPathMap *OutputMap,

include/swift/Driver/Job.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,31 @@ class Job {
184184
const llvm::opt::ArgStringList &Args);
185185
};
186186

187+
/// A BatchJob comprises a _set_ of jobs, each of which is sufficiently similar
188+
/// to the others that the whole set can be combined into a single subprocess
189+
/// (and thus run potentially more-efficiently than running each Job in the set
190+
/// individually).
191+
///
192+
/// Not all Jobs can be combined into a BatchJob: at present, only those Jobs
193+
/// that come from CompileJobActions, and which otherwise have the exact same
194+
/// input file list and arguments as one another, aside from their primary-file.
195+
/// See ToolChain::jobsAreBatchCombinable for details.
196+
197+
class BatchJob : public Job {
198+
SmallVector<const Job *, 4> CombinedJobs;
199+
public:
200+
BatchJob(const JobAction &Source, SmallVectorImpl<const Job *> &&Inputs,
201+
std::unique_ptr<CommandOutput> Output, const char *Executable,
202+
llvm::opt::ArgStringList Arguments,
203+
EnvironmentVector ExtraEnvironment,
204+
std::vector<FilelistInfo> Infos,
205+
ArrayRef<const Job *> Combined);
206+
207+
ArrayRef<const Job*> getCombinedJobs() const {
208+
return CombinedJobs;
209+
}
210+
};
211+
187212
} // end namespace driver
188213
} // end namespace swift
189214

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,10 @@ def whole_module_optimization : Flag<["-"], "whole-module-optimization">,
619619
HelpText<"Optimize input files together instead of individually">,
620620
Flags<[FrontendOption, NoInteractiveOption]>;
621621

622+
def batch_mode : Flag<["-"], "batch-mode">,
623+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
624+
HelpText<"Combine frontend jobs into batches">;
625+
622626
def wmo : Flag<["-"], "wmo">, Alias<whole_module_optimization>,
623627
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>;
624628

lib/Driver/Compilation.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const LogJobSet &ljs) {
8484
}
8585

8686

87-
Compilation::Compilation(DiagnosticEngine &Diags, OutputLevel Level,
87+
Compilation::Compilation(DiagnosticEngine &Diags,
88+
const ToolChain &TC, OutputLevel Level,
8889
std::unique_ptr<InputArgList> InputArgs,
8990
std::unique_ptr<DerivedArgList> TranslatedArgs,
9091
InputFileList InputsWithTypes,
@@ -95,7 +96,8 @@ Compilation::Compilation(DiagnosticEngine &Diags, OutputLevel Level,
9596
bool SaveTemps,
9697
bool ShowDriverTimeCompilation,
9798
std::unique_ptr<UnifiedStatsReporter> StatsReporter)
98-
: Diags(Diags), Level(Level), RawInputArgs(std::move(InputArgs)),
99+
: Diags(Diags), TheToolChain(TC), Level(Level),
100+
RawInputArgs(std::move(InputArgs)),
99101
TranslatedArgs(std::move(TranslatedArgs)),
100102
InputFilesWithTypes(std::move(InputsWithTypes)), ArgsHash(ArgsHash),
101103
BuildStartTime(StartTime),

lib/Driver/Driver.cpp

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -197,42 +197,46 @@ static void validateArgs(DiagnosticEngine &diags, const ArgList &Args) {
197197
}
198198
}
199199

200-
/// Creates an appropriate ToolChain for a given driver and target triple.
201-
///
202-
/// This uses a std::unique_ptr instead of returning a toolchain by value
203-
/// because ToolChain has virtual methods.
204-
static std::unique_ptr<const ToolChain>
205-
makeToolChain(Driver &driver, const llvm::Triple &target) {
200+
std::unique_ptr<ToolChain>
201+
Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) {
202+
203+
if (const Arg *A = ArgList.getLastArg(options::OPT_target))
204+
DefaultTargetTriple = llvm::Triple::normalize(A->getValue());
205+
206+
const llvm::Triple target(DefaultTargetTriple);
207+
206208
switch (target.getOS()) {
207209
case llvm::Triple::Darwin:
208210
case llvm::Triple::MacOSX:
209211
case llvm::Triple::IOS:
210212
case llvm::Triple::TvOS:
211213
case llvm::Triple::WatchOS:
212-
return llvm::make_unique<toolchains::Darwin>(driver, target);
214+
return llvm::make_unique<toolchains::Darwin>(*this, target);
213215
break;
214216
case llvm::Triple::Linux:
215217
if (target.isAndroid()) {
216-
return llvm::make_unique<toolchains::Android>(driver, target);
218+
return llvm::make_unique<toolchains::Android>(*this, target);
217219
} else {
218-
return llvm::make_unique<toolchains::GenericUnix>(driver, target);
220+
return llvm::make_unique<toolchains::GenericUnix>(*this, target);
219221
}
220222
break;
221223
case llvm::Triple::FreeBSD:
222-
return llvm::make_unique<toolchains::GenericUnix>(driver, target);
224+
return llvm::make_unique<toolchains::GenericUnix>(*this, target);
223225
break;
224226
case llvm::Triple::Win32:
225-
return llvm::make_unique<toolchains::Cygwin>(driver, target);
227+
return llvm::make_unique<toolchains::Cygwin>(*this, target);
226228
break;
227229
case llvm::Triple::Haiku:
228-
return llvm::make_unique<toolchains::GenericUnix>(driver, target);
230+
return llvm::make_unique<toolchains::GenericUnix>(*this, target);
229231
break;
230232
default:
231-
return nullptr;
233+
Diags.diagnose(SourceLoc(), diag::error_unknown_target,
234+
ArgList.getLastArg(options::OPT_target)->getValue());
235+
break;
232236
}
237+
return nullptr;
233238
}
234239

235-
236240
static void computeArgsHash(SmallString<32> &out, const DerivedArgList &args) {
237241
SmallVector<const Arg *, 32> interestingArgs;
238242
interestingArgs.reserve(args.size());
@@ -501,16 +505,13 @@ static void validateEmbedBitcode(DerivedArgList &Args, OutputInfo &OI,
501505
}
502506
}
503507

504-
std::unique_ptr<Compilation> Driver::buildCompilation(
505-
ArrayRef<const char *> Args) {
508+
std::unique_ptr<Compilation>
509+
Driver::buildCompilation(const ToolChain &TC,
510+
std::unique_ptr<llvm::opt::InputArgList> ArgList) {
506511
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
507512

508513
llvm::sys::TimePoint<> StartTime = std::chrono::system_clock::now();
509514

510-
std::unique_ptr<InputArgList> ArgList(parseArgStrings(Args.slice(1)));
511-
if (Diags.hadAnyError())
512-
return nullptr;
513-
514515
// Claim --driver-mode here, since it's already been handled.
515516
(void) ArgList->hasArg(options::OPT_driver_mode);
516517

@@ -552,36 +553,25 @@ std::unique_ptr<Compilation> Driver::buildCompilation(
552553
std::unique_ptr<DerivedArgList> TranslatedArgList(
553554
translateInputArgs(*ArgList));
554555

555-
if (const Arg *A = ArgList->getLastArg(options::OPT_target))
556-
DefaultTargetTriple = llvm::Triple::normalize(A->getValue());
557-
558556
validateArgs(Diags, *TranslatedArgList);
559557

560558
if (Diags.hadAnyError())
561559
return nullptr;
562-
563-
std::unique_ptr<const ToolChain> TC =
564-
makeToolChain(*this, llvm::Triple(DefaultTargetTriple));
565-
if (!TC) {
566-
Diags.diagnose(SourceLoc(), diag::error_unknown_target,
567-
ArgList->getLastArg(options::OPT_target)->getValue());
568-
return nullptr;
569-
}
570560

571-
if (!handleImmediateArgs(*TranslatedArgList, *TC)) {
561+
if (!handleImmediateArgs(*TranslatedArgList, TC)) {
572562
return nullptr;
573563
}
574564

575565
// Construct the list of inputs.
576566
InputFileList Inputs;
577-
buildInputs(*TC, *TranslatedArgList, Inputs);
567+
buildInputs(TC, *TranslatedArgList, Inputs);
578568

579569
if (Diags.hadAnyError())
580570
return nullptr;
581571

582572
// Determine the OutputInfo for the driver.
583573
OutputInfo OI;
584-
buildOutputInfo(*TC, *TranslatedArgList, Inputs, OI);
574+
buildOutputInfo(TC, *TranslatedArgList, Inputs, OI);
585575

586576
if (Diags.hadAnyError())
587577
return nullptr;
@@ -686,7 +676,7 @@ std::unique_ptr<Compilation> Driver::buildCompilation(
686676
llvm_unreachable("Unknown OutputLevel argument!");
687677
}
688678

689-
std::unique_ptr<Compilation> C(new Compilation(Diags, Level,
679+
std::unique_ptr<Compilation> C(new Compilation(Diags, TC, Level,
690680
std::move(ArgList),
691681
std::move(TranslatedArgList),
692682
std::move(Inputs),
@@ -699,7 +689,7 @@ std::unique_ptr<Compilation> Driver::buildCompilation(
699689
std::move(StatsReporter)));
700690
// Construct the graph of Actions.
701691
SmallVector<const Action *, 8> TopLevelActions;
702-
buildActions(TopLevelActions, *TC, OI, OFM.get(),
692+
buildActions(TopLevelActions, TC, OI, OFM.get(),
703693
rebuildEverything ? nullptr : &outOfDateMap, *C);
704694

705695
if (Diags.hadAnyError())
@@ -710,7 +700,7 @@ std::unique_ptr<Compilation> Driver::buildCompilation(
710700
return nullptr;
711701
}
712702

713-
buildJobs(TopLevelActions, OI, OFM.get(), *TC, *C);
703+
buildJobs(TopLevelActions, OI, OFM.get(), TC, *C);
714704

715705
// For getting bulk fixits, or for when users explicitly request to continue
716706
// building despite errors.
@@ -1524,6 +1514,9 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
15241514
AllLinkerInputs.push_back(CA);
15251515
break;
15261516
}
1517+
case OutputInfo::Mode::BatchModeCompile: {
1518+
llvm_unreachable("Batch mode should not be used to build actions");
1519+
}
15271520
case OutputInfo::Mode::Immediate: {
15281521
if (Inputs.empty())
15291522
return;
@@ -2075,7 +2068,7 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
20752068

20762069
if (C.getArgs().hasArg(options::OPT_save_optimization_record,
20772070
options::OPT_save_optimization_record_path))
2078-
chooseSaveOptimizationPath(C, OI, Buf, Output.get());
2071+
chooseOptimizationRecordPath(C, OI, Buf, Output.get());
20792072

20802073
if ((isa<MergeModuleJobAction>(JA) ||
20812074
(isa<CompileJobAction>(JA) &&
@@ -2396,9 +2389,9 @@ void Driver::chooseTBDPath(Compilation &C, const OutputInfo &OI,
23962389
}
23972390
}
23982391

2399-
void Driver::chooseSaveOptimizationPath(Compilation &C, const OutputInfo &OI,
2400-
llvm::SmallString<128> &Buf,
2401-
CommandOutput *Output) const {
2392+
void Driver::chooseOptimizationRecordPath(Compilation &C, const OutputInfo &OI,
2393+
llvm::SmallString<128> &Buf,
2394+
CommandOutput *Output) const {
24022395
if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
24032396
auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
24042397
OI, C.getArgs(), options::OPT_save_optimization_record_path,

lib/Driver/FrontendUtil.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@
1717
#include "swift/Driver/Compilation.h"
1818
#include "swift/Driver/Driver.h"
1919
#include "swift/Driver/Job.h"
20+
#include "swift/Driver/ToolChain.h"
2021
#include "swift/Frontend/Frontend.h"
2122

2223
using namespace swift;
2324
using namespace swift::driver;
2425

2526
std::unique_ptr<CompilerInvocation>
26-
swift::driver::createCompilerInvocation(ArrayRef<const char *> ArgList,
27+
swift::driver::createCompilerInvocation(ArrayRef<const char *> Argv,
2728
DiagnosticEngine &Diags) {
2829
SmallVector<const char *, 16> Args;
2930
Args.push_back("<swiftc>"); // FIXME: Remove dummy argument.
30-
Args.insert(Args.end(), ArgList.begin(), ArgList.end());
31+
Args.insert(Args.end(), Argv.begin(), Argv.end());
3132

3233
// When creating a CompilerInvocation, ensure that the driver creates a single
3334
// frontend command.
@@ -40,7 +41,17 @@ swift::driver::createCompilerInvocation(ArrayRef<const char *> ArgList,
4041
// CompilerInvocation may wish to remap inputs to source buffers.
4142
TheDriver.setCheckInputFilesExist(false);
4243

43-
std::unique_ptr<Compilation> C = TheDriver.buildCompilation(Args);
44+
std::unique_ptr<llvm::opt::InputArgList> ArgList =
45+
TheDriver.parseArgStrings(ArrayRef<const char *>(Args).slice(1));
46+
if (Diags.hadAnyError())
47+
return nullptr;
48+
49+
std::unique_ptr<ToolChain> TC = TheDriver.buildToolChain(*ArgList);
50+
if (Diags.hadAnyError())
51+
return nullptr;
52+
53+
std::unique_ptr<Compilation> C =
54+
TheDriver.buildCompilation(*TC, std::move(ArgList));
4455
if (!C || C->getJobs().empty())
4556
return nullptr; // Don't emit an error; one should already have been emitted
4657

lib/Driver/Job.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,14 @@ void Job::printSummary(raw_ostream &os) const {
147147
}
148148
os << "}";
149149
}
150+
151+
BatchJob::BatchJob(const JobAction &Source,
152+
SmallVectorImpl<const Job *> &&Inputs,
153+
std::unique_ptr<CommandOutput> Output,
154+
const char *Executable, llvm::opt::ArgStringList Arguments,
155+
EnvironmentVector ExtraEnvironment,
156+
std::vector<FilelistInfo> Infos,
157+
ArrayRef<const Job *> Combined)
158+
: Job(Source, std::move(Inputs), std::move(Output), Executable, Arguments,
159+
ExtraEnvironment, Infos),
160+
CombinedJobs(Combined.begin(), Combined.end()) {}

0 commit comments

Comments
 (0)