From b4b1c4df640c9b40c303eef7d0364d01ec490a8e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 23 Nov 2023 23:58:50 +0100 Subject: [PATCH] spirv: add -fstructured-cfg option This enables the compiler to generate a structured cfg even in opencl, even if it is not strictly required by the SPIR-V Kernel specification. --- src/Compilation.zig | 15 ++++++++++++++- src/codegen/spirv.zig | 9 +++++++++ src/link.zig | 3 +++ src/main.zig | 9 ++++++++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 4917f40b29..7fa1adf528 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1002,6 +1002,8 @@ pub const InitOptions = struct { /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, error_limit: ?Module.ErrorInt = null, + /// (SPIR-V) whether to generate a structured control flow graph or not + want_structured_cfg: ?bool = null, }; fn addModuleTableToCacheHash( @@ -1447,6 +1449,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }; const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug); + const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); + // We put everything into the cache hash that *cannot be modified // during an incremental update*. For example, one cannot change the // target between updates, but one can change source files, so the @@ -1545,6 +1549,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { hash.add(options.skip_linker_dependencies); hash.add(options.parent_compilation_link_libc); hash.add(formatted_panics); + hash.add(options.emit_h != null); + hash.add(error_limit); + hash.addOptional(options.want_structured_cfg); // In the case of incremental cache mode, this `zig_cache_artifact_directory` // is computed based on a hash of non-linker inputs, and it is where all @@ -1699,7 +1706,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .local_zir_cache = local_zir_cache, .emit_h = emit_h, .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa), - .error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1), + .error_limit = error_limit, }; try module.init(); @@ -1958,6 +1965,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .force_undefined_symbols = options.force_undefined_symbols, .pdb_source_path = options.pdb_source_path, .pdb_out_path = options.pdb_out_path, + .want_structured_cfg = options.want_structured_cfg, }); errdefer bin_file.destroy(); comp.* = .{ @@ -2732,6 +2740,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.bin_file.options.valgrind); man.hash.add(comp.bin_file.options.single_threaded); man.hash.add(comp.bin_file.options.use_llvm); + man.hash.add(comp.bin_file.options.use_lib_llvm); man.hash.add(comp.bin_file.options.dll_export_fns); man.hash.add(comp.bin_file.options.is_test); man.hash.add(comp.test_evented_io); @@ -2739,8 +2748,10 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptionalBytes(comp.test_name_prefix); man.hash.add(comp.bin_file.options.skip_linker_dependencies); man.hash.add(comp.bin_file.options.parent_compilation_link_libc); + man.hash.add(comp.formatted_panics); man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); + man.hash.addOptional(comp.bin_file.options.want_structured_cfg); } try man.addOptionalFile(comp.bin_file.options.linker_script); @@ -6823,6 +6834,7 @@ fn buildOutputFromZig( .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, .parent_compilation_link_libc = comp.bin_file.options.link_libc, + .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); @@ -6903,6 +6915,7 @@ pub fn build_crt_file( .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, .parent_compilation_link_libc = comp.bin_file.options.link_libc, + .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 8bee639b60..7901e37135 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -99,6 +99,15 @@ pub const Object = struct { air: Air, liveness: Liveness, ) !void { + const target = mod.getTarget(); + // We always want a structured control flow in shaders. This option is only relevant + // for OpenCL kernels. + const want_structured_cfg = switch (target.os.tag) { + .opencl => mod.comp.bin_file.options.want_structured_cfg orelse false, + else => true, + }; + _ = want_structured_cfg; + var decl_gen = DeclGen{ .gpa = self.gpa, .object = self, diff --git a/src/link.zig b/src/link.zig index 1648d6a63e..c6b946ddc4 100644 --- a/src/link.zig +++ b/src/link.zig @@ -268,6 +268,9 @@ pub const Options = struct { /// (Windows) .def file to specify when linking module_definition_file: ?[]const u8 = null, + /// (SPIR-V) whether to generate a structured control flow graph or not + want_structured_cfg: ?bool = null, + pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode { return if (options.use_lld) .Obj else options.output_mode; } diff --git a/src/main.zig b/src/main.zig index 641dd04164..11e40f09ca 100644 --- a/src/main.zig +++ b/src/main.zig @@ -493,6 +493,8 @@ const usage_build_generic = \\ msvc Use msvc include paths (must be present on the system) \\ gnu Use mingw include paths (distributed with Zig) \\ none Do not use any autodetected include paths + \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow + \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow \\ \\Link Options: \\ -l[lib], --library [lib] Link against system library (only if actually used) @@ -913,7 +915,7 @@ fn buildOutputType( var pdb_out_path: ?[]const u8 = null; var dwarf_format: ?std.dwarf.Format = null; var error_limit: ?Module.ErrorInt = null; - + var want_structured_cfg: ?bool = null; // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. // This array is populated by zig cc frontend and then has to be converted to zig-style // CPU features. @@ -1070,6 +1072,10 @@ fn buildOutputType( if (mem.eql(u8, next_arg, "--")) break; try extra_rcflags.append(next_arg); } + } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) { + want_structured_cfg = true; + } else if (mem.startsWith(u8, arg, "-fno-structured-cfg")) { + want_structured_cfg = false; } else if (mem.eql(u8, arg, "--color")) { const next_arg = args_iter.next() orelse { fatal("expected [auto|on|off] after --color", .{}); @@ -3595,6 +3601,7 @@ fn buildOutputType( .error_tracing = error_tracing, .pdb_out_path = pdb_out_path, .error_limit = error_limit, + .want_structured_cfg = want_structured_cfg, }) catch |err| switch (err) { error.LibCUnavailable => { const target = target_info.target;