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 {...@@ -1002,6 +1002,8 @@ pub const InitOptions = struct {
1002 /// (Windows) PDB output path1002 /// (Windows) PDB output path
1003 pdb_out_path: ?[]const u8 = null,1003 pdb_out_path: ?[]const u8 = null,
1004 error_limit: ?Module.ErrorInt = null,1004 error_limit: ?Module.ErrorInt = null,
1005 /// (SPIR-V) whether to generate a structured control flow graph or not
1006 want_structured_cfg: ?bool = null,
1005};1007};
10061008
1007fn addModuleTableToCacheHash(1009fn addModuleTableToCacheHash(
...@@ -1447,6 +1449,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1447,6 +1449,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1447 };1449 };
1448 const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug);1450 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
1450 // We put everything into the cache hash that *cannot be modified1454 // We put everything into the cache hash that *cannot be modified
1451 // during an incremental update*. For example, one cannot change the1455 // during an incremental update*. For example, one cannot change the
1452 // target between updates, but one can change source files, so the1456 // target between updates, but one can change source files, so the
...@@ -1545,6 +1549,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1545,6 +1549,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1545 hash.add(options.skip_linker_dependencies);1549 hash.add(options.skip_linker_dependencies);
1546 hash.add(options.parent_compilation_link_libc);1550 hash.add(options.parent_compilation_link_libc);
1547 hash.add(formatted_panics);1551 hash.add(formatted_panics);
1552 hash.add(options.emit_h != null);
1553 hash.add(error_limit);
1554 hash.addOptional(options.want_structured_cfg);
15481555
1549 // In the case of incremental cache mode, this `zig_cache_artifact_directory`1556 // In the case of incremental cache mode, this `zig_cache_artifact_directory`
1550 // is computed based on a hash of non-linker inputs, and it is where all1557 // 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 {...@@ -1699,7 +1706,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1699 .local_zir_cache = local_zir_cache,1706 .local_zir_cache = local_zir_cache,
1700 .emit_h = emit_h,1707 .emit_h = emit_h,
1701 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),1708 .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,
1703 };1710 };
1704 try module.init();1711 try module.init();
17051712
...@@ -1958,6 +1965,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1958,6 +1965,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1958 .force_undefined_symbols = options.force_undefined_symbols,1965 .force_undefined_symbols = options.force_undefined_symbols,
1959 .pdb_source_path = options.pdb_source_path,1966 .pdb_source_path = options.pdb_source_path,
1960 .pdb_out_path = options.pdb_out_path,1967 .pdb_out_path = options.pdb_out_path,
1968 .want_structured_cfg = options.want_structured_cfg,
1961 });1969 });
1962 errdefer bin_file.destroy();1970 errdefer bin_file.destroy();
1963 comp.* = .{1971 comp.* = .{
...@@ -2732,6 +2740,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2732,6 +2740,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2732 man.hash.add(comp.bin_file.options.valgrind);2740 man.hash.add(comp.bin_file.options.valgrind);
2733 man.hash.add(comp.bin_file.options.single_threaded);2741 man.hash.add(comp.bin_file.options.single_threaded);
2734 man.hash.add(comp.bin_file.options.use_llvm);2742 man.hash.add(comp.bin_file.options.use_llvm);
2743 man.hash.add(comp.bin_file.options.use_lib_llvm);
2735 man.hash.add(comp.bin_file.options.dll_export_fns);2744 man.hash.add(comp.bin_file.options.dll_export_fns);
2736 man.hash.add(comp.bin_file.options.is_test);2745 man.hash.add(comp.bin_file.options.is_test);
2737 man.hash.add(comp.test_evented_io);2746 man.hash.add(comp.test_evented_io);
...@@ -2739,8 +2748,10 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2739,8 +2748,10 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2739 man.hash.addOptionalBytes(comp.test_name_prefix);2748 man.hash.addOptionalBytes(comp.test_name_prefix);
2740 man.hash.add(comp.bin_file.options.skip_linker_dependencies);2749 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
2741 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);2750 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
2751 man.hash.add(comp.formatted_panics);
2742 man.hash.add(mod.emit_h != null);2752 man.hash.add(mod.emit_h != null);
2743 man.hash.add(mod.error_limit);2753 man.hash.add(mod.error_limit);
2754 man.hash.addOptional(comp.bin_file.options.want_structured_cfg);
2744 }2755 }
27452756
2746 try man.addOptionalFile(comp.bin_file.options.linker_script);2757 try man.addOptionalFile(comp.bin_file.options.linker_script);
...@@ -6823,6 +6834,7 @@ fn buildOutputFromZig(...@@ -6823,6 +6834,7 @@ fn buildOutputFromZig(
6823 .clang_passthrough_mode = comp.clang_passthrough_mode,6834 .clang_passthrough_mode = comp.clang_passthrough_mode,
6824 .skip_linker_dependencies = true,6835 .skip_linker_dependencies = true,
6825 .parent_compilation_link_libc = comp.bin_file.options.link_libc,6836 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
6837 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
6826 });6838 });
6827 defer sub_compilation.destroy();6839 defer sub_compilation.destroy();
68286840
...@@ -6903,6 +6915,7 @@ pub fn build_crt_file(...@@ -6903,6 +6915,7 @@ pub fn build_crt_file(
6903 .clang_passthrough_mode = comp.clang_passthrough_mode,6915 .clang_passthrough_mode = comp.clang_passthrough_mode,
6904 .skip_linker_dependencies = true,6916 .skip_linker_dependencies = true,
6905 .parent_compilation_link_libc = comp.bin_file.options.link_libc,6917 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
6918 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
6906 });6919 });
6907 defer sub_compilation.destroy();6920 defer sub_compilation.destroy();
69086921
src/codegen/spirv.zig+9
...@@ -99,6 +99,15 @@ pub const Object = struct {...@@ -99,6 +99,15 @@ pub const Object = struct {
99 air: Air,99 air: Air,
100 liveness: Liveness,100 liveness: Liveness,
101 ) !void {101 ) !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
102 var decl_gen = DeclGen{111 var decl_gen = DeclGen{
103 .gpa = self.gpa,112 .gpa = self.gpa,
104 .object = self,113 .object = self,
src/link.zig+3
...@@ -268,6 +268,9 @@ pub const Options = struct {...@@ -268,6 +268,9 @@ pub const Options = struct {
268 /// (Windows) .def file to specify when linking268 /// (Windows) .def file to specify when linking
269 module_definition_file: ?[]const u8 = null,269 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
271 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {274 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
272 return if (options.use_lld) .Obj else options.output_mode;275 return if (options.use_lld) .Obj else options.output_mode;
273 }276 }
src/main.zig+8-1
...@@ -493,6 +493,8 @@ const usage_build_generic =...@@ -493,6 +493,8 @@ const usage_build_generic =
493 \\ msvc Use msvc include paths (must be present on the system)493 \\ msvc Use msvc include paths (must be present on the system)
494 \\ gnu Use mingw include paths (distributed with Zig)494 \\ gnu Use mingw include paths (distributed with Zig)
495 \\ none Do not use any autodetected include paths495 \\ 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
496 \\498 \\
497 \\Link Options:499 \\Link Options:
498 \\ -l[lib], --library [lib] Link against system library (only if actually used)500 \\ -l[lib], --library [lib] Link against system library (only if actually used)
...@@ -913,7 +915,7 @@ fn buildOutputType(...@@ -913,7 +915,7 @@ fn buildOutputType(
913 var pdb_out_path: ?[]const u8 = null;915 var pdb_out_path: ?[]const u8 = null;
914 var dwarf_format: ?std.dwarf.Format = null;916 var dwarf_format: ?std.dwarf.Format = null;
915 var error_limit: ?Module.ErrorInt = null;917 var error_limit: ?Module.ErrorInt = null;
916918 var want_structured_cfg: ?bool = null;
917 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.919 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
918 // This array is populated by zig cc frontend and then has to be converted to zig-style920 // This array is populated by zig cc frontend and then has to be converted to zig-style
919 // CPU features.921 // CPU features.
...@@ -1070,6 +1072,10 @@ fn buildOutputType(...@@ -1070,6 +1072,10 @@ fn buildOutputType(
1070 if (mem.eql(u8, next_arg, "--")) break;1072 if (mem.eql(u8, next_arg, "--")) break;
1071 try extra_rcflags.append(next_arg);1073 try extra_rcflags.append(next_arg);
1072 }1074 }
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;
1073 } else if (mem.eql(u8, arg, "--color")) {1079 } else if (mem.eql(u8, arg, "--color")) {
1074 const next_arg = args_iter.next() orelse {1080 const next_arg = args_iter.next() orelse {
1075 fatal("expected [auto|on|off] after --color", .{});1081 fatal("expected [auto|on|off] after --color", .{});
...@@ -3595,6 +3601,7 @@ fn buildOutputType(...@@ -3595,6 +3601,7 @@ fn buildOutputType(
3595 .error_tracing = error_tracing,3601 .error_tracing = error_tracing,
3596 .pdb_out_path = pdb_out_path,3602 .pdb_out_path = pdb_out_path,
3597 .error_limit = error_limit,3603 .error_limit = error_limit,
3604 .want_structured_cfg = want_structured_cfg,
3598 }) catch |err| switch (err) {3605 }) catch |err| switch (err) {
3599 error.LibCUnavailable => {3606 error.LibCUnavailable => {
3600 const target = target_info.target;3607 const target = target_info.target;