Added support for thin lto

This commit is contained in:
Travis Lange 2025-01-03 11:04:40 -05:00 committed by Alex Rønne Petersen
parent da1ffae7d2
commit 82e7f23c49
8 changed files with 50 additions and 25 deletions

View file

@ -5399,8 +5399,10 @@ pub fn addCCArgs(
}, },
} }
if (comp.config.lto) { switch (comp.config.lto) {
try argv.append("-flto"); .none => try argv.append("-fno-lto"),
.full => try argv.append("-flto=full"),
.thin => try argv.append("-flto=thin"),
} }
// This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`. // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.
@ -6450,7 +6452,7 @@ pub fn build_crt_file(
.link_libc = false, .link_libc = false,
.lto = switch (output_mode) { .lto = switch (output_mode) {
.Lib => comp.config.lto, .Lib => comp.config.lto,
.Obj, .Exe => false, .Obj, .Exe => .none,
}, },
}); });
const root_mod = try Package.Module.create(arena, .{ const root_mod = try Package.Module.create(arena, .{

View file

@ -48,7 +48,7 @@ use_lib_llvm: bool,
/// and updates the final binary. /// and updates the final binary.
use_lld: bool, use_lld: bool,
c_frontend: CFrontend, c_frontend: CFrontend,
lto: bool, lto: LtoMode,
/// WASI-only. Type of WASI execution model ("command" or "reactor"). /// WASI-only. Type of WASI execution model ("command" or "reactor").
/// Always set to `command` for non-WASI targets. /// Always set to `command` for non-WASI targets.
wasi_exec_model: std.builtin.WasiExecModel, wasi_exec_model: std.builtin.WasiExecModel,
@ -65,6 +65,8 @@ san_cov_trace_pc_guard: bool,
pub const CFrontend = enum { clang, aro }; pub const CFrontend = enum { clang, aro };
pub const LtoMode = enum { none, full, thin };
pub const DebugFormat = union(enum) { pub const DebugFormat = union(enum) {
strip, strip,
dwarf: std.dwarf.Format, dwarf: std.dwarf.Format,
@ -101,7 +103,7 @@ pub const Options = struct {
use_lib_llvm: ?bool = null, use_lib_llvm: ?bool = null,
use_lld: ?bool = null, use_lld: ?bool = null,
use_clang: ?bool = null, use_clang: ?bool = null,
lto: ?bool = null, lto: ?LtoMode = null,
/// WASI-only. Type of WASI execution model ("command" or "reactor"). /// WASI-only. Type of WASI execution model ("command" or "reactor").
wasi_exec_model: ?std.builtin.WasiExecModel = null, wasi_exec_model: ?std.builtin.WasiExecModel = null,
import_memory: ?bool = null, import_memory: ?bool = null,
@ -258,7 +260,7 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b false; break :b false;
} }
if (options.lto == true) { if (options.lto != null and options.lto != .none) {
if (options.use_lld == false) return error.LtoRequiresLld; if (options.use_lld == false) return error.LtoRequiresLld;
break :b true; break :b true;
} }
@ -284,16 +286,16 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b .clang; break :b .clang;
}; };
const lto = b: { const lto: LtoMode = b: {
if (!use_lld) { if (!use_lld) {
// zig ld LTO support is tracked by // zig ld LTO support is tracked by
// https://github.com/ziglang/zig/issues/8680 // https://github.com/ziglang/zig/issues/8680
if (options.lto == true) return error.LtoRequiresLld; if (options.lto != null and options.lto != .none) return error.LtoRequiresLld;
break :b false; break :b .none;
} }
if (options.lto) |x| break :b x; if (options.lto) |x| break :b x;
if (!options.any_c_source_files) break :b false; if (!options.any_c_source_files) break :b .none;
// https://github.com/llvm/llvm-project/pull/116537 // https://github.com/llvm/llvm-project/pull/116537
switch (target.abi) { switch (target.abi) {
@ -303,15 +305,15 @@ pub fn resolve(options: Options) ResolveError!Config {
.ilp32, .ilp32,
.muslabin32, .muslabin32,
.muslx32, .muslx32,
=> break :b false, => break :b .none,
else => {}, else => {},
} }
break :b switch (options.output_mode) { break :b switch (options.output_mode) {
.Lib, .Obj => false, .Lib, .Obj => .none,
.Exe => switch (root_optimize_mode) { .Exe => switch (root_optimize_mode) {
.Debug => false, .Debug => .none,
.ReleaseSafe, .ReleaseFast, .ReleaseSmall => true, .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .full,
}, },
}; };
}; };

View file

@ -1056,7 +1056,7 @@ pub const Object = struct {
time_report: bool, time_report: bool,
sanitize_thread: bool, sanitize_thread: bool,
fuzz: bool, fuzz: bool,
lto: bool, lto: Compilation.Config.LtoMode,
}; };
pub fn emit(o: *Object, options: EmitOptions) !void { pub fn emit(o: *Object, options: EmitOptions) !void {
@ -1338,7 +1338,7 @@ pub const Object = struct {
.time_report = options.time_report, .time_report = options.time_report,
.tsan = options.sanitize_thread, .tsan = options.sanitize_thread,
.sancov = options.fuzz, .sancov = options.fuzz,
.lto = options.lto, .lto = options.lto != .none,
// https://github.com/ziglang/zig/issues/21215 // https://github.com/ziglang/zig/issues/21215
.allow_fast_isel = !comp.root_mod.resolved_target.result.cpu.arch.isMIPS(), .allow_fast_isel = !comp.root_mod.resolved_target.result.cpu.arch.isMIPS(),
.asm_filename = null, .asm_filename = null,

View file

@ -37,7 +37,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
.root_strip = comp.compilerRtStrip(), .root_strip = comp.compilerRtStrip(),
.link_libc = true, .link_libc = true,
// Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
.lto = false, .lto = .none,
}) catch |err| { }) catch |err| {
comp.setMiscFailure( comp.setMiscFailure(
.libunwind, .libunwind,

View file

@ -1859,7 +1859,7 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
if (comp.version) |version| { if (comp.version) |version| {
try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor })); try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
} }
if (comp.config.lto) { if (comp.config.lto != .none) {
switch (optimize_mode) { switch (optimize_mode) {
.Debug => {}, .Debug => {},
.ReleaseSmall => try argv.append("-OPT:lldlto=2"), .ReleaseSmall => try argv.append("-OPT:lldlto=2"),

View file

@ -1640,7 +1640,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
// copy when generating relocatables. Normally, we would expect `lld -r` to work. // copy when generating relocatables. Normally, we would expect `lld -r` to work.
// However, because LLD wants to resolve BPF relocations which it shouldn't, it fails // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
// before even generating the relocatable. // before even generating the relocatable.
if (output_mode == .Obj and (comp.config.lto or target.cpu.arch.isBpf())) { if (output_mode == .Obj and (comp.config.lto != .none or target.cpu.arch.isBpf())) {
// In this case we must do a simple file copy // In this case we must do a simple file copy
// here. TODO: think carefully about how we can avoid this redundant operation when doing // here. TODO: think carefully about how we can avoid this redundant operation when doing
// build-obj. See also the corresponding TODO in linkAsArchive. // build-obj. See also the corresponding TODO in linkAsArchive.
@ -1683,7 +1683,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot})); try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
} }
if (comp.config.lto) { if (comp.config.lto != .none) {
switch (comp.root_mod.optimize_mode) { switch (comp.root_mod.optimize_mode) {
.Debug => {}, .Debug => {},
.ReleaseSmall => try argv.append("--lto-O2"), .ReleaseSmall => try argv.append("--lto-O2"),

View file

@ -3537,7 +3537,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command }); try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
try argv.append("--error-limit=0"); try argv.append("--error-limit=0");
if (comp.config.lto) { if (comp.config.lto != .none) {
switch (comp.root_mod.optimize_mode) { switch (comp.root_mod.optimize_mode) {
.Debug => {}, .Debug => {},
.ReleaseSmall => try argv.append("-O2"), .ReleaseSmall => try argv.append("-O2"),

View file

@ -1386,9 +1386,18 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "-fno-PIE")) { } else if (mem.eql(u8, arg, "-fno-PIE")) {
create_module.opts.pie = false; create_module.opts.pie = false;
} else if (mem.eql(u8, arg, "-flto")) { } else if (mem.eql(u8, arg, "-flto")) {
create_module.opts.lto = true; create_module.opts.lto = .full;
} else if (mem.startsWith(u8, arg, "-flto=")) {
const mode = arg["-flto=".len..];
if (mem.eql(u8, mode, "full")) {
create_module.opts.lto = .full;
} else if (mem.eql(u8, mode, "thin")) {
create_module.opts.lto = .thin;
} else {
fatal("Invalid -flto mode: '{s}'. Must be 'full'or 'thin'.", .{mode});
}
} else if (mem.eql(u8, arg, "-fno-lto")) { } else if (mem.eql(u8, arg, "-fno-lto")) {
create_module.opts.lto = false; create_module.opts.lto = .none;
} else if (mem.eql(u8, arg, "-funwind-tables")) { } else if (mem.eql(u8, arg, "-funwind-tables")) {
mod_opts.unwind_tables = .sync; mod_opts.unwind_tables = .sync;
} else if (mem.eql(u8, arg, "-fasync-unwind-tables")) { } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
@ -1958,8 +1967,20 @@ fn buildOutputType(
.no_pic => mod_opts.pic = false, .no_pic => mod_opts.pic = false,
.pie => create_module.opts.pie = true, .pie => create_module.opts.pie = true,
.no_pie => create_module.opts.pie = false, .no_pie => create_module.opts.pie = false,
.lto => create_module.opts.lto = true, .lto => {
.no_lto => create_module.opts.lto = false, if (mem.eql(u8, it.only_arg, "flto") or
mem.eql(u8, it.only_arg, "auto") or
mem.eql(u8, it.only_arg, "full") or
mem.eql(u8, it.only_arg, "jobserver"))
{
create_module.opts.lto = .full;
} else if (mem.eql(u8, it.only_arg, "thin")) {
create_module.opts.lto = .thin;
} else {
fatal("Invalid -flto mode: '{s}'. Must be 'auto', 'full', 'thin', or 'jobserver'.", .{it.only_arg});
}
},
.no_lto => create_module.opts.lto = .none,
.red_zone => mod_opts.red_zone = true, .red_zone => mod_opts.red_zone = true,
.no_red_zone => mod_opts.red_zone = false, .no_red_zone => mod_opts.red_zone = false,
.omit_frame_pointer => mod_opts.omit_frame_pointer = true, .omit_frame_pointer => mod_opts.omit_frame_pointer = true,