Skip to content

Commit f196c16

Browse files
authored
Merge pull request #32430 from kateinoigakukun/katei/llvm-lto-driver
[LTO] Support LLVM LTO for driver
2 parents 8e6346e + d6cddaa commit f196c16

File tree

14 files changed

+299
-21
lines changed

14 files changed

+299
-21
lines changed

include/swift/Driver/Action.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,20 @@ class GeneratePCHJobAction : public JobAction {
329329
class DynamicLinkJobAction : public JobAction {
330330
virtual void anchor() override;
331331
LinkKind Kind;
332+
bool ShouldPerformLTO;
332333

333334
public:
334-
DynamicLinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
335+
DynamicLinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K,
336+
bool ShouldPerformLTO)
335337
: JobAction(Action::Kind::DynamicLinkJob, Inputs, file_types::TY_Image),
336-
Kind(K) {
338+
Kind(K), ShouldPerformLTO(ShouldPerformLTO) {
337339
assert(Kind != LinkKind::None && Kind != LinkKind::StaticLibrary);
338340
}
339341

340342
LinkKind getKind() const { return Kind; }
341343

344+
bool shouldPerformLTO() const { return ShouldPerformLTO; }
345+
342346
static bool classof(const Action *A) {
343347
return A->getKind() == Action::Kind::DynamicLinkJob;
344348
}

include/swift/Driver/Driver.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ class OutputInfo {
101101
/// The output type which should be used for compile actions.
102102
file_types::ID CompilerOutputType = file_types::ID::TY_INVALID;
103103

104+
enum class LTOKind {
105+
None,
106+
LLVMThin,
107+
LLVMFull,
108+
};
109+
110+
LTOKind LTOVariant = LTOKind::None;
111+
104112
/// Describes if and how the output of compile actions should be
105113
/// linked together.
106114
LinkKind LinkAction = LinkKind::None;

lib/Driver/DarwinToolChains.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@ static bool findXcodeClangPath(llvm::SmallVectorImpl<char> &path) {
199199
return !path.empty();
200200
}
201201

202+
static bool findXcodeClangLibPath(const Twine &libName,
203+
llvm::SmallVectorImpl<char> &path) {
204+
assert(path.empty());
205+
206+
if (!findXcodeClangPath(path)) {
207+
return false;
208+
}
209+
llvm::sys::path::remove_filename(path); // 'clang'
210+
llvm::sys::path::remove_filename(path); // 'bin'
211+
llvm::sys::path::append(path, "lib", libName);
212+
return true;
213+
}
214+
202215
static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments,
203216
unsigned major, unsigned minor, unsigned micro) {
204217
llvm::SmallString<8> buf;
@@ -236,12 +249,15 @@ toolchains::Darwin::addLinkerInputArgs(InvocationInfo &II,
236249
Arguments.push_back("-filelist");
237250
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
238251
II.FilelistInfos.push_back(
239-
{Arguments.back(), file_types::TY_Object,
252+
{Arguments.back(), context.OI.CompilerOutputType,
240253
FilelistInfo::WhichFiles::InputJobsAndSourceInputActions});
241254
} else {
242255
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
243256
file_types::TY_Object);
257+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
258+
file_types::TY_LLVM_BC);
244259
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
260+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
245261
}
246262

247263

@@ -271,11 +287,7 @@ static void findARCLiteLibPath(const toolchains::Darwin &TC,
271287
// If we don't have a 'lib/arc/' directory, find the "arclite" library
272288
// relative to the Clang in the active Xcode.
273289
ARCLiteLib.clear();
274-
if (findXcodeClangPath(ARCLiteLib)) {
275-
llvm::sys::path::remove_filename(ARCLiteLib); // 'clang'
276-
llvm::sys::path::remove_filename(ARCLiteLib); // 'bin'
277-
llvm::sys::path::append(ARCLiteLib, "lib", "arc");
278-
}
290+
findXcodeClangLibPath("arc", ARCLiteLib);
279291
}
280292
}
281293

@@ -304,6 +316,15 @@ toolchains::Darwin::addArgsToLinkARCLite(ArgStringList &Arguments,
304316
}
305317
}
306318

