authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-11-23 23:58:50+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-11-24 11:40:18+01:00
logb4b1c4df640c9b40c303eef7d0364d01ec490a8e
treebf5d534fb5b3c7cdb3b78f2846e4272939258e45
parentcb026c5d599dddc38f34ee93438d52bbffe2f6ad
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

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.

4 files changed, 34 insertions(+), 2 deletions(-)

src/Compilation.zig+14-1
......@@ -1002,6 +1002,8 @@ pub const InitOptions = struct {
10021002 /// (Windows) PDB output path
10031003 pdb_out_path: ?[]const u8 = null,
10041004 error_limit: ?Module.ErrorInt = null,
1005 /// (SPIR-V) whether to generate a structured control flow graph or not
1006 want_structured_cfg: ?bool = null,
10051007};
10061008
10071009fn addModuleTableToCacheHash(
......@@ -1447,6 +1449,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14471449 };
14481450 const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug);
14491451
1452 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
1453
14501454 // We put everything into the cache hash that *cannot be modified
14511455 // during an incremental update*. For example, one cannot change the
14521456 // target between updates, but one can change source files, so the
......@@ -1545,6 +1549,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15451549 hash.add(options.skip_linker_dependencies);
15461550 hash.add(options.parent_compilation_link_libc);
15471551 hash.add(formatted_panics);
1552 hash.add(options.emit_h != null);
1553 hash.add(error_limit);
1554 hash.addOptional(options.want_structured_cfg);
15481555
15491556 // In the case of incremental cache mode, this `zig_cache_artifact_directory`
15501557 // 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 {
16991706 .local_zir_cache = local_zir_cache,
17001707 .emit_h = emit_h,
17011708 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1702 .error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1),
1709 .error_limit = error_limit,
17031710 };
17041711 try module.init();
17051712
......@@ -1958,6 +1965,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
19581965 .force_undefined_symbols = options.force_undefined_symbols,
19591966 .pdb_source_path = options.pdb_source_path,
19601967 .pdb_out_path = options.pdb_out_path,
1968 .want_structured_cfg = options.want_structured_cfg,
19611969 });
19621970 errdefer bin_file.destroy();
19631971 comp.* = .{
......@@ -2732,6 +2740,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
27322740 man.hash.add(comp.bin_file.options.valgrind);
27332741 man.hash.add(comp.bin_file.options.single_threaded);
27342742 man.hash.add(comp.bin_file.options.use_llvm);
2743 man.hash.add(comp.bin_file.options.use_lib_llvm);
27352744 man.hash.add(comp.bin_file.options.dll_export_fns);
27362745 man.hash.add(comp.bin_file.options.is_test);
27372746 man.hash.add(comp.test_evented_io);
......@@ -2739,8 +2748,10 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
27392748 man.hash.addOptionalBytes(comp.test_name_prefix);
27402749 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
27412750 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
2751 man.hash.add(comp.formatted_panics);
27422752 man.hash.add(mod.emit_h != null);
27432753 man.hash.add(mod.error_limit);
2754 man.hash.addOptional(comp.bin_file.options.want_structured_cfg);
27442755 }
27452756
27462757 try man.addOptionalFile(comp.bin_file.options.linker_script);
......@@ -6823,6 +6834,7 @@ fn buildOutputFromZig(
68236834 .clang_passthrough_mode = comp.clang_passthrough_mode,
68246835 .skip_linker_dependencies = true,
68256836 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
6837 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
68266838 });
68276839 defer sub_compilation.destroy();
68286840
......@@ -6903,6 +6915,7 @@ pub fn build_crt_file(
69036915 .clang_passthrough_mode = comp.clang_passthrough_mode,
69046916 .skip_linker_dependencies = true,
69056917 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
6918 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
69066919 });
69076920 defer sub_compilation.destroy();
69086921
src/codegen/spirv.zig+9
......@@ -99,6 +99,15 @@ pub const Object = struct {
9999 air: Air,
100100 liveness: Liveness,
101101 ) !void {
102 const target = mod.getTarget();
103 // We always want a structured control flow in shaders. This option is only relevant
104 // for OpenCL kernels.
105 const want_structured_cfg = switch (target.os.tag) {
106 .opencl => mod.comp.bin_file.options.want_structured_cfg orelse false,
107 else => true,
108 };
109 _ = want_structured_cfg;
110
102111 var decl_gen = DeclGen{
103112 .gpa = self.gpa,
104113 .object = self,
src/link.zig+3
......@@ -268,6 +268,9 @@ pub const Options = struct {
268268 /// (Windows) .def file to specify when linking
269269 module_definition_file: ?[]const u8 = null,
270270
271 /// (SPIR-V) whether to generate a structured control flow graph or not
272 want_structured_cfg: ?bool = null,
273
271274 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
272275 return if (options.use_lld) .Obj else options.output_mode;
273276 }
src/main.zig+8-1
......@@ -493,6 +493,8 @@ const usage_build_generic =
493493 \\ msvc Use msvc include paths (must be present on the system)
494494 \\ gnu Use mingw include paths (distributed with Zig)
495495 \\ none Do not use any autodetected include paths
496 \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow
497 \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow
496498 \\
497499 \\Link Options:
498500 \\ -l[lib], --library [lib] Link against system library (only if actually used)
......@@ -913,7 +915,7 @@ fn buildOutputType(
913915 var pdb_out_path: ?[]const u8 = null;
914916 var dwarf_format: ?std.dwarf.Format = null;
915917 var error_limit: ?Module.ErrorInt = null;
916
918 var want_structured_cfg: ?bool = null;
917919 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
918920 // This array is populated by zig cc frontend and then has to be converted to zig-style
919921 // CPU features.
......@@ -1070,6 +1072,10 @@ fn buildOutputType(
10701072 if (mem.eql(u8, next_arg, "--")) break;
10711073 try extra_rcflags.append(next_arg);
10721074 }
1075 } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) {
1076 want_structured_cfg = true;
1077 } else if (mem.startsWith(u8, arg, "-fno-structured-cfg")) {
1078 want_structured_cfg = false;
10731079 } else if (mem.eql(u8, arg, "--color")) {
10741080 const next_arg = args_iter.next() orelse {
10751081 fatal("expected [auto|on|off] after --color", .{});
......@@ -3595,6 +3601,7 @@ fn buildOutputType(
35953601 .error_tracing = error_tracing,
35963602 .pdb_out_path = pdb_out_path,
35973603 .error_limit = error_limit,
3604 .want_structured_cfg = want_structured_cfg,
35983605 }) catch |err| switch (err) {
35993606 error.LibCUnavailable => {
36003607 const target = target_info.target;