From 72812fe9b5a1f26da136faf81d80a6bcf63c532b Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 3 Jan 2022 05:13:39 -0800 Subject: [PATCH] microsoft/compiler: Support emitting multiple functions into a DXIL module The instruction and block lists are moved into a new "function definition" struct, and the DXIL module tracks one at a time for adding instructions into. The NIR side still only emits the main function here though. Reviewed-by: Boris Brezillon Reviewed-by: Bill Kristiansen Part-of: --- src/microsoft/compiler/dxil_dump.c | 7 +- src/microsoft/compiler/dxil_module.c | 134 +++++++++++++++++---------- src/microsoft/compiler/dxil_module.h | 20 ++-- src/microsoft/compiler/nir_to_dxil.c | 23 ++--- 4 files changed, 113 insertions(+), 71 deletions(-) diff --git a/src/microsoft/compiler/dxil_dump.c b/src/microsoft/compiler/dxil_dump.c index 2ba3196f89e..225019b98a7 100644 --- a/src/microsoft/compiler/dxil_dump.c +++ b/src/microsoft/compiler/dxil_dump.c @@ -97,7 +97,12 @@ dxil_dump_module(struct dxil_dumper *d, struct dxil_module *m) dump_funcs(d, &m->func_list); dump_attr_set_list(d, &m->attr_set_list); dump_constants(d, &m->const_list); - dump_instrs(d, &m->instr_list); + + struct dxil_func_def *func_def; + LIST_FOR_EACH_ENTRY(func_def, &m->func_def_list, head) { + dump_instrs(d, &func_def->instr_list); + } + dump_mdnodes(d, &m->mdnode_list); dump_named_nodes(d, &m->md_named_node_list); dump_io_signatures(d->buf, m); diff --git a/src/microsoft/compiler/dxil_module.c b/src/microsoft/compiler/dxil_module.c index a7df7988862..c5b4100630a 100644 --- a/src/microsoft/compiler/dxil_module.c +++ b/src/microsoft/compiler/dxil_module.c @@ -45,17 +45,15 @@ dxil_module_init(struct dxil_module *m, void *ralloc_ctx) list_inithead(&m->type_list); list_inithead(&m->func_list); + list_inithead(&m->func_def_list); list_inithead(&m->attr_set_list); list_inithead(&m->gvar_list); list_inithead(&m->const_list); - list_inithead(&m->instr_list); list_inithead(&m->mdnode_list); list_inithead(&m->md_named_node_list); m->functions = rzalloc(ralloc_ctx, struct rb_tree); rb_tree_init(m->functions); - - m->curr_block = 0; } void @@ -1842,7 +1840,7 @@ dxil_add_global_ptr_var(struct dxil_module *m, const char *name, as, align, value); } -static struct dxil_func * +static const struct dxil_func * add_function(struct dxil_module *m, const char *name, const struct dxil_type *type, bool decl, unsigned attr_set) @@ -1869,11 +1867,33 @@ add_function(struct dxil_module *m, const char *name, return func; } -const struct dxil_func * +struct dxil_func_def * dxil_add_function_def(struct dxil_module *m, const char *name, - const struct dxil_type *type) + const struct dxil_type *type, unsigned num_blocks) { - return add_function(m, name, type, false, 0); + struct dxil_func_def *def = ralloc_size(m->ralloc_ctx, sizeof(struct dxil_func_def)); + + def->func = add_function(m, name, type, false, 0); + if (!def->func) + return NULL; + + list_inithead(&def->instr_list); + def->curr_block = 0; + + assert(num_blocks > 0); + def->basic_block_ids = rzalloc_array(m->ralloc_ctx, int, + num_blocks); + if (!def->basic_block_ids) + return NULL; + + for (int i = 0; i < num_blocks; ++i) + def->basic_block_ids[i] = -1; + def->num_basic_block_ids = num_blocks; + + list_addtail(&def->head, &m->func_def_list); + m->cur_emitting_func = def; + + return def; } static unsigned @@ -2567,7 +2587,7 @@ create_instr(struct dxil_module *m, enum instr_type type, ret->value.id = -1; ret->value.type = ret_type; ret->has_value = false; - list_addtail(&ret->head, &m->instr_list); + list_addtail(&ret->head, &m->cur_emitting_func->instr_list); } return ret; } @@ -2682,7 +2702,7 @@ dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond, instr->br.cond = cond; instr->br.succ[0] = true_block; instr->br.succ[1] = false_block; - m->curr_block++; + m->cur_emitting_func->curr_block++; return true; } @@ -2787,7 +2807,7 @@ dxil_emit_ret_void(struct dxil_module *m) return false; instr->ret.value = NULL; - m->curr_block++; + m->cur_emitting_func->curr_block++; return true; } @@ -3055,25 +3075,25 @@ emit_cast(struct dxil_module *m, struct dxil_instr *instr) } static bool -emit_branch(struct dxil_module *m, struct dxil_instr *instr) +emit_branch(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr) { assert(instr->type == INSTR_BR); - assert(instr->br.succ[0] < m->num_basic_block_ids); - assert(m->basic_block_ids[instr->br.succ[0]] >= 0); + assert(instr->br.succ[0] < func->num_basic_block_ids); + assert(func->basic_block_ids[instr->br.succ[0]] >= 0); if (!instr->br.cond) { /* unconditional branch */ - uint64_t succ = m->basic_block_ids[instr->br.succ[0]]; + uint64_t succ = func->basic_block_ids[instr->br.succ[0]]; return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, &succ, 1); } /* conditional branch */ assert(instr->value.id > instr->br.cond->id); - assert(instr->br.succ[1] < m->num_basic_block_ids); - assert(m->basic_block_ids[instr->br.succ[1]] >= 0); + assert(instr->br.succ[1] < func->num_basic_block_ids); + assert(func->basic_block_ids[instr->br.succ[1]] >= 0); uint64_t data[] = { - m->basic_block_ids[instr->br.succ[0]], - m->basic_block_ids[instr->br.succ[1]], + func->basic_block_ids[instr->br.succ[0]], + func->basic_block_ids[instr->br.succ[1]], instr->value.id - instr->br.cond->id }; return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_BR, @@ -3081,7 +3101,7 @@ emit_branch(struct dxil_module *m, struct dxil_instr *instr) } static bool -emit_phi(struct dxil_module *m, struct dxil_instr *instr) +emit_phi(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr) { assert(instr->type == INSTR_PHI); uint64_t data[128]; @@ -3090,9 +3110,9 @@ emit_phi(struct dxil_module *m, struct dxil_instr *instr) for (int i = 0; i < instr->phi.num_incoming; ++i) { int64_t value_delta = instr->value.id - instr->phi.incoming[i].value->id; data[1 + i * 2] = encode_signed(value_delta); - assert(instr->phi.incoming[i].block < m->num_basic_block_ids); - assert(m->basic_block_ids[instr->phi.incoming[i].block] >= 0); - data[1 + i * 2 + 1] = m->basic_block_ids[instr->phi.incoming[i].block]; + assert(instr->phi.incoming[i].block < func->num_basic_block_ids); + assert(func->basic_block_ids[instr->phi.incoming[i].block] >= 0); + data[1 + i * 2 + 1] = func->basic_block_ids[instr->phi.incoming[i].block]; } return emit_record_no_abbrev(&m->buf, FUNC_CODE_INST_PHI, data, 1 + 2 * instr->phi.num_incoming); @@ -3266,7 +3286,7 @@ emit_atomicrmw(struct dxil_module *m, struct dxil_instr *instr) } static bool -emit_instr(struct dxil_module *m, struct dxil_instr *instr) +emit_instr(struct dxil_module *m, struct dxil_func_def *func, struct dxil_instr *instr) { switch (instr->type) { case INSTR_BINOP: @@ -3282,10 +3302,10 @@ emit_instr(struct dxil_module *m, struct dxil_instr *instr) return emit_cast(m, instr); case INSTR_BR: - return emit_branch(m, instr); + return emit_branch(m, func, instr); case INSTR_PHI: - return emit_phi(m, instr); + return emit_phi(m, func, instr); case INSTR_CALL: return emit_call(m, instr); @@ -3320,14 +3340,14 @@ emit_instr(struct dxil_module *m, struct dxil_instr *instr) } static bool -emit_function(struct dxil_module *m) +emit_function(struct dxil_module *m, struct dxil_func_def *func) { if (!enter_subblock(m, DXIL_FUNCTION_BLOCK, 4) || - !emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, m->curr_block)) + !emit_record_int(m, FUNC_CODE_DECLAREBLOCKS, func->curr_block)) return false; - list_for_each_entry(struct dxil_instr, instr, &m->instr_list, head) { - if (!emit_instr(m, instr)) + list_for_each_entry(struct dxil_instr, instr, &func->instr_list, head) { + if (!emit_instr(m, func, instr)) return false; } @@ -3354,11 +3374,18 @@ assign_values(struct dxil_module *m) c->value.id = next_value_id++; } - struct dxil_instr *instr; - LIST_FOR_EACH_ENTRY(instr, &m->instr_list, head) { - instr->value.id = next_value_id; - if (instr->has_value) - next_value_id++; + /* All functions start at this ID */ + unsigned value_id_at_functions_start = next_value_id; + + struct dxil_func_def *func_def; + LIST_FOR_EACH_ENTRY(func_def, &m->func_def_list, head) { + struct dxil_instr *instr; + next_value_id = value_id_at_functions_start; + LIST_FOR_EACH_ENTRY(instr, &func_def->instr_list, head) { + instr->value.id = next_value_id; + if (instr->has_value) + next_value_id++; + } } } @@ -3366,20 +3393,27 @@ bool dxil_emit_module(struct dxil_module *m) { assign_values(m); - return dxil_buffer_emit_bits(&m->buf, 'B', 8) && - dxil_buffer_emit_bits(&m->buf, 'C', 8) && - dxil_buffer_emit_bits(&m->buf, 0xC0, 8) && - dxil_buffer_emit_bits(&m->buf, 0xDE, 8) && - enter_subblock(m, DXIL_MODULE, 3) && - emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) && - emit_blockinfo(m) && - emit_attrib_group_table(m) && - emit_attribute_table(m) && - emit_type_table(m) && - emit_module_info(m) && - emit_module_consts(m) && - emit_metadata(m) && - emit_value_symbol_table(m) && - emit_function(m) && - exit_block(m); + if (!(dxil_buffer_emit_bits(&m->buf, 'B', 8) && + dxil_buffer_emit_bits(&m->buf, 'C', 8) && + dxil_buffer_emit_bits(&m->buf, 0xC0, 8) && + dxil_buffer_emit_bits(&m->buf, 0xDE, 8) && + enter_subblock(m, DXIL_MODULE, 3) && + emit_record_int(m, DXIL_MODULE_CODE_VERSION, 1) && + emit_blockinfo(m) && + emit_attrib_group_table(m) && + emit_attribute_table(m) && + emit_type_table(m) && + emit_module_info(m) && + emit_module_consts(m) && + emit_metadata(m) && + emit_value_symbol_table(m))) + return false; + + struct dxil_func_def *func; + LIST_FOR_EACH_ENTRY(func, &m->func_def_list, head) { + if (!emit_function(m, func)) + return false; + } + + return exit_block(m); } diff --git a/src/microsoft/compiler/dxil_module.h b/src/microsoft/compiler/dxil_module.h index 057a5d0cb65..08021082099 100644 --- a/src/microsoft/compiler/dxil_module.h +++ b/src/microsoft/compiler/dxil_module.h @@ -162,6 +162,16 @@ struct dxil_shader_info { unsigned has_per_sample_input:1; }; +struct dxil_func_def { + struct list_head head; + const struct dxil_func *func; + + struct list_head instr_list; + int *basic_block_ids; /* maps from "user" ids to LLVM ids */ + size_t num_basic_block_ids; + unsigned curr_block; +}; + struct dxil_module { void *ralloc_ctx; enum dxil_shader_kind shader_kind; @@ -195,8 +205,8 @@ struct dxil_module { struct list_head type_list; struct list_head gvar_list; struct list_head func_list; + struct list_head func_def_list; struct list_head attr_set_list; - struct list_head instr_list; struct list_head const_list; struct list_head mdnode_list; struct list_head md_named_node_list; @@ -207,9 +217,7 @@ struct dxil_module { struct rb_tree *functions; - int *basic_block_ids; /* maps from "user" ids to LLVM ids */ - size_t num_basic_block_ids; - unsigned curr_block; + struct dxil_func_def *cur_emitting_func; }; struct dxil_instr; @@ -233,9 +241,9 @@ dxil_add_global_ptr_var(struct dxil_module *m, const char *name, enum dxil_address_space as, int align, const struct dxil_value *value); -const struct dxil_func * +struct dxil_func_def * dxil_add_function_def(struct dxil_module *m, const char *name, - const struct dxil_type *type); + const struct dxil_type *type, unsigned num_blocks); const struct dxil_func * dxil_add_function_decl(struct dxil_module *m, const char *name, diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index 5357a34d423..dc8907ccded 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -1432,11 +1432,10 @@ emit_metadata(struct ntd_context *ctx) !emit_dx_shader_model(&ctx->mod)) return false; - const struct dxil_type *void_type = dxil_module_get_void_type(&ctx->mod); - const struct dxil_type *main_func_type = dxil_module_add_function_type(&ctx->mod, void_type, NULL, 0); - const struct dxil_func *main_func = dxil_add_function_def(&ctx->mod, "main", main_func_type); - if (!main_func) + const struct dxil_func_def *main_func_def = ctx->mod.cur_emitting_func; + if (!main_func_def) return false; + const struct dxil_func *main_func = main_func_def->func; const struct dxil_mdnode *resources_node = emit_resources(ctx); @@ -4612,8 +4611,8 @@ static bool emit_instr(struct ntd_context *ctx, struct nir_instr* instr) static bool emit_block(struct ntd_context *ctx, struct nir_block *block) { - assert(block->index < ctx->mod.num_basic_block_ids); - ctx->mod.basic_block_ids[block->index] = ctx->mod.curr_block; + assert(block->index < ctx->mod.cur_emitting_func->num_basic_block_ids); + ctx->mod.cur_emitting_func->basic_block_ids[block->index] = ctx->mod.cur_emitting_func->curr_block; nir_foreach_instr(instr, block) { TRACE_CONVERSION(instr); @@ -4999,16 +4998,12 @@ emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts) nir_function_impl *entry = nir_shader_get_entrypoint(ctx->shader); nir_metadata_require(entry, nir_metadata_block_index); - assert(entry->num_blocks > 0); - ctx->mod.basic_block_ids = rzalloc_array(ctx->ralloc_ctx, int, - entry->num_blocks); - if (!ctx->mod.basic_block_ids) + const struct dxil_type *void_type = dxil_module_get_void_type(&ctx->mod); + const struct dxil_type *main_func_type = dxil_module_add_function_type(&ctx->mod, void_type, NULL, 0); + struct dxil_func_def *main_func = dxil_add_function_def(&ctx->mod, "main", main_func_type, entry->num_blocks); + if (!main_func) return false; - for (int i = 0; i < entry->num_blocks; ++i) - ctx->mod.basic_block_ids[i] = -1; - ctx->mod.num_basic_block_ids = entry->num_blocks; - ctx->defs = rzalloc_array(ctx->ralloc_ctx, struct dxil_def, entry->ssa_alloc); if (!ctx->defs)