lima/ppir: add control flow support

This commit adds support for nir_jump_instr, if and loop
nir_cf_nodes.

Tested-by: Andreas Baierl <ichgeh@imkreisrum.de>
Reviewed-by: Qiang Yu <yuq825@gmail.com>
Reviewed-by: Erico Nunes <nunes.erico@gmail.com>
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
This commit is contained in:
Vasily Khoruzhick 2019-08-18 23:37:23 -07:00
parent 1cdf585613
commit 28d4b456a5
6 changed files with 168 additions and 23 deletions

View File

@ -558,6 +558,7 @@ static void ppir_codegen_encode_branch(ppir_node *node, void *code)
ppir_codegen_field_branch *b = code;
ppir_branch_node *branch;
ppir_instr *target_instr;
ppir_block *target;
if (node->op == ppir_op_discard) {
ppir_codegen_encode_discard(node, code);
return;
@ -586,7 +587,16 @@ static void ppir_codegen_encode_branch(ppir_node *node, void *code)
assert(false);
}
target_instr = list_first_entry(&branch->target->instr_list, ppir_instr, list);
target = branch->target;
while (list_empty(&target->instr_list)) {
if (!target->list.next)
break;
target = LIST_ENTRY(ppir_block, target->list.next, list);
}
assert(!list_empty(&target->instr_list));
target_instr = list_first_entry(&target->instr_list, ppir_instr, list);
b->branch.target = target_instr->offset - node->instr->offset;
b->branch.next_count = target_instr->encode_size;
}

View File

@ -273,6 +273,7 @@ void ppir_instr_print_list(ppir_compiler *comp)
printf("const0|1\n");
list_for_each_entry(ppir_block, block, &comp->block_list, list) {
printf("-------block %3d-------\n", block->index);
list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
printf("%c%03d: ", instr->is_end ? '*' : ' ', instr->index);
for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
@ -291,8 +292,8 @@ void ppir_instr_print_list(ppir_compiler *comp)
}
printf("\n");
}
printf("------------------------\n");
}
printf("===========================\n");
}
static void ppir_instr_print_sub(ppir_instr *instr)
@ -325,12 +326,13 @@ void ppir_instr_print_dep(ppir_compiler *comp)
printf("======ppir instr depend======\n");
list_for_each_entry(ppir_block, block, &comp->block_list, list) {
printf("-------block %3d-------\n", block->index);
list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
if (ppir_instr_is_root(instr)) {
ppir_instr_print_sub(instr);
printf("\n");
}
}
printf("------------------------\n");
}
printf("=============================\n");
}

View File

@ -227,22 +227,20 @@ static bool ppir_lower_select(ppir_block *block, ppir_node *node)
move_dest->pipeline = ppir_pipeline_reg_fmul;
move_dest->write_mask = 1;
ppir_node_foreach_pred(node, dep) {
ppir_node *pred = dep->pred;
ppir_dest *dest = ppir_node_get_dest(pred);
if (ppir_node_target_equal(alu->src, dest)) {
ppir_node_replace_pred(dep, move);
ppir_node_add_dep(move, pred);
}
}
ppir_node *pred = alu->src[0].node;
ppir_dep *dep = ppir_dep_for_pred(node, pred);
if (dep)
ppir_node_replace_pred(dep, move);
else
ppir_node_add_dep(node, move);
/* move must be the first pred of select node which make sure
* the float mul slot is free when node to instr
*/
assert(ppir_node_first_pred(node) == move);
/* pred can be a register */
if (pred)
ppir_node_add_dep(move, pred);
src->swizzle[0] = 0;
ppir_node_target_assign(alu->src, move);
return true;
}

View File

@ -463,8 +463,39 @@ static ppir_block *ppir_get_block(ppir_compiler *comp, nir_block *nblock)
static ppir_node *ppir_emit_jump(ppir_block *block, nir_instr *ni)
{
ppir_error("nir_jump_instr not support\n");
return NULL;
ppir_node *node;
ppir_compiler *comp = block->comp;
ppir_branch_node *branch;
ppir_block *jump_block;
nir_jump_instr *jump = nir_instr_as_jump(ni);
switch (jump->type) {
case nir_jump_break: {
assert(comp->current_block->successors[0]);
assert(!comp->current_block->successors[1]);
jump_block = comp->current_block->successors[0];
}
break;
case nir_jump_continue:
jump_block = comp->loop_cont_block;
break;
default:
ppir_error("nir_jump_instr not support\n");
return NULL;
}
assert(jump_block != NULL);
node = ppir_node_create(block, ppir_op_branch, -1, 0);
if (!node)
return NULL;
branch = ppir_node_to_branch(node);
/* Unconditional */
branch->num_src = 0;
branch->target = jump_block;
return node;
}
static ppir_node *(*ppir_emit_instr[nir_instr_type_phi])(ppir_block *, nir_instr *) = {
@ -494,6 +525,8 @@ static bool ppir_emit_block(ppir_compiler *comp, nir_block *nblock)
{
ppir_block *block = ppir_get_block(comp, nblock);
comp->current_block = block;
list_addtail(&block->list, &comp->block_list);
nir_foreach_instr(instr, nblock) {
@ -508,16 +541,99 @@ static bool ppir_emit_block(ppir_compiler *comp, nir_block *nblock)
return true;
}
static bool ppir_emit_if(ppir_compiler *comp, nir_if *nif)
static bool ppir_emit_cf_list(ppir_compiler *comp, struct exec_list *list);
static bool ppir_emit_if(ppir_compiler *comp, nir_if *if_stmt)
{
ppir_error("if nir_cf_node not support\n");
return false;
ppir_node *node;
ppir_branch_node *else_branch, *after_branch;
nir_block *nir_else_block = nir_if_first_else_block(if_stmt);
bool empty_else_block =
(nir_else_block == nir_if_last_else_block(if_stmt) &&
exec_list_is_empty(&nir_else_block->instr_list));
ppir_block *block = comp->current_block;
node = ppir_node_create(block, ppir_op_branch, -1, 0);
if (!node)
return false;
else_branch = ppir_node_to_branch(node);
ppir_node_add_src(block->comp, node, &else_branch->src[0],
&if_stmt->condition, 1);
else_branch->num_src = 1;
/* Negate condition to minimize branching. We're generating following:
* current_block: { ...; if (!statement) branch else_block; }
* then_block: { ...; branch after_block; }
* else_block: { ... }
* after_block: { ... }
*
* or if else list is empty:
* block: { if (!statement) branch else_block; }
* then_block: { ... }
* else_block: after_block: { ... }
*/
else_branch->negate = true;
list_addtail(&else_branch->node.list, &block->node_list);
ppir_emit_cf_list(comp, &if_stmt->then_list);
if (empty_else_block) {
nir_block *nblock = nir_if_last_else_block(if_stmt);
assert(nblock->successors[0]);
assert(!nblock->successors[1]);
else_branch->target = ppir_get_block(comp, nblock->successors[0]);
/* Add empty else block to the list */
list_addtail(&block->successors[1]->list, &comp->block_list);
return true;
}
else_branch->target = ppir_get_block(comp, nir_if_first_else_block(if_stmt));
nir_block *last_then_block = nir_if_last_then_block(if_stmt);
assert(last_then_block->successors[0]);
assert(!last_then_block->successors[1]);
block = ppir_get_block(comp, last_then_block);
node = ppir_node_create(block, ppir_op_branch, -1, 0);
if (!node)
return false;
after_branch = ppir_node_to_branch(node);
/* Unconditional */
after_branch->num_src = 0;
after_branch->target = ppir_get_block(comp, last_then_block->successors[0]);
/* Target should be after_block, will fixup later */
list_addtail(&after_branch->node.list, &block->node_list);
ppir_emit_cf_list(comp, &if_stmt->else_list);
return true;
}
static bool ppir_emit_loop(ppir_compiler *comp, nir_loop *nloop)
{
ppir_error("loop nir_cf_node not support\n");
return false;
ppir_block *save_loop_cont_block = comp->loop_cont_block;
ppir_block *block;
ppir_branch_node *loop_branch;
nir_block *loop_last_block;
ppir_node *node;
comp->loop_cont_block = ppir_get_block(comp, nir_loop_first_block(nloop));
ppir_emit_cf_list(comp, &nloop->body);
loop_last_block = nir_loop_last_block(nloop);
block = ppir_get_block(comp, loop_last_block);
node = ppir_node_create(block, ppir_op_branch, -1, 0);
if (!node)
return false;
loop_branch = ppir_node_to_branch(node);
/* Unconditional */
loop_branch->num_src = 0;
loop_branch->target = comp->loop_cont_block;
list_addtail(&loop_branch->node.list, &block->node_list);
comp->loop_cont_block = save_loop_cont_block;
comp->num_loops++;
return true;
}
static bool ppir_emit_function(ppir_compiler *comp, nir_function_impl *nfunc)

View File

@ -469,6 +469,21 @@ void ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred)
list_addtail(&dep->succ_link, &new_pred->succ_list);
}
ppir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred)
{
if (!pred)
return NULL;
if (node->block != pred->block)
return NULL;
ppir_node_foreach_pred(node, dep) {
if (dep->pred == pred)
return dep;
}
return NULL;
}
void ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src)
{
ppir_node_foreach_succ_safe(src, dep) {
@ -573,7 +588,7 @@ void ppir_node_print_prog(ppir_compiler *comp)
printf("========prog========\n");
list_for_each_entry(ppir_block, block, &comp->block_list, list) {
printf("-------block------\n");
printf("-------block %3d-------\n", block->index);
list_for_each_entry(ppir_node, node, &block->node_list, list) {
if (ppir_node_is_root(node))
ppir_node_print_node(node, 0);

View File

@ -369,6 +369,9 @@ typedef struct ppir_compiler {
int num_fills;
ppir_block *discard_block;
ppir_block *current_block;
ppir_block *loop_break_block;
ppir_block *loop_cont_block;
} ppir_compiler;
void *ppir_node_create(ppir_block *block, ppir_op op, int index, unsigned mask);
@ -379,6 +382,7 @@ void ppir_node_print_prog(ppir_compiler *comp);
void ppir_node_replace_child(ppir_node *parent, ppir_node *old_child, ppir_node *new_child);
void ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src);
void ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred);
ppir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred);
ppir_node *ppir_node_clone(ppir_block *block, ppir_node *node);
static inline bool ppir_node_is_root(ppir_node *node)