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:
parent
1cdf585613
commit
28d4b456a5
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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 *pred = alu->src[0].node;
|
||||
ppir_dep *dep = ppir_dep_for_pred(node, pred);
|
||||
if (dep)
|
||||
ppir_node_replace_pred(dep, move);
|
||||
ppir_node_add_dep(move, pred);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -463,10 +463,41 @@ 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_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 *) = {
|
||||
[nir_instr_type_alu] = ppir_emit_alu,
|
||||
[nir_instr_type_intrinsic] = ppir_emit_intrinsic,
|
||||
|
@ -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");
|
||||
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");
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue