From 60a20bcf3dc329f3e95d28b7f99d2f90060c65a7 Mon Sep 17 00:00:00 2001 From: Konstantin Seurer Date: Mon, 4 Nov 2024 21:16:16 +0100 Subject: [PATCH] nir: Stop using instructions for debug info Annotating ssa defs without affecting compilation is impossible with debug info instructions since referencing a nir_def from the debug info instr will add uses. The old approach also stops worrking if passes reorder instructions. This patch proposes a solution which should not regress performance just like the old approach. The difference is that this one allocates a bit more space for debug info instead of adding a new instruction for it. Reviewed-by: Alyssa Rosenzweig Part-of: --- .../compiler/aco_instruction_selection.cpp | 23 ++- src/amd/vulkan/radv_shader.c | 1 + src/broadcom/compiler/vir.c | 3 - src/compiler/nir/nir.c | 115 ++++++++------- src/compiler/nir/nir.h | 83 +++++------ src/compiler/nir/nir_builder.c | 28 ++-- src/compiler/nir/nir_clone.c | 75 ++++++---- src/compiler/nir/nir_divergence_analysis.c | 3 - src/compiler/nir/nir_inline_helpers.h | 16 --- src/compiler/nir/nir_instr_set.c | 22 --- src/compiler/nir/nir_opt_dce.c | 10 -- .../nir/nir_opt_move_discards_to_top.c | 1 - src/compiler/nir/nir_opt_peephole_select.c | 4 - src/compiler/nir/nir_print.c | 135 ++++++------------ src/compiler/nir/nir_propagate_invariant.c | 1 - src/compiler/nir/nir_schedule.c | 2 - src/compiler/nir/nir_serialize.c | 127 ++++++++-------- src/compiler/nir/nir_validate.c | 3 - src/compiler/spirv/spirv_to_nir.c | 34 ++--- src/freedreno/ir3/ir3_compiler_nir.c | 2 - .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 3 - 21 files changed, 308 insertions(+), 383 deletions(-) diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index adf8bf8129a..285c3f0c5e6 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -9947,22 +9947,17 @@ visit_jump(isel_context* ctx, nir_jump_instr* instr) } void -visit_debug_info(isel_context* ctx, nir_debug_info_instr* instr) +visit_debug_info(isel_context* ctx, nir_instr_debug_info* instr_info) { ac_shader_debug_info info; memset(&info, 0, sizeof(info)); - switch (instr->type) { - case nir_debug_info_src_loc: - info.type = ac_shader_debug_info_src_loc; - info.src_loc.file = strdup(nir_src_as_string(instr->src_loc.filename)); - info.src_loc.line = instr->src_loc.line; - info.src_loc.column = instr->src_loc.column; - info.src_loc.spirv_offset = instr->src_loc.spirv_offset; - break; - default: - return; - } + info.type = ac_shader_debug_info_src_loc; + if (instr_info->filename) + info.src_loc.file = strdup(instr_info->filename); + info.src_loc.line = instr_info->line; + info.src_loc.column = instr_info->column; + info.src_loc.spirv_offset = instr_info->spirv_offset; Builder bld(ctx->program, ctx->block); bld.pseudo(aco_opcode::p_debug_info, Operand::c32(ctx->program->debug_info.size())); @@ -9990,6 +9985,9 @@ visit_block(isel_context* ctx, nir_block* block) ctx->block->instructions.reserve(ctx->block->instructions.size() + exec_list_length(&block->instr_list) * 2); nir_foreach_instr (instr, block) { + if (ctx->shader->has_debug_info) + visit_debug_info(ctx, nir_instr_get_debug_info(instr)); + switch (instr->type) { case nir_instr_type_alu: visit_alu_instr(ctx, nir_instr_as_alu(instr)); break; case nir_instr_type_load_const: visit_load_const(ctx, nir_instr_as_load_const(instr)); break; @@ -9999,7 +9997,6 @@ visit_block(isel_context* ctx, nir_block* block) case nir_instr_type_undef: visit_undef(ctx, nir_instr_as_undef(instr)); break; case nir_instr_type_deref: break; case nir_instr_type_jump: visit_jump(ctx, nir_instr_as_jump(instr)); break; - case nir_instr_type_debug_info: visit_debug_info(ctx, nir_instr_as_debug_info(instr)); break; default: isel_err(instr, "Unknown NIR instr type"); } } diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 00fb3a5c1ac..bf0edba5373 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -375,6 +375,7 @@ radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_st .force_ssbo_non_uniform = pdev->cache_key.ssbo_non_uniform, .lower_terminate_to_discard = pdev->cache_key.lower_terminate_to_discard, .emit_debug_break = !!device->trap_handler_shader, + .debug_info = !!(instance->debug_flags & RADV_DEBUG_NIR_DEBUG_INFO), }; nir = spirv_to_nir(spirv, stage->spirv.size / 4, spec_entries, num_spec_entries, stage->stage, stage->entrypoint, &spirv_options, &pdev->nir_options[stage->stage]); diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c index 674bef23abf..0b526768d8b 100644 --- a/src/broadcom/compiler/vir.c +++ b/src/broadcom/compiler/vir.c @@ -1316,9 +1316,6 @@ v3d_instr_delay_cb(nir_instr *instr, void *data) case nir_instr_type_tex: return 5; - - case nir_instr_type_debug_info: - return 0; } return 0; diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 8f9ec619779..14d52dbd2de 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -663,12 +663,24 @@ nir_loop_create(nir_shader *shader) return loop; } -static void -instr_init(nir_instr *instr, nir_instr_type type) +static void * +nir_instr_create(nir_shader *shader, nir_instr_type type, uint32_t size) { + nir_instr *instr; + if (shader->has_debug_info) { + nir_instr_debug_info *debug_info = + gc_zalloc_size(shader->gctx, offsetof(nir_instr_debug_info, instr) + size, 8); + instr = &debug_info->instr; + instr->has_debug_info = true; + } else { + instr = gc_zalloc_size(shader->gctx, size, 8); + } + instr->type = type; instr->block = NULL; exec_node_init(&instr->node); + + return instr; } static void @@ -683,9 +695,10 @@ nir_alu_instr * nir_alu_instr_create(nir_shader *shader, nir_op op) { unsigned num_srcs = nir_op_infos[op].num_inputs; - nir_alu_instr *instr = gc_zalloc_zla(shader->gctx, nir_alu_instr, nir_alu_src, num_srcs); + nir_alu_instr *instr = + nir_instr_create(shader, nir_instr_type_alu, + sizeof(nir_alu_instr) + sizeof(nir_alu_src) * num_srcs); - instr_init(&instr->instr, nir_instr_type_alu); instr->op = op; for (unsigned i = 0; i < num_srcs; i++) alu_src_init(&instr->src[i]); @@ -696,9 +709,8 @@ nir_alu_instr_create(nir_shader *shader, nir_op op) nir_deref_instr * nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type) { - nir_deref_instr *instr = gc_zalloc(shader->gctx, nir_deref_instr, 1); - - instr_init(&instr->instr, nir_instr_type_deref); + nir_deref_instr *instr = + nir_instr_create(shader, nir_instr_type_deref, sizeof(nir_deref_instr)); instr->deref_type = deref_type; if (deref_type != nir_deref_type_var) @@ -714,8 +726,9 @@ nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type) nir_jump_instr * nir_jump_instr_create(nir_shader *shader, nir_jump_type type) { - nir_jump_instr *instr = gc_alloc(shader->gctx, nir_jump_instr, 1); - instr_init(&instr->instr, nir_instr_type_jump); + nir_jump_instr *instr = + nir_instr_create(shader, nir_instr_type_jump, sizeof(nir_jump_instr)); + src_init(&instr->condition); instr->type = type; instr->target = NULL; @@ -729,8 +742,8 @@ nir_load_const_instr_create(nir_shader *shader, unsigned num_components, unsigned bit_size) { nir_load_const_instr *instr = - gc_zalloc_zla(shader->gctx, nir_load_const_instr, nir_const_value, num_components); - instr_init(&instr->instr, nir_instr_type_load_const); + nir_instr_create(shader, nir_instr_type_load_const, + sizeof(nir_load_const_instr) + sizeof(nir_const_value) * num_components); nir_def_init(&instr->instr, &instr->def, num_components, bit_size); @@ -742,9 +755,9 @@ nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op) { unsigned num_srcs = nir_intrinsic_infos[op].num_srcs; nir_intrinsic_instr *instr = - gc_zalloc_zla(shader->gctx, nir_intrinsic_instr, nir_src, num_srcs); + nir_instr_create(shader, nir_instr_type_intrinsic, + sizeof(nir_intrinsic_instr) + sizeof(nir_src) * num_srcs); - instr_init(&instr->instr, nir_instr_type_intrinsic); instr->intrinsic = op; for (unsigned i = 0; i < num_srcs; i++) @@ -758,9 +771,9 @@ nir_call_instr_create(nir_shader *shader, nir_function *callee) { const unsigned num_params = callee->num_params; nir_call_instr *instr = - gc_zalloc_zla(shader->gctx, nir_call_instr, nir_src, num_params); + nir_instr_create(shader, nir_instr_type_call, + sizeof(nir_call_instr) + sizeof(nir_src) * num_params); - instr_init(&instr->instr, nir_instr_type_call); instr->callee = callee; instr->num_params = num_params; for (unsigned i = 0; i < num_params; i++) @@ -779,8 +792,8 @@ static int8_t default_tg4_offsets[4][2] = { nir_tex_instr * nir_tex_instr_create(nir_shader *shader, unsigned num_srcs) { - nir_tex_instr *instr = gc_zalloc(shader->gctx, nir_tex_instr, 1); - instr_init(&instr->instr, nir_instr_type_tex); + nir_tex_instr *instr = + nir_instr_create(shader, nir_instr_type_tex, sizeof(nir_tex_instr)); instr->num_srcs = num_srcs; instr->src = gc_alloc(shader->gctx, nir_tex_src, num_srcs); @@ -794,12 +807,28 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs) return instr; } +static void * +nir_instr_get_gc_pointer(nir_instr *instr) +{ + if (unlikely(instr->has_debug_info)) + return nir_instr_get_debug_info(instr); + + return instr; +} + +static gc_ctx * +nir_instr_get_gc_context(nir_instr *instr) +{ + return gc_get_context(nir_instr_get_gc_pointer(instr)); +} + void nir_tex_instr_add_src(nir_tex_instr *tex, nir_tex_src_type src_type, nir_def *src) { - nir_tex_src *new_srcs = gc_zalloc(gc_get_context(tex), nir_tex_src, tex->num_srcs + 1); + nir_tex_src *new_srcs = gc_zalloc(nir_instr_get_gc_context(&tex->instr), + nir_tex_src, tex->num_srcs + 1); for (unsigned i = 0; i < tex->num_srcs; i++) { new_srcs[i].src_type = tex->src[i].src_type; @@ -843,8 +872,8 @@ nir_tex_instr_has_explicit_tg4_offsets(nir_tex_instr *tex) nir_phi_instr * nir_phi_instr_create(nir_shader *shader) { - nir_phi_instr *instr = gc_alloc(shader->gctx, nir_phi_instr, 1); - instr_init(&instr->instr, nir_instr_type_phi); + nir_phi_instr *instr = + nir_instr_create(shader, nir_instr_type_phi, sizeof(nir_phi_instr)); exec_list_make_empty(&instr->srcs); @@ -864,7 +893,8 @@ nir_phi_instr_add_src(nir_phi_instr *instr, nir_block *pred, nir_def *src) { nir_phi_src *phi_src; - phi_src = gc_zalloc(gc_get_context(instr), nir_phi_src, 1); + phi_src = gc_zalloc(nir_instr_get_gc_context(&instr->instr), + nir_phi_src, 1); phi_src->pred = pred; phi_src->src = nir_src_for_ssa(src); nir_src_set_parent_instr(&phi_src->src, &instr->instr); @@ -876,41 +906,21 @@ nir_phi_instr_add_src(nir_phi_instr *instr, nir_block *pred, nir_def *src) nir_parallel_copy_instr * nir_parallel_copy_instr_create(nir_shader *shader) { - nir_parallel_copy_instr *instr = gc_alloc(shader->gctx, nir_parallel_copy_instr, 1); - instr_init(&instr->instr, nir_instr_type_parallel_copy); + nir_parallel_copy_instr *instr = + nir_instr_create(shader, nir_instr_type_parallel_copy, sizeof(nir_parallel_copy_instr)); exec_list_make_empty(&instr->entries); return instr; } -nir_debug_info_instr * -nir_debug_info_instr_create(nir_shader *shader, nir_debug_info_type type, - uint32_t string_length) -{ - uint32_t additional_size = 0; - if (type == nir_debug_info_string) - additional_size = string_length + 1; - - nir_debug_info_instr *instr = gc_zalloc_size( - shader->gctx, sizeof(nir_debug_info_instr) + additional_size, 1); - instr_init(&instr->instr, nir_instr_type_debug_info); - - instr->type = type; - - if (type == nir_debug_info_string) - instr->string_length = string_length; - - return instr; -} - nir_undef_instr * nir_undef_instr_create(nir_shader *shader, unsigned num_components, unsigned bit_size) { - nir_undef_instr *instr = gc_alloc(shader->gctx, nir_undef_instr, 1); - instr_init(&instr->instr, nir_instr_type_undef); + nir_undef_instr *instr = + nir_instr_create(shader, nir_instr_type_undef, sizeof(nir_undef_instr)); nir_def_init(&instr->instr, &instr->def, num_components, bit_size); @@ -1228,7 +1238,7 @@ nir_instr_free(nir_instr *instr) break; } - gc_free(instr); + gc_free(nir_instr_get_gc_pointer(instr)); } void @@ -1367,9 +1377,6 @@ nir_instr_def(nir_instr *instr) case nir_instr_type_undef: return &nir_instr_as_undef(instr)->def; - case nir_instr_type_debug_info: - return &nir_instr_as_debug_info(instr)->def; - case nir_instr_type_call: case nir_instr_type_jump: return NULL; @@ -1442,16 +1449,6 @@ nir_src_as_const_value(nir_src src) return load->value; } -const char * -nir_src_as_string(nir_src src) -{ - nir_debug_info_instr *di = nir_src_as_debug_info(src); - if (di && di->type == nir_debug_info_string) - return di->string; - - return NULL; -} - /** * Returns true if the source is known to be always uniform. Otherwise it * returns false which means it may or may not be uniform but it can't be diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 2f46815a812..2a1198abbbf 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -990,7 +990,6 @@ typedef enum ENUM_PACKED { nir_instr_type_undef, nir_instr_type_phi, nir_instr_type_parallel_copy, - nir_instr_type_debug_info, } nir_instr_type; typedef struct nir_instr { @@ -1003,6 +1002,12 @@ typedef struct nir_instr { */ uint8_t pass_flags; + /* Equal to nir_shader::has_debug_info and intended to be used by + * functions that deal with debug information but do not have access to + * the nir_shader. + */ + bool has_debug_info; + /** generic instruction index. */ uint32_t index; } nir_instr; @@ -2722,40 +2727,34 @@ typedef struct { struct exec_list entries; } nir_parallel_copy_instr; -typedef enum nir_debug_info_type { - nir_debug_info_src_loc, - nir_debug_info_string, -} nir_debug_info_type; +/* This struct contains metadata for correlating the final nir shader + * (after many lowering and optimization passes) with the source spir-v + * or glsl. To avoid adding unnecessary overhead when the driver does not + * preserve non-semantic information (which is the common case), debug + * information is allocated before the instruction: + * + * +-------------------+-----------+--------------------------------+ + * | Debug information | nir_instr | Instruction type specific data | + * +-------------------+-----------+--------------------------------+ + * + * This is only allocated if nir_shader::has_debug_info is set. Accesses + * to nir_instr_debug_info should therefore check nir_shader::has_debug_info + * or nir_instr::has_debug_info. + */ +typedef struct nir_instr_debug_info { + /* Path to the source file this instruction originates from. */ + char *filename; + /* 0 if uninitialized. */ + uint32_t line; + uint32_t column; + uint32_t spirv_offset; -typedef enum nir_debug_info_source { - nir_debug_info_spirv, - nir_debug_info_nir, -} nir_debug_info_source; + /* Line in the output of nir_print_shader. 0 if uninitialized. */ + uint32_t nir_line; -typedef struct nir_debug_info_instr { + /* The nir_instr has to be the last field since it has a varying size. */ nir_instr instr; - - nir_debug_info_type type; - - union { - struct { - nir_src filename; - /* 0 if only the spirv_offset is available. */ - uint32_t line; - uint32_t column; - - uint32_t spirv_offset; - - nir_debug_info_source source; - } src_loc; - - uint16_t string_length; - }; - - nir_def def; - - char string[]; -} nir_debug_info_instr; +} nir_instr_debug_info; NIR_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr, type, nir_instr_type_alu) @@ -2778,9 +2777,6 @@ NIR_DEFINE_CAST(nir_instr_as_phi, nir_instr, nir_phi_instr, instr, NIR_DEFINE_CAST(nir_instr_as_parallel_copy, nir_instr, nir_parallel_copy_instr, instr, type, nir_instr_type_parallel_copy) -NIR_DEFINE_CAST(nir_instr_as_debug_info, nir_instr, - nir_debug_info_instr, instr, - type, nir_instr_type_debug_info) #define NIR_DEFINE_SRC_AS_CONST(type, suffix) \ static inline type \ @@ -4516,6 +4512,8 @@ typedef struct nir_shader { unsigned printf_info_count; u_printf_info *printf_info; + + bool has_debug_info; } nir_shader; #define nir_foreach_function(func, shader) \ @@ -4740,10 +4738,6 @@ nir_phi_src *nir_phi_instr_add_src(nir_phi_instr *instr, nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader); -nir_debug_info_instr *nir_debug_info_instr_create(nir_shader *shader, - nir_debug_info_type type, - uint32_t string_length); - nir_undef_instr *nir_undef_instr_create(nir_shader *shader, unsigned num_components, unsigned bit_size); @@ -5031,6 +5025,16 @@ nir_cursor nir_instr_free_and_dce(nir_instr *instr); nir_def *nir_instr_def(nir_instr *instr); +/* Return the debug information associated with this instruction, + * assuming the parent shader has debug info. + */ +static ALWAYS_INLINE nir_instr_debug_info * +nir_instr_get_debug_info(nir_instr *instr) +{ + assert(instr->has_debug_info); + return container_of(instr, nir_instr_debug_info, instr); +} + typedef bool (*nir_foreach_def_cb)(nir_def *def, void *state); typedef bool (*nir_foreach_src_cb)(nir_src *src, void *state); static inline bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state); @@ -5053,7 +5057,6 @@ NIR_SRC_AS_(alu_instr, nir_alu_instr, nir_instr_type_alu, nir_instr_as_alu) NIR_SRC_AS_(intrinsic, nir_intrinsic_instr, nir_instr_type_intrinsic, nir_instr_as_intrinsic) NIR_SRC_AS_(deref, nir_deref_instr, nir_instr_type_deref, nir_instr_as_deref) -NIR_SRC_AS_(debug_info, nir_debug_info_instr, nir_instr_type_debug_info, nir_instr_as_debug_info) const char *nir_src_as_string(nir_src src); diff --git a/src/compiler/nir/nir_builder.c b/src/compiler/nir/nir_builder.c index 02e99e0d5fd..c30a447bf62 100644 --- a/src/compiler/nir/nir_builder.c +++ b/src/compiler/nir/nir_builder.c @@ -312,17 +312,6 @@ nir_build_tex_deref_instr(nir_builder *build, nir_texop op, return &tex->def; } -nir_def * -nir_build_string(nir_builder *build, const char *value) -{ - nir_debug_info_instr *instr = - nir_debug_info_instr_create(build->shader, nir_debug_info_string, strlen(value)); - memcpy(instr->string, value, instr->string_length); - nir_def_init(&instr->instr, &instr->def, 1, nir_get_ptr_bitsize(build->shader)); - nir_builder_instr_insert(build, &instr->instr); - return &instr->def; -} - nir_def * nir_vec_scalars(nir_builder *build, nir_scalar *comp, unsigned num_components) { @@ -385,6 +374,23 @@ nir_builder_instr_insert(nir_builder *build, nir_instr *instr) { nir_instr_insert(build->cursor, instr); + if (unlikely(build->shader->has_debug_info && + (build->cursor.option == nir_cursor_before_instr || + build->cursor.option == nir_cursor_after_instr))) { + nir_instr_debug_info *cursor_info = nir_instr_get_debug_info(build->cursor.instr); + nir_instr_debug_info *instr_info = nir_instr_get_debug_info(instr); + + if (!instr_info->line) + instr_info->line = cursor_info->line; + if (!instr_info->column) + instr_info->column = cursor_info->column; + if (!instr_info->spirv_offset) + instr_info->spirv_offset = cursor_info->spirv_offset; + if (!instr_info->filename) + instr_info->filename = cursor_info->filename; + } + + /* Move the cursor forward. */ build->cursor = nir_after_instr(instr); } diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c index 19b3b05a527..f3caef339c6 100644 --- a/src/compiler/nir/nir_clone.c +++ b/src/compiler/nir/nir_clone.c @@ -218,10 +218,49 @@ __clone_def(clone_state *state, nir_instr *ninstr, add_remap(state, ndef, def); } +/* Returns a copy of the argument string that is owned by the new shader. + * Uses remap_table avoid allocating multiple copies of the same string. + */ +static char * +clone_string(clone_state *state, const char *string) +{ + if (!string) + return NULL; + + if (!state->remap_table) + return ralloc_strdup(state->ns, string); + + struct hash_entry *entry = _mesa_hash_table_search(state->remap_table, string); + if (entry) + return entry->data; + + char *cloned = ralloc_strdup(state->ns, string); + _mesa_hash_table_insert(state->remap_table, string, cloned); + return cloned; +} + +static void +clone_debug_info(clone_state *state, nir_instr *ninstr, const nir_instr *instr) +{ + if (likely(!state->ns->has_debug_info || !instr->has_debug_info)) + return; + + nir_instr_debug_info *ndebug_info = nir_instr_get_debug_info(ninstr); + const nir_instr_debug_info *debug_info = nir_instr_get_debug_info((void *)instr); + + ndebug_info->filename = clone_string(state, debug_info->filename); + + ndebug_info->line = debug_info->line; + ndebug_info->column = debug_info->column; + ndebug_info->spirv_offset = debug_info->spirv_offset; + ndebug_info->nir_line = debug_info->nir_line; +} + static nir_alu_instr * clone_alu(clone_state *state, const nir_alu_instr *alu) { nir_alu_instr *nalu = nir_alu_instr_create(state->ns, alu->op); + clone_debug_info(state, &nalu->instr, &alu->instr); nalu->exact = alu->exact; nalu->fp_fast_math = alu->fp_fast_math; nalu->no_signed_wrap = alu->no_signed_wrap; @@ -253,6 +292,7 @@ clone_deref_instr(clone_state *state, const nir_deref_instr *deref) { nir_deref_instr *nderef = nir_deref_instr_create(state->ns, deref->deref_type); + clone_debug_info(state, &nderef->instr, &deref->instr); __clone_def(state, &nderef->instr, &nderef->def, &deref->def); @@ -300,6 +340,7 @@ clone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr) { nir_intrinsic_instr *nitr = nir_intrinsic_instr_create(state->ns, itr->intrinsic); + clone_debug_info(state, &nitr->instr, &itr->instr); unsigned num_srcs = nir_intrinsic_infos[itr->intrinsic].num_srcs; @@ -322,6 +363,7 @@ clone_load_const(clone_state *state, const nir_load_const_instr *lc) nir_load_const_instr *nlc = nir_load_const_instr_create(state->ns, lc->def.num_components, lc->def.bit_size); + clone_debug_info(state, &nlc->instr, &lc->instr); memcpy(&nlc->value, &lc->value, sizeof(*nlc->value) * lc->def.num_components); @@ -337,6 +379,7 @@ clone_ssa_undef(clone_state *state, const nir_undef_instr *sa) nir_undef_instr *nsa = nir_undef_instr_create(state->ns, sa->def.num_components, sa->def.bit_size); + clone_debug_info(state, &nsa->instr, &sa->instr); if (likely(state->remap_table)) add_remap(state, &nsa->def, &sa->def); @@ -348,6 +391,7 @@ static nir_tex_instr * clone_tex(clone_state *state, const nir_tex_instr *tex) { nir_tex_instr *ntex = nir_tex_instr_create(state->ns, tex->num_srcs); + clone_debug_info(state, &ntex->instr, &tex->instr); ntex->sampler_dim = tex->sampler_dim; ntex->dest_type = tex->dest_type; @@ -381,6 +425,7 @@ static nir_phi_instr * clone_phi(clone_state *state, const nir_phi_instr *phi, nir_block *nblk) { nir_phi_instr *nphi = nir_phi_instr_create(state->ns); + clone_debug_info(state, &nphi->instr, &phi->instr); __clone_def(state, &nphi->instr, &nphi->def, &phi->def); @@ -417,6 +462,7 @@ clone_jump(clone_state *state, const nir_jump_instr *jmp) assert(jmp->type != nir_jump_goto && jmp->type != nir_jump_goto_if); nir_jump_instr *njmp = nir_jump_instr_create(state->ns, jmp->type); + clone_debug_info(state, &njmp->instr, &jmp->instr); return njmp; } @@ -426,6 +472,7 @@ clone_call(clone_state *state, const nir_call_instr *call) { nir_function *ncallee = remap_global(state, call->callee); nir_call_instr *ncall = nir_call_instr_create(state->ns, ncallee); + clone_debug_info(state, &ncall->instr, &call->instr); for (unsigned i = 0; i < ncall->num_params; i++) __clone_src(state, ncall, &ncall->params[i], &call->params[i]); @@ -433,30 +480,6 @@ clone_call(clone_state *state, const nir_call_instr *call) return ncall; } -static nir_debug_info_instr * -clone_debug_info(clone_state *state, nir_debug_info_instr *di) -{ - nir_debug_info_instr *instr = - nir_debug_info_instr_create(state->ns, di->type, di->string_length); - - switch (di->type) { - case nir_debug_info_src_loc: - if (di->src_loc.line) - __clone_src(state, instr, &instr->src_loc.filename, &di->src_loc.filename); - instr->src_loc.line = di->src_loc.line; - instr->src_loc.column = di->src_loc.column; - instr->src_loc.spirv_offset = di->src_loc.spirv_offset; - instr->src_loc.source = di->src_loc.source; - return instr; - case nir_debug_info_string: - memcpy(instr->string, di->string, di->string_length); - __clone_def(state, &instr->instr, &instr->def, &di->def); - return instr; - } - - unreachable("Unimplemented nir_debug_info_type"); -} - static nir_instr * clone_instr(clone_state *state, const nir_instr *instr) { @@ -479,8 +502,6 @@ clone_instr(clone_state *state, const nir_instr *instr) return &clone_jump(state, nir_instr_as_jump(instr))->instr; case nir_instr_type_call: return &clone_call(state, nir_instr_as_call(instr))->instr; - case nir_instr_type_debug_info: - return &clone_debug_info(state, nir_instr_as_debug_info(instr))->instr; case nir_instr_type_parallel_copy: unreachable("Cannot clone parallel copies"); default: @@ -783,6 +804,8 @@ nir_shader_clone(void *mem_ctx, const nir_shader *s) nir_shader *ns = nir_shader_create(mem_ctx, s->info.stage, s->options, NULL); state.ns = ns; + ns->has_debug_info = s->has_debug_info; + clone_var_list(&state, &ns->variables, &s->variables); /* Go through and clone functions */ diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 2d7529a78f9..3155b0594a1 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -1110,7 +1110,6 @@ instr_is_loop_invariant(nir_instr *instr, struct divergence_state *state) switch (instr->type) { case nir_instr_type_load_const: case nir_instr_type_undef: - case nir_instr_type_debug_info: case nir_instr_type_jump: return true; case nir_instr_type_intrinsic: @@ -1146,8 +1145,6 @@ update_instr_divergence(nir_instr *instr, struct divergence_state *state) return visit_def(&nir_instr_as_undef(instr)->def, state); case nir_instr_type_deref: return visit_deref(state->shader, nir_instr_as_deref(instr), state); - case nir_instr_type_debug_info: - return false; case nir_instr_type_call: return false; case nir_instr_type_jump: diff --git a/src/compiler/nir/nir_inline_helpers.h b/src/compiler/nir/nir_inline_helpers.h index 17f2581ccee..0180cb6979d 100644 --- a/src/compiler/nir/nir_inline_helpers.h +++ b/src/compiler/nir/nir_inline_helpers.h @@ -32,13 +32,6 @@ _nir_foreach_def(nir_instr *instr, nir_foreach_def_cb cb, void *state) case nir_instr_type_undef: return cb(&nir_instr_as_undef(instr)->def, state); - case nir_instr_type_debug_info: { - nir_debug_info_instr *di = nir_instr_as_debug_info(instr); - if (di->type == nir_debug_info_string) - return cb(&di->def, state); - return true; - } - case nir_instr_type_call: case nir_instr_type_jump: return true; @@ -141,15 +134,6 @@ nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state) return true; } - case nir_instr_type_debug_info: { - nir_debug_info_instr *di = nir_instr_as_debug_info(instr); - if (di->type == nir_debug_info_src_loc && di->src_loc.line) { - if (!_nir_visit_src(&di->src_loc.filename, cb, state)) - return false; - } - return true; - } - case nir_instr_type_load_const: case nir_instr_type_undef: return true; diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c index c14c996e216..4f9dc232d8a 100644 --- a/src/compiler/nir/nir_instr_set.c +++ b/src/compiler/nir/nir_instr_set.c @@ -70,8 +70,6 @@ instr_can_rewrite(const nir_instr *instr) return nir_intrinsic_can_reorder(intr); } } - case nir_instr_type_debug_info: - return nir_instr_as_debug_info(instr)->type == nir_debug_info_string; case nir_instr_type_call: case nir_instr_type_jump: case nir_instr_type_undef: @@ -275,13 +273,6 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr) return hash; } -static uint32_t -hash_debug_info(uint32_t hash, const nir_debug_info_instr *instr) -{ - assert(instr->type == nir_debug_info_string); - return XXH32(instr->string, instr->string_length, hash); -} - /* Computes a hash of an instruction for use in a hash table. Note that this * will only work for instructions where instr_can_rewrite() returns true, and * it should return identical hashes for two instructions that are the same @@ -313,9 +304,6 @@ hash_instr(const void *data) case nir_instr_type_tex: hash = hash_tex(hash, nir_instr_as_tex(instr)); break; - case nir_instr_type_debug_info: - hash = hash_debug_info(hash, nir_instr_as_debug_info(instr)); - break; default: unreachable("Invalid instruction type"); } @@ -739,16 +727,6 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2) return true; } - case nir_instr_type_debug_info: { - nir_debug_info_instr *di1 = nir_instr_as_debug_info(instr1); - nir_debug_info_instr *di2 = nir_instr_as_debug_info(instr2); - - assert(di1->type == nir_debug_info_string); - assert(di2->type == nir_debug_info_string); - - return di1->string_length == di2->string_length && - !memcmp(di1->string, di2->string, di1->string_length); - } case nir_instr_type_call: case nir_instr_type_jump: case nir_instr_type_undef: diff --git a/src/compiler/nir/nir_opt_dce.c b/src/compiler/nir/nir_opt_dce.c index 5b2f18c2a5c..ab2642b29fd 100644 --- a/src/compiler/nir/nir_opt_dce.c +++ b/src/compiler/nir/nir_opt_dce.c @@ -96,16 +96,6 @@ is_live(BITSET_WORD *defs_live, nir_instr *instr) } return false; } - case nir_instr_type_debug_info: { - nir_debug_info_instr *di = nir_instr_as_debug_info(instr); - if (di->type == nir_debug_info_src_loc) { - nir_instr *next = nir_instr_next(instr); - return !next || next->type != nir_instr_type_debug_info; - } else if (di->type == nir_debug_info_string) { - return is_def_live(&di->def, defs_live); - } - return true; - } default: unreachable("unexpected instr type"); } diff --git a/src/compiler/nir/nir_opt_move_discards_to_top.c b/src/compiler/nir/nir_opt_move_discards_to_top.c index f6c607068e5..f28c2baad6a 100644 --- a/src/compiler/nir/nir_opt_move_discards_to_top.c +++ b/src/compiler/nir/nir_opt_move_discards_to_top.c @@ -248,7 +248,6 @@ opt_move_discards_to_top_impl(nir_function_impl *impl) case nir_instr_type_load_const: case nir_instr_type_undef: case nir_instr_type_phi: - case nir_instr_type_debug_info: /* These are all safe */ continue; diff --git a/src/compiler/nir/nir_opt_peephole_select.c b/src/compiler/nir/nir_opt_peephole_select.c index e0601d29c51..e6422214379 100644 --- a/src/compiler/nir/nir_opt_peephole_select.c +++ b/src/compiler/nir/nir_opt_peephole_select.c @@ -73,7 +73,6 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count, case nir_instr_type_phi: case nir_instr_type_undef: case nir_instr_type_tex: - case nir_instr_type_debug_info: break; case nir_instr_type_intrinsic: { @@ -273,9 +272,6 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count, break; } - case nir_instr_type_debug_info: - break; - default: return false; } diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 20aa9acedb3..6efcda51f44 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -80,7 +80,9 @@ typedef struct { */ unsigned padding_for_no_dest; - nir_debug_info_instr **debug_info; + bool gather_debug_info; + + nir_instr_debug_info last_debug_info; } print_state; static void @@ -2009,33 +2011,37 @@ print_parallel_copy_instr(nir_parallel_copy_instr *instr, print_state *state) } } -static void -print_debug_info_instr(nir_debug_info_instr *instr, print_state *state) -{ - FILE *fp = state->fp; - - switch (instr->type) { - case nir_debug_info_src_loc: - fprintf(fp, "// 0x%x", instr->src_loc.spirv_offset); - if (instr->src_loc.line) - fprintf(fp, " %s:%u:%u", nir_src_as_string(instr->src_loc.filename), instr->src_loc.line, instr->src_loc.column); - return; - case nir_debug_info_string: - return; /* Strings are printed for their uses. */ - } - - unreachable("Unimplemented nir_debug_info_type"); -} - static void print_instr(const nir_instr *instr, print_state *state, unsigned tabs) { FILE *fp = state->fp; - if (state->debug_info) { - nir_debug_info_instr *di = state->debug_info[instr->index]; - if (di) - di->src_loc.column = (uint32_t)ftell(fp); + if (state->gather_debug_info) { + nir_instr_debug_info *debug_info = nir_instr_get_debug_info((nir_instr *)instr); + debug_info->nir_line = (uint32_t)ftell(fp); + } + + if (state->shader->has_debug_info) { + nir_instr_debug_info *debug_info = nir_instr_get_debug_info((nir_instr *)instr); + + bool changed = state->last_debug_info.spirv_offset != debug_info->spirv_offset; + changed |= state->last_debug_info.nir_line != debug_info->nir_line; + + if (changed && debug_info->spirv_offset) { + print_indentation(tabs, fp); + + fprintf(fp, "// 0x%x", debug_info->spirv_offset); + + if (debug_info->filename) + fprintf(fp, " %s:%u:%u", debug_info->filename, debug_info->line, debug_info->column); + + if (debug_info->nir_line) + fprintf(fp, " nir:%u", debug_info->nir_line); + + fprintf(fp, "\n"); + } + + state->last_debug_info = *debug_info; } print_indentation(tabs, fp); @@ -2081,10 +2087,6 @@ print_instr(const nir_instr *instr, print_state *state, unsigned tabs) print_parallel_copy_instr(nir_instr_as_parallel_copy(instr), state); break; - case nir_instr_type_debug_info: - print_debug_info_instr(nir_instr_as_debug_info(instr), state); - break; - default: unreachable("Invalid instruction type"); break; @@ -2120,7 +2122,6 @@ block_has_instruction_with_dest(nir_block *block) case nir_instr_type_jump: case nir_instr_type_call: - case nir_instr_type_debug_info: /* Doesn't define a new value. */ break; } @@ -2730,13 +2731,13 @@ print_shader_info(const struct shader_info *info, FILE *fp) static void _nir_print_shader_annotated(nir_shader *shader, FILE *fp, struct hash_table *annotations, - nir_debug_info_instr **debug_info) + bool gather_debug_info) { print_state state; init_print_state(&state, shader, fp); - state.def_prefix = debug_info ? "ssa_" : "%"; + state.def_prefix = gather_debug_info ? "ssa_" : "%"; state.annotations = annotations; - state.debug_info = debug_info; + state.gather_debug_info = gather_debug_info; print_shader_info(&shader->info, fp); @@ -2781,7 +2782,7 @@ void nir_print_shader_annotated(nir_shader *shader, FILE *fp, struct hash_table *annotations) { - _nir_print_shader_annotated(shader, fp, annotations, NULL); + _nir_print_shader_annotated(shader, fp, annotations, false); } void @@ -2793,14 +2794,14 @@ nir_print_shader(nir_shader *shader, FILE *fp) static char * _nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx, - nir_debug_info_instr **debug_info) + bool gather_debug_info) { char *stream_data = NULL; size_t stream_size = 0; struct u_memstream mem; if (u_memstream_open(&mem, &stream_data, &stream_size)) { FILE *const stream = u_memstream_get(&mem); - _nir_print_shader_annotated(nir, stream, annotations, debug_info); + _nir_print_shader_annotated(nir, stream, annotations, gather_debug_info); u_memstream_close(&mem); } @@ -2816,7 +2817,7 @@ _nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, vo char * nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx) { - return _nir_shader_as_str_annotated(nir, annotations, mem_ctx, NULL); + return _nir_shader_as_str_annotated(nir, annotations, mem_ctx, false); } char * @@ -2883,67 +2884,25 @@ nir_log_shader_annotated_tagged(enum mesa_log_level level, const char *tag, char * nir_shader_gather_debug_info(nir_shader *shader, const char *filename, uint32_t first_line) { - uint32_t instr_count = 0; - nir_foreach_function_impl(impl, shader) { - nir_foreach_block(block, impl) { - nir_foreach_instr(instr, block) { - instr->index = instr_count; - instr_count++; - } - } - } + char *str = _nir_shader_as_str_annotated(shader, NULL, NULL, shader->has_debug_info); - if (!instr_count) - return nir_shader_as_str(shader, NULL); - - nir_debug_info_instr **debug_info = rzalloc_array(shader, nir_debug_info_instr *, instr_count); - - instr_count = 0; - nir_foreach_function_impl(impl, shader) { - nir_builder b = nir_builder_at(nir_before_cf_list(&impl->body)); - nir_def *filename_def = nir_build_string(&b, filename); - - nir_foreach_block(block, impl) { - nir_foreach_instr_safe(instr, block) { - if (instr->type == nir_instr_type_debug_info || - instr->type == nir_instr_type_phi) - continue; - - nir_debug_info_instr *di = nir_debug_info_instr_create(shader, nir_debug_info_src_loc, 0); - di->src_loc.filename = nir_src_for_ssa(filename_def); - di->src_loc.source = nir_debug_info_nir; - debug_info[instr_count++] = di; - } - } - } - - char *str = _nir_shader_as_str_annotated(shader, NULL, NULL, debug_info); + if (!shader->has_debug_info) + return str; uint32_t line = first_line; uint32_t character_index = 0; - for (uint32_t i = 0; i < instr_count; i++) { - nir_debug_info_instr *di = debug_info[i]; - if (!di) - continue; - - while (character_index < di->src_loc.column) { - if (str[character_index] == '\n') - line++; - character_index++; - } - - di->src_loc.line = line; - di->src_loc.column = 0; - } - - instr_count = 0; nir_foreach_function_impl(impl, shader) { nir_foreach_block(block, impl) { nir_foreach_instr_safe(instr, block) { - if (instr->type != nir_instr_type_debug_info && - instr->type != nir_instr_type_phi) - nir_instr_insert_before(instr, &debug_info[instr_count++]->instr); + nir_instr_debug_info *di = nir_instr_get_debug_info(instr); + while (character_index < di->nir_line) { + if (str[character_index] == '\n') + line++; + character_index++; + } + + di->nir_line = line; } } } diff --git a/src/compiler/nir/nir_propagate_invariant.c b/src/compiler/nir/nir_propagate_invariant.c index 9a6e91f9ef6..abf9e5fb664 100644 --- a/src/compiler/nir/nir_propagate_invariant.c +++ b/src/compiler/nir/nir_propagate_invariant.c @@ -126,7 +126,6 @@ propagate_invariant_instr(nir_instr *instr, struct set *invariants) case nir_instr_type_jump: case nir_instr_type_undef: case nir_instr_type_load_const: - case nir_instr_type_debug_info: break; /* Nothing to do */ case nir_instr_type_phi: { diff --git a/src/compiler/nir/nir_schedule.c b/src/compiler/nir/nir_schedule.c index 1439b024a1c..74fda70b50d 100644 --- a/src/compiler/nir/nir_schedule.c +++ b/src/compiler/nir/nir_schedule.c @@ -462,7 +462,6 @@ nir_schedule_calculate_deps(nir_deps_state *state, nir_schedule_node *n) case nir_instr_type_load_const: case nir_instr_type_alu: case nir_instr_type_deref: - case nir_instr_type_debug_info: break; case nir_instr_type_tex: @@ -1096,7 +1095,6 @@ nir_schedule_get_delay(nir_schedule_scoreboard *scoreboard, nir_instr *instr) case nir_instr_type_parallel_copy: case nir_instr_type_call: case nir_instr_type_phi: - case nir_instr_type_debug_info: return 1; case nir_instr_type_intrinsic: diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index 933371669da..66a7af95f31 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -64,6 +64,7 @@ typedef struct { /* Don't write optional data such as variable names. */ bool strip; + bool debug_info; } write_ctx; typedef struct { @@ -87,6 +88,8 @@ typedef struct { const struct glsl_type *last_type; const struct glsl_type *last_interface_type; struct nir_variable_data last_var_data; + + struct hash_table *strings; } read_ctx; static void @@ -615,7 +618,7 @@ write_def(write_ctx *ctx, const nir_def *def, union packed_instr header, * instruction that is also ALU. If it is, we don't have to write * the current header. This is a typical occurence after scalarization. */ - if (instr_type == nir_instr_type_alu) { + if (instr_type == nir_instr_type_alu && likely(!ctx->debug_info)) { bool equal_header = false; if (ctx->last_instr_type == nir_instr_type_alu) { @@ -1603,60 +1606,44 @@ read_call(read_ctx *ctx) } static void -write_debug_info(write_ctx *ctx, const nir_debug_info_instr *di) +write_debug_info(write_ctx *ctx, const nir_instr *instr) { - union packed_instr header; - header.u32 = 0; + nir_instr_debug_info *debug_info = nir_instr_get_debug_info((void *)instr); - header.debug_info.instr_type = nir_instr_type_debug_info; - header.debug_info.type = di->type; - header.debug_info.string_length = di->string_length; + blob_write_uint32(ctx->blob, debug_info->line); + blob_write_uint32(ctx->blob, debug_info->column); + blob_write_uint32(ctx->blob, debug_info->spirv_offset); - switch (di->type) { - case nir_debug_info_src_loc: - blob_write_uint32(ctx->blob, header.u32); - blob_write_uint32(ctx->blob, di->src_loc.line); - blob_write_uint32(ctx->blob, di->src_loc.column); - blob_write_uint32(ctx->blob, di->src_loc.spirv_offset); - blob_write_uint8(ctx->blob, di->src_loc.source); - if (di->src_loc.line) - write_src(ctx, &di->src_loc.filename); - return; - case nir_debug_info_string: - write_def(ctx, &di->def, header, di->instr.type); - blob_write_bytes(ctx->blob, di->string, di->string_length); - return; - } + blob_write_uint32(ctx->blob, debug_info->nir_line); - unreachable("Unimplemented nir_debug_info_type"); + blob_write_uint8(ctx->blob, !!debug_info->filename); + if (debug_info->filename) + blob_write_string(ctx->blob, debug_info->filename); } -static nir_debug_info_instr * -read_debug_info(read_ctx *ctx, union packed_instr header) +static void +read_debug_info(read_ctx *ctx, nir_instr_debug_info *debug_info) { - nir_debug_info_type type = header.debug_info.type; + memset(debug_info, 0, sizeof(*debug_info)); - switch (type) { - case nir_debug_info_src_loc: { - nir_debug_info_instr *di = nir_debug_info_instr_create(ctx->nir, type, 0); - di->src_loc.line = blob_read_uint32(ctx->blob); - di->src_loc.column = blob_read_uint32(ctx->blob); - di->src_loc.spirv_offset = blob_read_uint32(ctx->blob); - di->src_loc.source = blob_read_uint8(ctx->blob); - if (di->src_loc.line) - read_src(ctx, &di->src_loc.filename); - return di; - } - case nir_debug_info_string: { - nir_debug_info_instr *di = - nir_debug_info_instr_create(ctx->nir, type, header.debug_info.string_length); - read_def(ctx, &di->def, &di->instr, header); - memcpy(di->string, blob_read_bytes(ctx->blob, di->string_length), di->string_length); - return di; - } - } + debug_info->line = blob_read_uint32(ctx->blob); + debug_info->column = blob_read_uint32(ctx->blob); + debug_info->spirv_offset = blob_read_uint32(ctx->blob); - unreachable("Unimplemented nir_debug_info_type"); + debug_info->nir_line = blob_read_uint32(ctx->blob); + + bool has_filename = blob_read_uint8(ctx->blob); + if (has_filename) { + const char *filename = blob_read_string(ctx->blob); + + struct hash_entry *entry = _mesa_hash_table_search(ctx->strings, filename); + if (entry) { + debug_info->filename = entry->data; + } else { + debug_info->filename = ralloc_strdup(ctx->nir, filename); + _mesa_hash_table_insert(ctx->strings, filename, debug_info->filename); + } + } } static void @@ -1665,6 +1652,9 @@ write_instr(write_ctx *ctx, const nir_instr *instr) /* We have only 4 bits for the instruction type. */ assert(instr->type < 16); + if (unlikely(ctx->debug_info)) + write_debug_info(ctx, instr); + switch (instr->type) { case nir_instr_type_alu: write_alu(ctx, nir_instr_as_alu(instr)); @@ -1694,9 +1684,6 @@ write_instr(write_ctx *ctx, const nir_instr *instr) blob_write_uint32(ctx->blob, instr->type); write_call(ctx, nir_instr_as_call(instr)); break; - case nir_instr_type_debug_info: - write_debug_info(ctx, nir_instr_as_debug_info(instr)); - break; case nir_instr_type_parallel_copy: unreachable("Cannot write parallel copies"); default: @@ -1708,6 +1695,10 @@ write_instr(write_ctx *ctx, const nir_instr *instr) static unsigned read_instr(read_ctx *ctx, nir_block *block) { + nir_instr_debug_info debug_info; + if (unlikely(ctx->nir->has_debug_info)) + read_debug_info(ctx, &debug_info); + STATIC_ASSERT(sizeof(union packed_instr) == 4); union packed_instr header; header.u32 = blob_read_uint32(ctx->blob); @@ -1747,15 +1738,17 @@ read_instr(read_ctx *ctx, nir_block *block) case nir_instr_type_call: instr = &read_call(ctx)->instr; break; - case nir_instr_type_debug_info: - instr = &read_debug_info(ctx, header)->instr; - break; case nir_instr_type_parallel_copy: unreachable("Cannot read parallel copies"); default: unreachable("bad instr type"); } + if (unlikely(ctx->nir->has_debug_info)) { + nir_instr_debug_info *dst = nir_instr_get_debug_info(instr); + memcpy(dst, &debug_info, offsetof(nir_instr_debug_info, instr)); + } + nir_instr_insert_after_block(block, instr); return 1; } @@ -2101,6 +2094,12 @@ read_xfb_info(read_ctx *ctx) return xfb; } +enum nir_serialize_shader_flags { + NIR_SERIALIZE_SHADER_NAME = 1 << 0, + NIR_SERIALIZE_SHADER_LABEL = 1 << 1, + NIR_SERIALIZE_DEBUG_INFO = 1 << 2, +}; + /** * Serialize NIR into a binary blob. * @@ -2116,17 +2115,22 @@ nir_serialize(struct blob *blob, const nir_shader *nir, bool strip) ctx.blob = blob; ctx.nir = nir; ctx.strip = strip; + ctx.debug_info = nir->has_debug_info && !strip; util_dynarray_init(&ctx.phi_fixups, NULL); size_t idx_size_offset = blob_reserve_uint32(blob); struct shader_info info = nir->info; - uint32_t strings = 0; + + enum nir_serialize_shader_flags flags = 0; if (!strip && info.name) - strings |= 0x1; + flags |= NIR_SERIALIZE_SHADER_NAME; if (!strip && info.label) - strings |= 0x2; - blob_write_uint32(blob, strings); + flags |= NIR_SERIALIZE_SHADER_LABEL; + if (ctx.debug_info) + flags |= NIR_SERIALIZE_DEBUG_INFO; + blob_write_uint32(blob, flags); + if (!strip && info.name) blob_write_string(blob, info.name); if (!strip && info.label) @@ -2176,15 +2180,19 @@ nir_deserialize(void *mem_ctx, ctx.idx_table_len = blob_read_uint32(blob); ctx.idx_table = calloc(ctx.idx_table_len, sizeof(uintptr_t)); - uint32_t strings = blob_read_uint32(blob); - char *name = (strings & 0x1) ? blob_read_string(blob) : NULL; - char *label = (strings & 0x2) ? blob_read_string(blob) : NULL; + enum nir_serialize_shader_flags flags = blob_read_uint32(blob); + char *name = (flags & NIR_SERIALIZE_SHADER_NAME) ? blob_read_string(blob) : NULL; + char *label = (flags & NIR_SERIALIZE_SHADER_LABEL) ? blob_read_string(blob) : NULL; struct shader_info info; blob_copy_bytes(blob, (uint8_t *)&info, sizeof(info)); ctx.nir = nir_shader_create(mem_ctx, info.stage, options, NULL); + ctx.nir->has_debug_info = !!(flags & NIR_SERIALIZE_DEBUG_INFO); + if (ctx.nir->has_debug_info) + ctx.strings = _mesa_hash_table_create(NULL, _mesa_hash_string, _mesa_key_string_equal); + info.name = name ? ralloc_strdup(ctx.nir, name) : NULL; info.label = label ? ralloc_strdup(ctx.nir, label) : NULL; @@ -2223,6 +2231,7 @@ nir_deserialize(void *mem_ctx, } free(ctx.idx_table); + _mesa_hash_table_destroy(ctx.strings, NULL); nir_validate_shader(ctx.nir, "after deserialize"); diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 7a6a89d8d45..5504c8d7cee 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -1156,9 +1156,6 @@ validate_instr(nir_instr *instr, validate_state *state) validate_jump_instr(nir_instr_as_jump(instr), state); break; - case nir_instr_type_debug_info: - break; - default: validate_assert(state, !"Invalid ALU instruction type"); break; diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index e1851672fa5..0c19ddbc67b 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -6119,31 +6119,27 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) { if (b->options->debug_info) { - nir_debug_info_instr *instr = - nir_debug_info_instr_create(b->shader, nir_debug_info_src_loc, 0); - instr->src_loc.spirv_offset = b->spirv_offset; - instr->src_loc.source = nir_debug_info_spirv; + /* Insert a nop to attach debug info to the cursor of the builder. + * This should not affect compilation since the nop will be eliminated + * in spirv_to_nir. + */ + nir_intrinsic_instr *nop = nir_nop(&b->nb); + + nir_instr_debug_info *info = nir_instr_get_debug_info(&nop->instr); + info->spirv_offset = b->spirv_offset; if (b->file) { - nir_def *filename; struct hash_entry *he = _mesa_hash_table_search(b->strings, b->file); if (he) { - filename = he->data; + info->filename = he->data; } else { - nir_builder _b = nir_builder_at(nir_before_cf_list(&b->nb.impl->body)); - filename = nir_build_string(&_b, b->file); - _mesa_hash_table_insert(b->strings, b->file, filename); + info->filename = ralloc_strdup(b->shader, b->file); + _mesa_hash_table_insert(b->strings, b->file, info->filename); } - instr->src_loc.filename = nir_src_for_ssa(filename); - /* Make sure line is at least 1 since 0 is reserved for spirv_offset-only - * source locations. - */ - instr->src_loc.line = MAX2(b->line, 1); - instr->src_loc.column = b->col; + info->line = b->line; + info->column = b->col; } - - nir_builder_instr_insert(&b->nb, &instr->instr); } switch (opcode) { @@ -6929,6 +6925,7 @@ spirv_to_nir(const uint32_t *words, size_t word_count, b->shader->info.subgroup_size = options->subgroup_size; b->shader->info.float_controls_execution_mode = options->float_controls_execution_mode; b->shader->info.cs.shader_index = options->shader_index; + b->shader->has_debug_info = options->debug_info; _mesa_blake3_compute(words, word_count * sizeof(uint32_t), b->shader->info.source_blake3); /* Skip the SPIR-V header, handled at vtn_create_builder */ @@ -7167,6 +7164,9 @@ spirv_to_nir(const uint32_t *words, size_t word_count, nir_shader *shader = b->shader; ralloc_free(b); + if (shader->has_debug_info) + nir_print_shader(shader, stdout); + return shader; } diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 7200250fed3..c97132c2b7b 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -4286,7 +4286,6 @@ emit_instr(struct ir3_context *ctx, nir_instr *instr) break; case nir_instr_type_call: case nir_instr_type_parallel_copy: - case nir_instr_type_debug_info: ir3_context_error(ctx, "Unhandled NIR instruction type: %d\n", instr->type); break; @@ -4463,7 +4462,6 @@ instr_can_be_predicated(nir_instr *instr) return true; case nir_instr_type_call: case nir_instr_type_jump: - case nir_instr_type_debug_info: return false; case nir_instr_type_intrinsic: { nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 5fc74d604fd..83729d597bb 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4173,9 +4173,6 @@ emit_block(struct ntv_context *ctx, struct nir_block *block) case nir_instr_type_deref: emit_deref(ctx, nir_instr_as_deref(instr)); break; - case nir_instr_type_debug_info: - unreachable("nir_instr_type_debug_info not supported"); - break; } } }