On 3 Nov. 2016 18:21, "Gustaw Smolarczyk" <wielkie...@gmail.com> wrote: > > I am not really that much familiar with nir, so I apologize if what I write below is wrong. > > What if we had something like: > > a = 0; > if (x) { > discard_if(y); > a = 1; > } > > Then if (x && !y), we must not discard and both at the same time set a to 1. Your transformation would probably change it to: > > a = 0; > discard_if(x && y); > > Which is incorrect. > > I think you have to ensure (if the intrinsic is discard_if) that discard_if is the only instruction inside the then block. Or just remove the intrinsic from the then block and leave the rest of the if alone. >
Yes you are right I need to add a check that there is only one instruction in the then block. Thanks, Dave. > Regards, > Gustaw > > 2016-11-03 4:28 GMT+01:00 Dave Airlie <airl...@gmail.com>: >> >> From: Dave Airlie <airl...@redhat.com> >> >> This is ported from GLSL and converts >> >> if (cond) >> discard; >> >> into >> discard_if(cond); >> >> This removes a block, but also is needed by radv >> to workaround a bug in the LLVM backend. >> >> v2: handle if (a) discard_if(b) (nha) >> cleanup and drop pointless loop (Matt) >> make sure there are no dependent phis (Eric) >> >> Signed-off-by: Dave Airlie <airl...@redhat.com> >> --- >> src/compiler/Makefile.sources | 1 + >> src/compiler/nir/nir.h | 2 + >> src/compiler/nir/nir_opt_conditional_discard.c | 124 +++++++++++++++++++++++++ >> 3 files changed, 127 insertions(+) >> create mode 100644 src/compiler/nir/nir_opt_conditional_discard.c >> >> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources >> index 669c499..b710cbd 100644 >> --- a/src/compiler/Makefile.sources >> +++ b/src/compiler/Makefile.sources >> @@ -228,6 +228,7 @@ NIR_FILES = \ >> nir/nir_metadata.c \ >> nir/nir_move_vec_src_uses_to_dest.c \ >> nir/nir_normalize_cubemap_coords.c \ >> + nir/nir_opt_conditional_discard.c \ >> nir/nir_opt_constant_folding.c \ >> nir/nir_opt_copy_propagate.c \ >> nir/nir_opt_cse.c \ >> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h >> index 9264763..2a77139 100644 >> --- a/src/compiler/nir/nir.h >> +++ b/src/compiler/nir/nir.h >> @@ -2531,6 +2531,8 @@ bool nir_opt_remove_phis(nir_shader *shader); >> >> bool nir_opt_undef(nir_shader *shader); >> >> +bool nir_opt_conditional_discard(nir_shader *shader); >> + >> void nir_sweep(nir_shader *shader); >> >> nir_intrinsic_op nir_intrinsic_from_system_value(gl_system_value val); >> diff --git a/src/compiler/nir/nir_opt_conditional_discard.c b/src/compiler/nir/nir_opt_conditional_discard.c >> new file mode 100644 >> index 0000000..2259a14 >> --- /dev/null >> +++ b/src/compiler/nir/nir_opt_conditional_discard.c >> @@ -0,0 +1,124 @@ >> +/* >> + * Copyright © 2016 Red Hat >> + * >> + * Permission is hereby granted, free of charge, to any person obtaining a >> + * copy of this software and associated documentation files (the "Software"), >> + * to deal in the Software without restriction, including without limitation >> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, >> + * and/or sell copies of the Software, and to permit persons to whom the >> + * Software is furnished to do so, subject to the following conditions: >> + * >> + * The above copyright notice and this permission notice (including the next >> + * paragraph) shall be included in all copies or substantial portions of the >> + * Software. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER >> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING >> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS >> + * IN THE SOFTWARE. >> + */ >> + >> +#include "nir.h" >> +#include "nir_builder.h" >> + >> +/** @file nir_opt_conditional_discard.c >> + * >> + * Handles optimization of lowering if (cond) discard to discard_if(cond). >> + */ >> + >> +static bool >> +nir_opt_conditional_discard_block(nir_block *block, void *mem_ctx) >> +{ >> + nir_builder bld; >> + >> + if (nir_cf_node_is_first(&block->cf_node)) >> + return false; >> + >> + nir_cf_node *prev_node = nir_cf_node_prev(&block->cf_node); >> + if (prev_node->type != nir_cf_node_if) >> + return false; >> + >> + nir_if *if_stmt = nir_cf_node_as_if(prev_node); >> + nir_block *then_block = nir_if_first_then_block(if_stmt); >> + nir_block *else_block = nir_if_first_else_block(if_stmt); >> + >> + /* check there is only one else block and it is empty */ >> + if (nir_if_last_else_block(if_stmt) != else_block) >> + return false; >> + if (!exec_list_is_empty(&else_block->instr_list)) >> + return false; >> + >> + /* check there is only one then block and it has instructions in it */ >> + if (nir_if_last_then_block(if_stmt) != then_block) >> + return false; >> + if (exec_list_is_empty(&then_block->instr_list)) >> + return false; >> + >> + /* >> + * make sure no subsequent phi nodes point at this if. >> + */ >> + nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node)); >> + nir_foreach_instr_safe(instr, after) { >> + if (instr->type != nir_instr_type_phi) >> + break; >> + nir_phi_instr *phi = nir_instr_as_phi(instr); >> + >> + nir_foreach_phi_src(phi_src, phi) { >> + if (phi_src->pred == then_block || >> + phi_src->pred == else_block) >> + return false; >> + } >> + } >> + >> + /* Get the first instruction in the then block and confirm it is >> + * a discard or a discard_if >> + */ >> + nir_instr *instr = nir_block_first_instr(then_block); >> + if (instr->type != nir_instr_type_intrinsic) >> + return false; >> + >> + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); >> + if (intrin->intrinsic != nir_intrinsic_discard && >> + intrin->intrinsic != nir_intrinsic_discard_if) >> + return false; >> + >> + nir_src cond; >> + >> + nir_builder_init(&bld, mem_ctx); >> + >> + if (intrin->intrinsic == nir_intrinsic_discard) >> + cond = if_stmt->condition; >> + else >> + cond = nir_src_for_ssa(nir_iand(&bld, >> + nir_ssa_for_src(&bld, if_stmt->condition, 1), >> + nir_ssa_for_src(&bld, intrin->src[0], 1))); >> + >> + nir_intrinsic_instr *discard_if = >> + nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_discard_if); >> + nir_src_copy(&discard_if->src[0], &cond, discard_if); >> + >> + nir_instr_insert_before_cf(prev_node, &discard_if->instr); >> + nir_instr_remove(&intrin->instr); >> + nir_cf_node_remove(&if_stmt->cf_node); >> + >> + return true; >> +} >> + >> +bool >> +nir_opt_conditional_discard(nir_shader *shader) >> +{ >> + bool progress = false; >> + >> + nir_foreach_function(function, shader) { >> + if (function->impl) { >> + void *mem_ctx = ralloc_parent(function->impl); >> + nir_foreach_block_safe(block, function->impl) { >> + progress |= nir_opt_conditional_discard_block(block, mem_ctx); >> + } >> + } >> + } >> + return progress; >> +} >> -- >> 2.7.4 >> >> _______________________________________________ >> mesa-dev mailing list >> mesa-dev@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/mesa-dev > >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev