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 <boris.brezillon@collabora.com>
Reviewed-by: Bill Kristiansen <billkris@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14399>
This commit is contained in:
Jesse Natalie
2022-01-03 05:13:39 -08:00
committed by Marge Bot
parent e5f353f2f2
commit 72812fe9b5
4 changed files with 113 additions and 71 deletions
+6 -1
View File
@@ -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);
+84 -50
View File
@@ -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);
}
+14 -6
View File
@@ -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,
+9 -14
View File
@@ -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)