319+
void toolchains::Darwin::addLTOLibArgs(ArgStringList &Arguments,
320+
const JobContext &context) const {
321+
llvm::SmallString<128> LTOLibPath;
322+
if (findXcodeClangLibPath("libLTO.dylib", LTOLibPath)) {
323+
Arguments.push_back("-lto_library");
324+
Arguments.push_back(context.Args.MakeArgString(LTOLibPath));
325+
}
326+
}
327+
307328
void
308329
toolchains::Darwin::addSanitizerArgs(ArgStringList &Arguments,
309330
const DynamicLinkJobAction &job,
@@ -705,6 +726,10 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job,
705726

706727
addArgsToLinkARCLite(Arguments, context);
707728

729+
if (job.shouldPerformLTO()) {
730+
addLTOLibArgs(Arguments, context);
731+
}
732+
708733
for (const Arg *arg :
709734
context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) {
710735
Arguments.push_back("-F");
@@ -777,14 +802,17 @@ toolchains::Darwin::constructInvocation(const StaticLinkJobAction &job,
777802
if (context.shouldUseInputFileList()) {
778803
Arguments.push_back("-filelist");
779804
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
780-
II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object,
805+
II.FilelistInfos.push_back({Arguments.back(), context.OI.CompilerOutputType,
781806
FilelistInfo::WhichFiles::InputJobs});
782807
} else {
783808
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
784809
file_types::TY_Object);
810+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
811+
file_types::TY_LLVM_BC);
785812
}
786813

787814
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
815+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
788816

789817
Arguments.push_back("-o");
790818

lib/Driver/Driver.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,12 +1444,29 @@ static bool isSDKTooOld(StringRef sdkPath, const llvm::Triple &target) {
14441444
void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
14451445
const bool BatchMode, const InputFileList &Inputs,
14461446
OutputInfo &OI) const {
1447+
1448+
if (const Arg *A = Args.getLastArg(options::OPT_lto)) {
1449+
auto LTOVariant =
1450+
llvm::StringSwitch<Optional<OutputInfo::LTOKind>>(A->getValue())
1451+
.Case("llvm-thin", OutputInfo::LTOKind::LLVMThin)
1452+
.Case("llvm-full", OutputInfo::LTOKind::LLVMFull)
1453+
.Default(llvm::None);
1454+
if (LTOVariant)
1455+
OI.LTOVariant = LTOVariant.getValue();
1456+
else
1457+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
1458+
A->getAsString(Args), A->getValue());
1459+
}
1460+
1461+
auto CompilerOutputType = OI.LTOVariant != OutputInfo::LTOKind::None
1462+
? file_types::TY_LLVM_BC
1463+
: file_types::TY_Object;
14471464
// By default, the driver does not link its output; this will be updated
14481465
// appropriately below if linking is required.
14491466

14501467
OI.CompilerOutputType = driverKind == DriverKind::Interactive
14511468
? file_types::TY_Nothing
1452-
: file_types::TY_Object;
1469+
: CompilerOutputType;
14531470

14541471
if (const Arg *A = Args.getLastArg(options::OPT_num_threads)) {
14551472
if (BatchMode) {
@@ -1479,14 +1496,14 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
14791496
diag::error_static_emit_executable_disallowed);
14801497

14811498
OI.LinkAction = LinkKind::Executable;
1482-
OI.CompilerOutputType = file_types::TY_Object;
1499+
OI.CompilerOutputType = CompilerOutputType;
14831500
break;
14841501

14851502
case options::OPT_emit_library:
14861503
OI.LinkAction = Args.hasArg(options::OPT_static) ?
14871504
LinkKind::StaticLibrary :
14881505
LinkKind::DynamicLibrary;
1489-
OI.CompilerOutputType = file_types::TY_Object;
1506+
OI.CompilerOutputType = CompilerOutputType;
14901507
break;
14911508

14921509
case options::OPT_static:
@@ -2131,15 +2148,16 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
21312148
MergeModuleAction = C.createAction<MergeModuleJobAction>(AllModuleInputs);
21322149
}
21332150

2151+
bool shouldPerformLTO = OI.LTOVariant != OutputInfo::LTOKind::None;
21342152
if (OI.shouldLink() && !AllLinkerInputs.empty()) {
21352153
JobAction *LinkAction = nullptr;
21362154

21372155
if (OI.LinkAction == LinkKind::StaticLibrary) {
2138-
LinkAction = C.createAction<StaticLinkJobAction>(AllLinkerInputs,
2139-
OI.LinkAction);
2156+
LinkAction =
2157+
C.createAction<StaticLinkJobAction>(AllLinkerInputs, OI.LinkAction);
21402158
} else {
2141-
LinkAction = C.createAction<DynamicLinkJobAction>(AllLinkerInputs,
2142-
OI.LinkAction);
2159+
LinkAction = C.createAction<DynamicLinkJobAction>(
2160+
AllLinkerInputs, OI.LinkAction, shouldPerformLTO);
21432161
}
21442162

21452163
// On ELF platforms there's no built in autolinking mechanism, so we
@@ -2161,9 +2179,10 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
21612179
AutolinkExtractInputs.push_back(A);
21622180
}
21632181
const bool AutolinkExtractRequired =
2164-
(Triple.getObjectFormat() == llvm::Triple::ELF && !Triple.isPS4()) ||
2165-
Triple.getObjectFormat() == llvm::Triple::Wasm ||
2166-
Triple.isOSCygMing();
2182+
((Triple.getObjectFormat() == llvm::Triple::ELF && !Triple.isPS4()) ||
2183+
Triple.getObjectFormat() == llvm::Triple::Wasm ||
2184+
Triple.isOSCygMing()) &&
2185+
!shouldPerformLTO;
21672186
if (!AutolinkExtractInputs.empty() && AutolinkExtractRequired) {
21682187
auto *AutolinkExtractAction =
21692188
C.createAction<AutolinkExtractJobAction>(AutolinkExtractInputs);

lib/Driver/ToolChains.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@ static bool addOutputsOfType(ArgStringList &Arguments,
129129
return Added;
130130
}
131131

132+
static void addLTOArgs(const OutputInfo &OI, ArgStringList &arguments) {
133+
switch (OI.LTOVariant) {
134+
case OutputInfo::LTOKind::None:
135+
break;
136+
case OutputInfo::LTOKind::LLVMThin:
137+
arguments.push_back("-lto=llvm-thin");
138+
break;
139+
case OutputInfo::LTOKind::LLVMFull:
140+
arguments.push_back("-lto=llvm-full");
141+
break;
142+
}
143+
}
144+
132145
void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
133146
const CommandOutput &output,
134147
const ArgList &inputArgs,
@@ -297,6 +310,8 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
297310
arguments.push_back(inputArgs.MakeArgString(workingDirectory));
298311
}
299312

313+
addLTOArgs(OI, arguments);
314+
300315
// -g implies -enable-anonymous-context-mangled-names, because the extra
301316
// metadata aids debugging.
302317
if (inputArgs.hasArg(options::OPT_g)) {

lib/Driver/ToolChains.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
4848
void addDeploymentTargetArgs(llvm::opt::ArgStringList &Arguments,
4949
const JobContext &context) const;
5050

51+
void addLTOLibArgs(llvm::opt::ArgStringList &Arguments,
52+
const JobContext &context) const;
53+
5154
void addCommonFrontendArgs(
5255
const OutputInfo &OI, const CommandOutput &output,
5356
const llvm::opt::ArgList &inputArgs,

lib/Driver/UnixToolChains.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ ToolChain::InvocationInfo toolchains::GenericUnix::constructInvocation(
7272

7373
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
7474
file_types::TY_Object);
75+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
76+
file_types::TY_LLVM_BC);
7577
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
78+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
7679

7780
Arguments.push_back("-o");
7881
Arguments.push_back(
@@ -165,9 +168,18 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
165168

166169
// Select the linker to use.
167170
std::string Linker;
171+
if (context.OI.LTOVariant != OutputInfo::LTOKind::None) {
172+
// Force to use lld for LTO on Unix-like platform (not including Darwin)
173+
// because we don't support gold LTO or something else except for lld LTO
174+
// at this time.
175+
Linker = "lld";
176+
}
177+
168178
if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) {
169179
Linker = A->getValue();
170-
} else {
180+
}
181+
182+
if (Linker.empty()) {
171183
Linker = getDefaultLinker();
172184
}
173185
if (!Linker.empty()) {
@@ -196,6 +208,17 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
196208
Arguments.push_back("-pie");
197209
}
198210

211+
switch (context.OI.LTOVariant) {
212+
case OutputInfo::LTOKind::LLVMThin:
213+
Arguments.push_back("-flto=thin");
214+
break;
215+
case OutputInfo::LTOKind::LLVMFull:
216+
Arguments.push_back("-flto=full");
217+
break;
218+
case OutputInfo::LTOKind::None:
219+
break;
220+
}
221+
199222
bool staticExecutable = false;
200223
bool staticStdlib = false;
201224

@@ -231,7 +254,10 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
231254

232255
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
233256
file_types::TY_Object);
257+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
258+
file_types::TY_LLVM_BC);
234259
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
260+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
235261

