From: Eric Anholt Date: Mon, 31 Dec 2018 20:18:34 +0000 (-0800) Subject: v3d: Handle dynamically uniform IF statements with uniform control flow. X-Git-Tag: upstream/19.0.0~784 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=080506057310ee3239ae8befe3679b9c2f752607;p=platform%2Fupstream%2Fmesa.git v3d: Handle dynamically uniform IF statements with uniform control flow. Loops will be trickier, since we need some analysis to figure out if the breaks/continues inside are uniform. Until we get that in NIR, this gets us some quick wins. total instructions in shared programs: 6192844 -> 6174162 (-0.30%) instructions in affected programs: 487781 -> 469099 (-3.83%) --- diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c index 9d20853..f209918 100644 --- a/src/broadcom/compiler/nir_to_vir.c +++ b/src/broadcom/compiler/nir_to_vir.c @@ -1715,7 +1715,60 @@ ntq_activate_execute_for_block(struct v3d_compile *c) } static void -ntq_emit_if(struct v3d_compile *c, nir_if *if_stmt) +ntq_emit_uniform_if(struct v3d_compile *c, nir_if *if_stmt) +{ + 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)); + + struct qblock *then_block = vir_new_block(c); + struct qblock *after_block = vir_new_block(c); + struct qblock *else_block; + if (empty_else_block) + else_block = after_block; + else + else_block = vir_new_block(c); + + /* Set up the flags for the IF condition (taking the THEN branch). */ + nir_alu_instr *if_condition_alu = ntq_get_alu_parent(if_stmt->condition); + enum v3d_qpu_cond cond; + if (!if_condition_alu || + !ntq_emit_comparison(c, if_condition_alu, &cond)) { + vir_PF(c, ntq_get_src(c, if_stmt->condition, 0), + V3D_QPU_PF_PUSHZ); + cond = V3D_QPU_COND_IFNA; + } + + /* Jump to ELSE. */ + vir_BRANCH(c, cond == V3D_QPU_COND_IFA ? + V3D_QPU_BRANCH_COND_ALLNA : + V3D_QPU_BRANCH_COND_ALLA); + vir_link_blocks(c->cur_block, else_block); + vir_link_blocks(c->cur_block, then_block); + + /* Process the THEN block. */ + vir_set_emit_block(c, then_block); + ntq_emit_cf_list(c, &if_stmt->then_list); + + if (!empty_else_block) { + /* At the end of the THEN block, jump to ENDIF */ + vir_BRANCH(c, V3D_QPU_BRANCH_COND_ALWAYS); + vir_link_blocks(c->cur_block, after_block); + + /* Emit the else block. */ + vir_set_emit_block(c, else_block); + ntq_activate_execute_for_block(c); + ntq_emit_cf_list(c, &if_stmt->else_list); + } + + vir_link_blocks(c->cur_block, after_block); + + vir_set_emit_block(c, after_block); +} + +static void +ntq_emit_nonuniform_if(struct v3d_compile *c, nir_if *if_stmt) { nir_block *nir_else_block = nir_if_first_else_block(if_stmt); bool empty_else_block = @@ -1810,6 +1863,17 @@ ntq_emit_if(struct v3d_compile *c, nir_if *if_stmt) } static void +ntq_emit_if(struct v3d_compile *c, nir_if *nif) +{ + if (c->execute.file == QFILE_NULL && + nir_src_is_dynamically_uniform(nif->condition)) { + ntq_emit_uniform_if(c, nif); + } else { + ntq_emit_nonuniform_if(c, nif); + } +} + +static void ntq_emit_jump(struct v3d_compile *c, nir_jump_instr *jump) { switch (jump->type) {