Skip to content

Commit c2b370c

Browse files
[LTO] Support LLVM level link time optimization on Darwin
This commit adds -llvm-lto flag for driver to enable LTO at LLVM level. When -llvm-lto given, compiler emits LLVM bitcode file instead of object file and link them using libLTO.dylib plugin.
1 parent ea142db commit c2b370c

File tree

7 files changed

+56
-10
lines changed

7 files changed

+56
-10
lines changed

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,10 @@ def disable_bridging_pch : Flag<["-"], "disable-bridging-pch">,
500500
Flags<[HelpHidden]>,
501501
HelpText<"Disable automatic generation of bridging PCH files">;
502502

503+
def llvm_lto : Flag<["-"], "llvm-lto">,
504+
Flags<[FrontendOption, NoInteractiveOption]>,
505+
HelpText<"Enable LLVM LTO">;
506+
503507
// Experimental feature options
504508

505509
// Note: this flag will be removed when JVP/differential generation in the

lib/Driver/DarwinToolChains.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,16 +234,19 @@ void
234234
toolchains::Darwin::addLinkerInputArgs(InvocationInfo &II,
235235
const JobContext &context) const {
236236
ArgStringList &Arguments = II.Arguments;
237+
auto InputType = context.Args.hasArg(options::OPT_llvm_lto) ?
238+
file_types::TY_LLVM_BC :
239+
file_types::TY_Object;
237240
if (context.shouldUseInputFileList()) {
238241
Arguments.push_back("-filelist");
239242
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
240243
II.FilelistInfos.push_back(
241-
{Arguments.back(), file_types::TY_Object,
244+
{Arguments.back(), InputType,
242245
FilelistInfo::WhichFiles::InputJobsAndSourceInputActions});
243246
} else {
244247
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
245-
file_types::TY_Object);
246-
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
248+
InputType);
249+
addInputsOfType(Arguments, context.InputActions, InputType);
247250
}
248251

249252

@@ -306,6 +309,20 @@ toolchains::Darwin::addArgsToLinkARCLite(ArgStringList &Arguments,
306309
}
307310
}
308311

312+
void
313+
toolchains::Darwin::addLTOLibArgs(ArgStringList &Arguments,
314+
const JobContext &context) const {
315+
llvm::SmallString<128> LTOLibPath;
316+
if (findXcodeClangPath(LTOLibPath)) {
317+
llvm::sys::path::remove_filename(LTOLibPath); // 'clang'
318+
llvm::sys::path::remove_filename(LTOLibPath); // 'bin'
319+
llvm::sys::path::append(LTOLibPath, "lib", "libLTO.dylib");
320+
321+
Arguments.push_back("-lto_library");
322+
Arguments.push_back(context.Args.MakeArgString(LTOLibPath));
323+
}
324+
}
325+
309326
void
310327
toolchains::Darwin::addSanitizerArgs(ArgStringList &Arguments,
311328
const DynamicLinkJobAction &job,
@@ -723,6 +740,10 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job,
723740

724741
addArgsToLinkARCLite(Arguments, context);
725742

743+
if (context.Args.hasArg(options::OPT_llvm_lto)) {
744+
addLTOLibArgs(Arguments, context);
745+
}
746+
726747
for (const Arg *arg :
727748
context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) {
728749
Arguments.push_back("-F");
@@ -786,18 +807,20 @@ toolchains::Darwin::constructInvocation(const StaticLinkJobAction &job,
786807
ArgStringList &Arguments = II.Arguments;
787808

788809
Arguments.push_back("-static");
789-
810+
auto InputType = context.Args.hasArg(options::OPT_llvm_lto) ?
811+
file_types::TY_LLVM_BC :
812+
file_types::TY_Object;
790813
if (context.shouldUseInputFileList()) {
791814
Arguments.push_back("-filelist");
792815
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
793-
II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object,
816+
II.FilelistInfos.push_back({Arguments.back(), InputType,
794817
FilelistInfo::WhichFiles::InputJobs});
795818
} else {
796819
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
797-
file_types::TY_Object);
820+
InputType);
798821
}
799822

800-
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
823+
addInputsOfType(Arguments, context.InputActions, InputType);
801824

802825
Arguments.push_back("-o");
803826

lib/Driver/Driver.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,12 +1434,15 @@ static bool isSDKTooOld(StringRef sdkPath, const llvm::Triple &target) {
14341434
void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
14351435
const bool BatchMode, const InputFileList &Inputs,
14361436
OutputInfo &OI) const {
1437+
auto LinkerInputType = Args.hasArg(options::OPT_llvm_lto)
1438+
? file_types::TY_LLVM_BC
1439+
: file_types::TY_Object;
14371440
// By default, the driver does not link its output; this will be updated
14381441
// appropriately below if linking is required.
14391442

14401443
OI.CompilerOutputType = driverKind == DriverKind::Interactive
14411444
? file_types::TY_Nothing
1442-
: file_types::TY_Object;
1445+
: LinkerInputType;
14431446

14441447
if (const Arg *A = Args.getLastArg(options::OPT_num_threads)) {
14451448
if (BatchMode) {
@@ -1469,14 +1472,14 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
14691472
diag::error_static_emit_executable_disallowed);
14701473

14711474
OI.LinkAction = LinkKind::Executable;
1472-
OI.CompilerOutputType = file_types::TY_Object;
1475+
OI.CompilerOutputType = LinkerInputType;
14731476
break;
14741477

14751478
case options::OPT_emit_library:
14761479
OI.LinkAction = Args.hasArg(options::OPT_static) ?
14771480
LinkKind::StaticLibrary :
14781481
LinkKind::DynamicLibrary;
1479-
OI.CompilerOutputType = file_types::TY_Object;
1482+
OI.CompilerOutputType = LinkerInputType;
14801483
break;
14811484

14821485
case options::OPT_static:

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,

test/Driver/Inputs/lto/lib.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public func libraryFunction() {
2+
print("Hello")
3+
}

test/Driver/Inputs/lto/main.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import A
2+
3+
libraryFunction()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// REQUIRES: OS=macosx
2+
// RUN: %target-swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -llvm-lto | %FileCheck %s
3+
// CHECK: bin/swift -frontend -emit-bc
4+
// CHECK-NEXT: bin/ld {{.+}} -lto_library {{.+}}/lib/libLTO.dylib
5+
6+
// RUN: %target-swiftc_driver %S/Inputs/lto/lib.swift -llvm-lto -emit-library -emit-module -module-name A
7+
// RUN: %target-swiftc_driver %S/Inputs/lto/main.swift -L. -I. -lA -llvm-lto

0 commit comments

Comments
 (0)