Skip to content

add LTO support #7856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ pub const InitOptions = struct {
want_valgrind: ?bool = null,
want_tsan: ?bool = null,
want_compiler_rt: ?bool = null,
want_lto: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
use_clang: ?bool = null,
Expand Down Expand Up @@ -602,6 +603,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
if (ofmt == .c)
break :blk false;

if (options.want_lto) |lto| {
if (lto) {
break :blk true;
}
}

// Our linker can't handle objects or most advanced options yet.
if (options.link_objects.len != 0 or
options.c_source_files.len != 0 or
Expand Down Expand Up @@ -647,6 +654,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
break :outer opts;
} else .{};

const lto = blk: {
if (options.want_lto) |explicit| {
if (!use_lld)
return error.LtoUnavailableWithoutLld;
break :blk explicit;
} else if (!use_lld) {
break :blk false;
} else if (options.c_source_files.len == 0) {
break :blk false;
} else if (darwin_options.system_linker_hack) {
break :blk false;
} else switch (options.output_mode) {
.Lib, .Obj => break :blk false,
.Exe => switch (options.optimize_mode) {
.Debug => break :blk false,
.ReleaseSafe, .ReleaseFast, .ReleaseSmall => break :blk true,
},
}
};

const tsan = options.want_tsan orelse false;

const link_libc = options.link_libc or target_util.osRequiresLibC(options.target) or tsan;
Expand Down Expand Up @@ -821,6 +848,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
cache.hash.add(ofmt);
cache.hash.add(pic);
cache.hash.add(pie);
cache.hash.add(lto);
cache.hash.add(tsan);
cache.hash.add(stack_check);
cache.hash.add(red_zone);
Expand Down Expand Up @@ -1022,6 +1050,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.libc_installation = libc_dirs.libc_installation,
.pic = pic,
.pie = pie,
.lto = lto,
.valgrind = valgrind,
.tsan = tsan,
.stack_check = stack_check,
Expand Down Expand Up @@ -2233,6 +2262,9 @@ pub fn addCCArgs(
"-nostdinc",
"-fno-spell-checking",
});
if (comp.bin_file.options.lto) {
try argv.append("-flto");
}

// According to Rich Felker libc headers are supposed to go before C language headers.
// However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
Expand Down Expand Up @@ -3255,6 +3287,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
.err_color = @enumToInt(comp.color),
.pic = comp.bin_file.options.pic,
.pie = comp.bin_file.options.pie,
.lto = comp.bin_file.options.lto,
.link_libc = comp.bin_file.options.link_libc,
.link_libcpp = comp.bin_file.options.link_libcpp,
.strip = comp.bin_file.options.strip,
Expand Down Expand Up @@ -3415,6 +3448,10 @@ pub fn build_crt_file(
.want_tsan = false,
.want_pic = comp.bin_file.options.pic,
.want_pie = comp.bin_file.options.pie,
.want_lto = switch (output_mode) {
.Lib => comp.bin_file.options.lto,
.Obj, .Exe => false,
},
.emit_h = null,
.strip = comp.compilerRtStrip(),
.is_native_os = comp.bin_file.options.is_native_os,
Expand Down
27 changes: 24 additions & 3 deletions src/clang_options_data.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2732,7 +2732,14 @@ flagpd1("fkeep-static-consts"),
flagpd1("flat_namespace"),
flagpd1("flax-vector-conversions"),
flagpd1("flimit-debug-info"),
flagpd1("flto"),
.{
.name = "flto",
.syntax = .flag,
.zig_equivalent = .lto,
.pd1 = true,
.pd2 = false,
.psl = false,
},
flagpd1("flto-unit"),
flagpd1("flto-visibility-public-std"),
sepd1("fmacro-backtrace-limit"),
Expand Down Expand Up @@ -2942,7 +2949,14 @@ flagpd1("fno-jump-tables"),
flagpd1("fno-keep-static-consts"),
flagpd1("fno-lax-vector-conversions"),
flagpd1("fno-limit-debug-info"),
flagpd1("fno-lto"),
.{
.name = "fno-lto",
.syntax = .flag,
.zig_equivalent = .no_lto,
.pd1 = true,
.pd2 = false,
.psl = false,
},
flagpd1("fno-lto-unit"),
flagpd1("fno-math-builtin"),
flagpd1("fno-math-errno"),
Expand Down Expand Up @@ -5638,7 +5652,14 @@ jspd1("Ttext"),
.pd2 = true,
.psl = false,
},
joinpd1("flto="),
.{
.name = "flto=",
.syntax = .joined,
.zig_equivalent = .lto,
.pd1 = true,
.pd2 = false,
.psl = false,
},
joinpd1("gcoff"),
joinpd1("mabi="),
joinpd1("mabs="),
Expand Down
8 changes: 7 additions & 1 deletion src/codegen/llvm/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,13 @@ pub const TargetMachine = opaque {
extern fn LLVMDisposeTargetMachine(T: *const TargetMachine) void;

pub const emitToFile = LLVMTargetMachineEmitToFile;
extern fn LLVMTargetMachineEmitToFile(*const TargetMachine, M: *const Module, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool;
extern fn LLVMTargetMachineEmitToFile(
*const TargetMachine,
M: *const Module,
Filename: [*:0]const u8,
codegen: CodeGenFileType,
ErrorMessage: *[*:0]const u8,
) LLVMBool;
};

pub const CodeMode = extern enum {
Expand Down
1 change: 1 addition & 0 deletions src/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub const Options = struct {
is_native_abi: bool,
pic: bool,
pie: bool,
lto: bool,
valgrind: bool,
tsan: bool,
stack_check: bool,
Expand Down
7 changes: 7 additions & 0 deletions src/link/Coff.zig
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,13 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
if (!self.base.options.strip) {
try argv.append("-DEBUG");
}
if (self.base.options.lto) {
switch (self.base.options.optimize_mode) {
.Debug => {},
.ReleaseSmall => try argv.append("-OPT:lldlto=2"),
.ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
}
}
if (self.base.options.output_mode == .Exe) {
const stack_size = self.base.options.stack_size_override orelse 16777216;
try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size}));
Expand Down
Loading