236262
for (const Arg *arg :
237263
context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) {
@@ -353,15 +379,19 @@ toolchains::GenericUnix::constructInvocation(const StaticLinkJobAction &job,
353379
ArgStringList Arguments;
354380

355381
// Configure the toolchain.
356-
const char *AR = "ar";
382+
const char *AR =
383+
context.OI.LTOVariant != OutputInfo::LTOKind::None ? "llvm-ar" : "ar";
357384
Arguments.push_back("crs");
358385

359386
Arguments.push_back(
360387
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));
361388

362389
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
363390
file_types::TY_Object);
391+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
392+
file_types::TY_LLVM_BC);
364393
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
394+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
365395

366396
InvocationInfo II{AR, Arguments};
367397

lib/Driver/WindowsToolChains.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job,
7676
if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) {
7777
Linker = A->getValue();
7878
}
79+
80+
switch (context.OI.LTOVariant) {
81+
case OutputInfo::LTOKind::LLVMThin:
82+
Arguments.push_back("-flto=thin");
83+
break;
84+
case OutputInfo::LTOKind::LLVMFull:
85+
Arguments.push_back("-flto=full");
86+
break;
87+
case OutputInfo::LTOKind::None:
88+
break;
89+
}
90+
91+
if (Linker.empty() && context.OI.LTOVariant != OutputInfo::LTOKind::None) {
92+
// Force to use lld for LTO on Windows because we don't support link LTO or
93+
// something else except for lld LTO at this time.
94+
Linker = "lld";
95+
}
96+
7997
if (!Linker.empty())
8098
Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker));
8199

@@ -117,7 +135,10 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job,
117135

118136
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
119137
file_types::TY_Object);
138+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
139+
file_types::TY_LLVM_BC);
120140
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
141+
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC);
121142

122143
for (const Arg *arg :
123144
context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) {

0 commit comments

Comments
 (0)