summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVasily Khoruzhick <[email protected]>2019-08-18 23:37:23 -0700
committerVasily Khoruzhick <[email protected]>2019-08-24 08:17:31 -0700
commit28d4b456a582c1388fc3dde45e98cc97389485dc (patch)
tree2095737304fb69d3387ab0e3bf718565c16cbfc0 /src
parent1cdf585613da37f23d737ac4713af0484d4a30d7 (diff)
lima/ppir: add control flow support
This commit adds support for nir_jump_instr, if and loop nir_cf_nodes. Tested-by: Andreas Baierl <[email protected]> Reviewed-by: Qiang Yu <[email protected]> Reviewed-by: Erico Nunes <[email protected]> Signed-off-by: Vasily Khoruzhick <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/lima/ir/pp/codegen.c12
-rw-r--r--src/gallium/drivers/lima/ir/pp/instr.c6
-rw-r--r--src/gallium/drivers/lima/ir/pp/lower.c22
-rw-r--r--src/gallium/drivers/lima/ir/pp/nir.c130
-rw-r--r--src/gallium/drivers/lima/ir/pp/node.c17
-rw-r--r--src/gallium/drivers/lima/ir/pp/ppir.h4
6 files changed, 168 insertions, 23 deletions
diff --git a/src/gallium/drivers/lima/ir/pp/codegen.c b/src/gallium/drivers/lima/ir/pp/codegen.c
index 4b1c48dffa3..f08f83a9f43 100644
--- a/src/gallium/drivers/lima/ir/pp/codegen.c
+++ b/src/gallium/drivers/lima/ir/pp/codegen.c
@@ -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;
}
diff --git a/src/gallium/drivers/lima/ir/pp/instr.c b/src/gallium/drivers/lima/ir/pp/instr.c
index 474f9ca8cab..74b6e5fbaea 100644
--- a/src/gallium/drivers/lima/ir/pp/instr.c
+++ b/src/gallium/drivers/lima/ir/pp/instr.c
@@ -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");
}
diff --git a/src/gallium/drivers/lima/ir/pp/lower.c b/src/gallium/drivers/lima/ir/pp/lower.c
index cd175cc0879..5aca32e683e 100644
--- a/src/gallium/drivers/lima/ir/pp/lower.c
+++ b/src/gallium/drivers/lima/ir/pp/lower.c
@@ -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;
}
diff --git a/src/gallium/drivers/lima/ir/pp/nir.c b/src/gallium/drivers/lima/ir/pp/nir.c
index 831c50b3cd0..4852e55a8b6 100644
--- a/src/gallium/drivers/lima/ir/pp/nir.c
+++ b/src/gallium/drivers/lima/ir/pp/nir.c
@@ -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)
diff --git a/src/gallium/drivers/lima/ir/pp/node.c b/src/gallium/drivers/lima/ir/pp/node.c
index 59635df3cdf..db141cac5c1 100644
--- a/src/gallium/drivers/lima/ir/pp/node.c
+++ b/src/gallium/drivers/lima/ir/pp/node.c
@@ -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);
diff --git a/src/gallium/drivers/lima/ir/pp/ppir.h b/src/gallium/drivers/lima/ir/pp/ppir.h
index db8087ede62..462cd93538a 100644
--- a/src/gallium/drivers/lima/ir/pp/ppir.h
+++ b/src/gallium/drivers/lima/ir/pp/ppir.h
@@ -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)