authorgravatar for travislange12@gmail.comTravis Lange <travislange12@gmail.com> 2025-01-03 11:04:40-05:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-01-05 18:08:11+01:00
log82e7f23c49be10ce74cb1a951aa7cb77799c2798
treeda65434206224508642a9b79adfbc21a29a2176c
parentda1ffae7d23b04c4efc5e99ba153d8c45eb980f3

Added support for thin lto


8 files changed, 50 insertions(+), 25 deletions(-)

src/Compilation.zig+5-3
...@@ -5399,8 +5399,10 @@ pub fn addCCArgs(...@@ -5399,8 +5399,10 @@ pub fn addCCArgs(
5399 },5399 },
5400 }5400 }
54015401
5402 if (comp.config.lto) {5402 switch (comp.config.lto) {
5403 try argv.append("-flto");5403 .none => try argv.append("-fno-lto"),
5404 .full => try argv.append("-flto=full"),
5405 .thin => try argv.append("-flto=thin"),
5404 }5406 }
54055407
5406 // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.5408 // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.
...@@ -6450,7 +6452,7 @@ pub fn build_crt_file(...@@ -6450,7 +6452,7 @@ pub fn build_crt_file(
6450 .link_libc = false,6452 .link_libc = false,
6451 .lto = switch (output_mode) {6453 .lto = switch (output_mode) {
6452 .Lib => comp.config.lto,6454 .Lib => comp.config.lto,
6453 .Obj, .Exe => false,6455 .Obj, .Exe => .none,
6454 },6456 },
6455 });6457 });
6456 const root_mod = try Package.Module.create(arena, .{6458 const root_mod = try Package.Module.create(arena, .{
src/Compilation/Config.zig+13-11
...@@ -48,7 +48,7 @@ use_lib_llvm: bool,...@@ -48,7 +48,7 @@ use_lib_llvm: bool,
48/// and updates the final binary.48/// and updates the final binary.
49use_lld: bool,49use_lld: bool,
50c_frontend: CFrontend,50c_frontend: CFrontend,
51lto: bool,51lto: LtoMode,
52/// WASI-only. Type of WASI execution model ("command" or "reactor").52/// WASI-only. Type of WASI execution model ("command" or "reactor").
53/// Always set to `command` for non-WASI targets.53/// Always set to `command` for non-WASI targets.
54wasi_exec_model: std.builtin.WasiExecModel,54wasi_exec_model: std.builtin.WasiExecModel,
...@@ -65,6 +65,8 @@ san_cov_trace_pc_guard: bool,...@@ -65,6 +65,8 @@ san_cov_trace_pc_guard: bool,
6565
66pub const CFrontend = enum { clang, aro };66pub const CFrontend = enum { clang, aro };
6767
68pub const LtoMode = enum { none, full, thin };
69
68pub const DebugFormat = union(enum) {70pub const DebugFormat = union(enum) {
69 strip,71 strip,
70 dwarf: std.dwarf.Format,72 dwarf: std.dwarf.Format,
...@@ -101,7 +103,7 @@ pub const Options = struct {...@@ -101,7 +103,7 @@ pub const Options = struct {
101 use_lib_llvm: ?bool = null,103 use_lib_llvm: ?bool = null,
102 use_lld: ?bool = null,104 use_lld: ?bool = null,
103 use_clang: ?bool = null,105 use_clang: ?bool = null,
104 lto: ?bool = null,106 lto: ?LtoMode = null,
105 /// WASI-only. Type of WASI execution model ("command" or "reactor").107 /// WASI-only. Type of WASI execution model ("command" or "reactor").
106 wasi_exec_model: ?std.builtin.WasiExecModel = null,108 wasi_exec_model: ?std.builtin.WasiExecModel = null,
107 import_memory: ?bool = null,109 import_memory: ?bool = null,
...@@ -258,7 +260,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -258,7 +260,7 @@ pub fn resolve(options: Options) ResolveError!Config {
258 break :b false;260 break :b false;
259 }261 }
260262
261 if (options.lto == true) {263 if (options.lto != null and options.lto != .none) {
262 if (options.use_lld == false) return error.LtoRequiresLld;264 if (options.use_lld == false) return error.LtoRequiresLld;
263 break :b true;265 break :b true;
264 }266 }
...@@ -284,16 +286,16 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -284,16 +286,16 @@ pub fn resolve(options: Options) ResolveError!Config {
284 break :b .clang;286 break :b .clang;
285 };287 };
286288
287 const lto = b: {289 const lto: LtoMode = b: {
288 if (!use_lld) {290 if (!use_lld) {
289 // zig ld LTO support is tracked by291 // zig ld LTO support is tracked by
290 // https://github.com/ziglang/zig/issues/8680292 // https://github.com/ziglang/zig/issues/8680
291 if (options.lto == true) return error.LtoRequiresLld;293 if (options.lto != null and options.lto != .none) return error.LtoRequiresLld;
292 break :b false;294 break :b .none;
293 }295 }
294296
295 if (options.lto) |x| break :b x;297 if (options.lto) |x| break :b x;
296 if (!options.any_c_source_files) break :b false;298 if (!options.any_c_source_files) break :b .none;
297299
298 // https://github.com/llvm/llvm-project/pull/116537300 // https://github.com/llvm/llvm-project/pull/116537
299 switch (target.abi) {301 switch (target.abi) {
...@@ -303,15 +305,15 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -303,15 +305,15 @@ pub fn resolve(options: Options) ResolveError!Config {
303 .ilp32,305 .ilp32,
304 .muslabin32,306 .muslabin32,
305 .muslx32,307 .muslx32,
306 => break :b false,308 => break :b .none,
307 else => {},309 else => {},
308 }310 }
309311
310 break :b switch (options.output_mode) {312 break :b switch (options.output_mode) {
311 .Lib, .Obj => false,313 .Lib, .Obj => .none,
312 .Exe => switch (root_optimize_mode) {314 .Exe => switch (root_optimize_mode) {
313 .Debug => false,315 .Debug => .none,
314 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => true,316 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .full,
315 },317 },
316 };318 };
317 };319 };
src/codegen/llvm.zig+2-2
...@@ -1056,7 +1056,7 @@ pub const Object = struct {...@@ -1056,7 +1056,7 @@ pub const Object = struct {
1056 time_report: bool,1056 time_report: bool,
1057 sanitize_thread: bool,1057 sanitize_thread: bool,
1058 fuzz: bool,1058 fuzz: bool,
1059 lto: bool,1059 lto: Compilation.Config.LtoMode,
1060 };1060 };
10611061
1062 pub fn emit(o: *Object, options: EmitOptions) !void {1062 pub fn emit(o: *Object, options: EmitOptions) !void {
...@@ -1338,7 +1338,7 @@ pub const Object = struct {...@@ -1338,7 +1338,7 @@ pub const Object = struct {
1338 .time_report = options.time_report,1338 .time_report = options.time_report,
1339 .tsan = options.sanitize_thread,1339 .tsan = options.sanitize_thread,
1340 .sancov = options.fuzz,1340 .sancov = options.fuzz,
1341 .lto = options.lto,1341 .lto = options.lto != .none,
1342 // https://github.com/ziglang/zig/issues/212151342 // https://github.com/ziglang/zig/issues/21215
1343 .allow_fast_isel = !comp.root_mod.resolved_target.result.cpu.arch.isMIPS(),1343 .allow_fast_isel = !comp.root_mod.resolved_target.result.cpu.arch.isMIPS(),
1344 .asm_filename = null,1344 .asm_filename = null,
src/libunwind.zig+1-1
...@@ -37,7 +37,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -37,7 +37,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
37 .root_strip = comp.compilerRtStrip(),37 .root_strip = comp.compilerRtStrip(),
38 .link_libc = true,38 .link_libc = true,
39 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/5682539 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
40 .lto = false,40 .lto = .none,
41 }) catch |err| {41 }) catch |err| {
42 comp.setMiscFailure(42 comp.setMiscFailure(
43 .libunwind,43 .libunwind,
src/link/Coff.zig+1-1
...@@ -1859,7 +1859,7 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -1859,7 +1859,7 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
1859 if (comp.version) |version| {1859 if (comp.version) |version| {
1860 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));1860 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
1861 }1861 }
1862 if (comp.config.lto) {1862 if (comp.config.lto != .none) {
1863 switch (optimize_mode) {1863 switch (optimize_mode) {
1864 .Debug => {},1864 .Debug => {},
1865 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),1865 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
src/link/Elf.zig+2-2
...@@ -1640,7 +1640,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s...@@ -1640,7 +1640,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
1640 // copy when generating relocatables. Normally, we would expect `lld -r` to work.1640 // copy when generating relocatables. Normally, we would expect `lld -r` to work.
1641 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails1641 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
1642 // before even generating the relocatable.1642 // before even generating the relocatable.
1643 if (output_mode == .Obj and (comp.config.lto or target.cpu.arch.isBpf())) {1643 if (output_mode == .Obj and (comp.config.lto != .none or target.cpu.arch.isBpf())) {
1644 // In this case we must do a simple file copy1644 // In this case we must do a simple file copy
1645 // here. TODO: think carefully about how we can avoid this redundant operation when doing1645 // here. TODO: think carefully about how we can avoid this redundant operation when doing
1646 // build-obj. See also the corresponding TODO in linkAsArchive.1646 // 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...@@ -1683,7 +1683,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
1683 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));1683 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
1684 }1684 }
16851685
1686 if (comp.config.lto) {1686 if (comp.config.lto != .none) {
1687 switch (comp.root_mod.optimize_mode) {1687 switch (comp.root_mod.optimize_mode) {
1688 .Debug => {},1688 .Debug => {},
1689 .ReleaseSmall => try argv.append("--lto-O2"),1689 .ReleaseSmall => try argv.append("--lto-O2"),
src/link/Wasm.zig+1-1
...@@ -3537,7 +3537,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -3537,7 +3537,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
3537 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });3537 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
3538 try argv.append("--error-limit=0");3538 try argv.append("--error-limit=0");
35393539
3540 if (comp.config.lto) {3540 if (comp.config.lto != .none) {
3541 switch (comp.root_mod.optimize_mode) {3541 switch (comp.root_mod.optimize_mode) {
3542 .Debug => {},3542 .Debug => {},
3543 .ReleaseSmall => try argv.append("-O2"),3543 .ReleaseSmall => try argv.append("-O2"),
src/main.zig+25-4
...@@ -1386,9 +1386,18 @@ fn buildOutputType(...@@ -1386,9 +1386,18 @@ fn buildOutputType(
1386 } else if (mem.eql(u8, arg, "-fno-PIE")) {1386 } else if (mem.eql(u8, arg, "-fno-PIE")) {
1387 create_module.opts.pie = false;1387 create_module.opts.pie = false;
1388 } else if (mem.eql(u8, arg, "-flto")) {1388 } else if (mem.eql(u8, arg, "-flto")) {
1389 create_module.opts.lto = true;1389 create_module.opts.lto = .full;
1390 } else if (mem.startsWith(u8, arg, "-flto=")) {
1391 const mode = arg["-flto=".len..];
1392 if (mem.eql(u8, mode, "full")) {
1393 create_module.opts.lto = .full;
1394 } else if (mem.eql(u8, mode, "thin")) {
1395 create_module.opts.lto = .thin;
1396 } else {
1397 fatal("Invalid -flto mode: '{s}'. Must be 'full'or 'thin'.", .{mode});
1398 }
1390 } else if (mem.eql(u8, arg, "-fno-lto")) {1399 } else if (mem.eql(u8, arg, "-fno-lto")) {
1391 create_module.opts.lto = false;1400 create_module.opts.lto = .none;
1392 } else if (mem.eql(u8, arg, "-funwind-tables")) {1401 } else if (mem.eql(u8, arg, "-funwind-tables")) {
1393 mod_opts.unwind_tables = .sync;1402 mod_opts.unwind_tables = .sync;
1394 } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {1403 } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
...@@ -1958,8 +1967,20 @@ fn buildOutputType(...@@ -1958,8 +1967,20 @@ fn buildOutputType(
1958 .no_pic => mod_opts.pic = false,1967 .no_pic => mod_opts.pic = false,
1959 .pie => create_module.opts.pie = true,1968 .pie => create_module.opts.pie = true,
1960 .no_pie => create_module.opts.pie = false,1969 .no_pie => create_module.opts.pie = false,
1961 .lto => create_module.opts.lto = true,1970 .lto => {
1962 .no_lto => create_module.opts.lto = false,1971 if (mem.eql(u8, it.only_arg, "flto") or
1972 mem.eql(u8, it.only_arg, "auto") or
1973 mem.eql(u8, it.only_arg, "full") or
1974 mem.eql(u8, it.only_arg, "jobserver"))
1975 {
1976 create_module.opts.lto = .full;
1977 } else if (mem.eql(u8, it.only_arg, "thin")) {
1978 create_module.opts.lto = .thin;
1979 } else {
1980 fatal("Invalid -flto mode: '{s}'. Must be 'auto', 'full', 'thin', or 'jobserver'.", .{it.only_arg});
1981 }
1982 },
1983 .no_lto => create_module.opts.lto = .none,
1963 .red_zone => mod_opts.red_zone = true,1984 .red_zone => mod_opts.red_zone = true,
1964 .no_red_zone => mod_opts.red_zone = false,1985 .no_red_zone => mod_opts.red_zone = false,
1965 .omit_frame_pointer => mod_opts.omit_frame_pointer = true,1986 .omit_frame_pointer => mod_opts.omit_frame_pointer = true,