<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Feb 28, 2015 at 10:33 AM, Connor Abbott <span dir="ltr"><<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Feb 27, 2015 at 8:13 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> Previously, the nir_if control-flow node had a source built straight into<br>
> it that was the if condition.  This has been the source of a lot of<br>
> edge-case headaches due to, in particular, the two different use sets that<br>
> we were carrying around.  This patch changes it to have a special jump<br>
> instruction that gets placed at the end of the block in front of the if.<br>
> This way we no longer have to keep special-casing the source and can treate<br>
> it like any other use in an instruction.<br>
><br>
> Cc: Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
<br>
</span>So at first my gut reaction is that this was a bad idea -- we would be<br>
splitting off part of the if, which is part of the control flow, into<br>
a separate instruction when all the other control flow stuff is part<br>
of the tree. But we already use instructions to represent breaks and<br>
continues, and clearly the ugliness that is if_uses dying is good<br>
enough that I can't possibly argue against this. Is there a reason you<br>
marked this as RFC? I remember that you stopped working on this a<br>
while ago because of some problem with the control-flow modification<br>
code in nir.c -- did you ever figure that out?<br><div><div class="h5"></div></div></blockquote><div><br></div><div>Why did I mark it as RFC?  Because I don't have a good enough excuse other than the obviously nice clean-up to merge it at the moment.  Honestly, the clean-up is probably a good enough reason.<br><br></div><div>Did I figure out the control-flow manipulation problems?  Yes, sort-of.  I got it to stop assert-failing in any case.  To be honest, I'm not 100% sure it's fixed correctly.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
><br>
> ---<br>
>  src/glsl/nir/glsl_to_nir.cpp             | 17 ++++--<br>
>  src/glsl/nir/nir.c                       | 70 +++++++----------------<br>
>  src/glsl/nir/nir.h                       | 11 ++--<br>
>  src/glsl/nir/nir_from_ssa.c              | 18 ------<br>
>  src/glsl/nir/nir_live_variables.c        |  4 --<br>
>  src/glsl/nir/nir_lower_to_source_mods.c  |  6 +-<br>
>  src/glsl/nir/nir_opt_copy_propagate.c    | 46 +++-------------<br>
>  src/glsl/nir/nir_opt_dce.c               |  7 ---<br>
>  src/glsl/nir/nir_opt_gcm.c               | 12 ----<br>
>  src/glsl/nir/nir_opt_global_to_local.c   | 11 ----<br>
>  src/glsl/nir/nir_opt_peephole_select.c   | 21 ++++---<br>
>  src/glsl/nir/nir_print.c                 |  9 ++-<br>
>  src/glsl/nir/nir_to_ssa.c                | 16 +-----<br>
>  src/glsl/nir/nir_validate.c              | 95 ++++++++++++--------------------<br>
>  src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 15 +++--<br>
>  15 files changed, 111 insertions(+), 247 deletions(-)<br>
><br>
> diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp<br>
> index adef19c..e84bf1c 100644<br>
> --- a/src/glsl/nir/glsl_to_nir.cpp<br>
> +++ b/src/glsl/nir/glsl_to_nir.cpp<br>
> @@ -536,12 +536,13 @@ nir_visitor::visit(ir_loop *ir)<br>
>  void<br>
>  nir_visitor::visit(ir_if *ir)<br>
>  {<br>
> -   nir_src condition = evaluate_rvalue(ir->condition);<br>
> +   nir_jump_instr *if_instr = nir_jump_instr_create(this->shader, nir_jump_if);<br>
> +   if_instr->if_src = evaluate_rvalue(ir->condition);<br>
> +   nir_instr_insert_after_cf_list(this->cf_node_list, &if_instr->instr);<br>
><br>
>     exec_list *old_list = this->cf_node_list;<br>
><br>
>     nir_if *if_stmt = nir_if_create(this->shader);<br>
> -   if_stmt->condition = condition;<br>
>     nir_cf_node_insert_end(old_list, &if_stmt->cf_node);<br>
><br>
>     this->cf_node_list = &if_stmt->then_list;<br>
> @@ -704,9 +705,13 @@ nir_visitor::visit(ir_assignment *ir)<br>
><br>
><br>
>        if (ir->condition) {<br>
> +         nir_jump_instr *if_instr = nir_jump_instr_create(this->shader, nir_jump_if);<br>
> +         if_instr->if_src = evaluate_rvalue(ir->condition);<br>
> +         nir_instr_insert_after_cf_list(this->cf_node_list, &if_instr->instr);<br>
> +<br>
>           nir_if *if_stmt = nir_if_create(this->shader);<br>
> -         if_stmt->condition = evaluate_rvalue(ir->condition);<br>
>           nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);<br>
> +<br>
>           nir_instr_insert_after_cf_list(&if_stmt->then_list, &copy->instr);<br>
>        } else {<br>
>           nir_instr_insert_after_cf_list(this->cf_node_list, &copy->instr);<br>
> @@ -779,9 +784,13 @@ nir_visitor::visit(ir_assignment *ir)<br>
>     store->src[0] = src;<br>
><br>
>     if (ir->condition) {<br>
> +      nir_jump_instr *if_instr = nir_jump_instr_create(this->shader, nir_jump_if);<br>
> +      if_instr->if_src = evaluate_rvalue(ir->condition);<br>
> +      nir_instr_insert_after_cf_list(this->cf_node_list, &if_instr->instr);<br>
> +<br>
>        nir_if *if_stmt = nir_if_create(this->shader);<br>
> -      if_stmt->condition = evaluate_rvalue(ir->condition);<br>
>        nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);<br>
> +<br>
>        nir_instr_insert_after_cf_list(&if_stmt->then_list, &store->instr);<br>
>     } else {<br>
>        nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);<br>
> diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c<br>
> index ab57fd4..bd668ee 100644<br>
> --- a/src/glsl/nir/nir.c<br>
> +++ b/src/glsl/nir/nir.c<br>
> @@ -68,8 +68,6 @@ reg_create(void *mem_ctx, struct exec_list *list)<br>
>                                  _mesa_key_pointer_equal);<br>
>     reg->defs = _mesa_set_create(mem_ctx, _mesa_hash_pointer,<br>
>                                  _mesa_key_pointer_equal);<br>
> -   reg->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,<br>
> -                                   _mesa_key_pointer_equal);<br>
><br>
>     reg->num_components = 0;<br>
>     reg->num_array_elems = 0;<br>
> @@ -317,7 +315,6 @@ nir_if_create(void *mem_ctx)<br>
>     nir_if *if_stmt = ralloc(mem_ctx, nir_if);<br>
><br>
>     cf_init(&if_stmt->cf_node, nir_cf_node_if);<br>
> -   src_init(&if_stmt->condition);<br>
><br>
>     nir_block *then = nir_block_create(mem_ctx);<br>
>     exec_list_make_empty(&if_stmt->then_list);<br>
> @@ -409,6 +406,7 @@ nir_jump_instr_create(void *mem_ctx, nir_jump_type type)<br>
>     nir_jump_instr *instr = ralloc(mem_ctx, nir_jump_instr);<br>
>     instr_init(&instr->instr, nir_instr_type_jump);<br>
>     instr->type = type;<br>
> +   src_init(&instr->if_src);<br>
>     return instr;<br>
>  }<br>
><br>
> @@ -860,8 +858,6 @@ handle_jump(nir_block *block)<br>
>     nir_instr *instr = nir_block_last_instr(block);<br>
>     nir_jump_instr *jump_instr = nir_instr_as_jump(instr);<br>
><br>
> -   unlink_block_successors(block);<br>
> -<br>
>     nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);<br>
>     nir_metadata_preserve(impl, nir_metadata_none);<br>
><br>
> @@ -869,6 +865,8 @@ handle_jump(nir_block *block)<br>
>         jump_instr->type == nir_jump_continue) {<br>
>        nir_loop *loop = nearest_loop(&block->cf_node);<br>
><br>
> +      unlink_block_successors(block);<br>
> +<br>
>        if (jump_instr->type == nir_jump_continue) {<br>
>           nir_cf_node *first_node = nir_loop_first_cf_node(loop);<br>
>           assert(first_node->type == nir_cf_node_block);<br>
> @@ -887,8 +885,12 @@ handle_jump(nir_block *block)<br>
>           if (last_block->successors[1] != NULL)<br>
>              unlink_blocks(last_block, after_block);<br>
>        }<br>
> +   } else if (jump_instr->type == nir_jump_if) {<br>
> +      /* Do nothing here for the moment */<br>
>     } else {<br>
>        assert(jump_instr->type == nir_jump_return);<br>
> +<br>
> +      unlink_block_successors(block);<br>
>        link_blocks(block, impl->end_block, NULL);<br>
>     }<br>
>  }<br>
> @@ -1008,26 +1010,9 @@ insert_block_after_block(nir_block *block, nir_block *after, bool has_jump)<br>
>        handle_jump(block);<br>
>  }<br>
><br>
> -static void<br>
> -update_if_uses(nir_cf_node *node)<br>
> -{<br>
> -   if (node->type != nir_cf_node_if)<br>
> -      return;<br>
> -<br>
> -   nir_if *if_stmt = nir_cf_node_as_if(node);<br>
> -<br>
> -   struct set *if_uses_set = if_stmt->condition.is_ssa ?<br>
> -                             if_stmt->condition.ssa->if_uses :<br>
> -                             if_stmt->condition.reg.reg->uses;<br>
> -<br>
> -   _mesa_set_add(if_uses_set, if_stmt);<br>
> -}<br>
> -<br>
>  void<br>
>  nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)<br>
>  {<br>
> -   update_if_uses(after);<br>
> -<br>
>     if (after->type == nir_cf_node_block) {<br>
>        /*<br>
>         * either node or the one after it must be a basic block, by invariant #2;<br>
> @@ -1073,8 +1058,6 @@ nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)<br>
>  void<br>
>  nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)<br>
>  {<br>
> -   update_if_uses(before);<br>
> -<br>
>     if (before->type == nir_cf_node_block) {<br>
>        nir_block *before_block = nir_cf_node_as_block(before);<br>
><br>
> @@ -1172,17 +1155,6 @@ cleanup_cf_node(nir_cf_node *node)<br>
>           cleanup_cf_node(child);<br>
>        foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)<br>
>           cleanup_cf_node(child);<br>
> -<br>
> -      struct set *if_uses;<br>
> -      if (if_stmt->condition.is_ssa) {<br>
> -         if_uses = if_stmt->condition.ssa->if_uses;<br>
> -      } else {<br>
> -         if_uses = if_stmt->condition.reg.reg->if_uses;<br>
> -      }<br>
> -<br>
> -      struct set_entry *entry = _mesa_set_search(if_uses, if_stmt);<br>
> -      assert(entry);<br>
> -      _mesa_set_remove(if_uses, entry);<br>
>        break;<br>
>     }<br>
><br>
> @@ -1652,6 +1624,15 @@ visit_load_const_src(nir_load_const_instr *instr, nir_foreach_src_cb cb,<br>
>  }<br>
><br>
>  static bool<br>
> +visit_jump_src(nir_jump_instr *instr, nir_foreach_src_cb cb, void *state)<br>
> +{<br>
> +   if (instr->type == nir_jump_if)<br>
> +      return visit_src(&instr->if_src, cb, state);<br>
> +   else<br>
> +      return true;<br>
> +}<br>
> +<br>
> +static bool<br>
>  visit_phi_src(nir_phi_instr *instr, nir_foreach_src_cb cb, void *state)<br>
>  {<br>
>     nir_foreach_phi_src(instr, src) {<br>
> @@ -1714,6 +1695,10 @@ nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)<br>
>        if (!visit_load_const_src(nir_instr_as_load_const(instr), cb, state))<br>
>           return false;<br>
>        break;<br>
> +   case nir_instr_type_jump:<br>
> +      if (!visit_jump_src(nir_instr_as_jump(instr), cb, state))<br>
> +         return false;<br>
> +      break;<br>
>     case nir_instr_type_phi:<br>
>        if (!visit_phi_src(nir_instr_as_phi(instr), cb, state))<br>
>           return false;<br>
> @@ -1723,7 +1708,6 @@ nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)<br>
>                                     cb, state))<br>
>           return false;<br>
>        break;<br>
> -   case nir_instr_type_jump:<br>
>     case nir_instr_type_ssa_undef:<br>
>        return true;<br>
><br>
> @@ -1846,8 +1830,6 @@ nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,<br>
>     def->parent_instr = instr;<br>
>     def->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,<br>
>                                  _mesa_key_pointer_equal);<br>
> -   def->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,<br>
> -                                   _mesa_key_pointer_equal);<br>
>     def->num_components = num_components;<br>
><br>
>     if (instr->block) {<br>
> @@ -1895,13 +1877,11 @@ nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx)<br>
><br>
>     assert(!new_src.is_ssa || def != new_src.ssa);<br>
><br>
> -   struct set *new_uses, *new_if_uses;<br>
> +   struct set *new_uses;<br>
>     if (new_src.is_ssa) {<br>
>        new_uses = new_src.ssa->uses;<br>
> -      new_if_uses = new_src.ssa->if_uses;<br>
>     } else {<br>
>        new_uses = new_src.reg.reg->uses;<br>
> -      new_if_uses = new_src.reg.reg->if_uses;<br>
>     }<br>
><br>
>     struct set_entry *entry;<br>
> @@ -1912,14 +1892,6 @@ nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx)<br>
>        nir_foreach_src(instr, ssa_def_rewrite_uses_src, &state);<br>
>        _mesa_set_add(new_uses, instr);<br>
>     }<br>
> -<br>
> -   set_foreach(def->if_uses, entry) {<br>
> -      nir_if *if_use = (nir_if *)entry->key;<br>
> -<br>
> -      _mesa_set_remove(def->if_uses, entry);<br>
> -      nir_src_copy(&if_use->condition, &new_src, mem_ctx);<br>
> -      _mesa_set_add(new_if_uses, if_use);<br>
> -   }<br>
>  }<br>
><br>
><br>
> diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h<br>
> index d5df596..1bfc616 100644<br>
> --- a/src/glsl/nir/nir.h<br>
> +++ b/src/glsl/nir/nir.h<br>
> @@ -400,9 +400,6 @@ typedef struct {<br>
><br>
>     /** set of nir_instr's where this register is defined (written to) */<br>
>     struct set *defs;<br>
> -<br>
> -   /** set of nir_if's where this register is used as a condition */<br>
> -   struct set *if_uses;<br>
>  } nir_register;<br>
><br>
>  typedef enum {<br>
> @@ -463,9 +460,6 @@ typedef struct {<br>
>     /** set of nir_instr's where this register is used (read from) */<br>
>     struct set *uses;<br>
><br>
> -   /** set of nir_if's where this register is used as a condition */<br>
> -   struct set *if_uses;<br>
> -<br>
>     uint8_t num_components;<br>
>  } nir_ssa_def;<br>
><br>
> @@ -1032,11 +1026,15 @@ typedef enum {<br>
>     nir_jump_return,<br>
>     nir_jump_break,<br>
>     nir_jump_continue,<br>
> +   nir_jump_if,<br>
>  } nir_jump_type;<br>
><br>
>  typedef struct {<br>
>     nir_instr instr;<br>
>     nir_jump_type type;<br>
> +<br>
> +   /* Only used for if instructions */<br>
> +   nir_src if_src;<br>
<br>
</div></div>Have you considered renaming this to something more generic like<br>
"condition"? We might want to use this to support conditional breaks<br>
and continues as well, if they might help us a little with another ...<br>
*cough* ... source language.<br><div class="HOEnZb"><div class="h5"></div></div></blockquote><div><br></div><div>Good call.  We will probably want conditional breaks/continues eventually anyway if for no other reason than that the i965 backend really likes predicated things.  As it stands, we already have a predicated break peephole in the backend.  Also, condition is a lot more descriptive than if_src anyway.<br><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
>  } nir_jump_instr;<br>
><br>
>  /* creates a new SSA variable in an undefined state */<br>
> @@ -1192,7 +1190,6 @@ nir_block_last_instr(nir_block *block)<br>
><br>
>  typedef struct {<br>
>     nir_cf_node cf_node;<br>
> -   nir_src condition;<br>
><br>
>     struct exec_list then_list; /** < list of nir_cf_node */<br>
>     struct exec_list else_list; /** < list of nir_cf_node */<br>
> diff --git a/src/glsl/nir/nir_from_ssa.c b/src/glsl/nir/nir_from_ssa.c<br>
> index c695c95..45cdea1 100644<br>
> --- a/src/glsl/nir/nir_from_ssa.c<br>
> +++ b/src/glsl/nir/nir_from_ssa.c<br>
> @@ -558,7 +558,6 @@ rewrite_ssa_dest(nir_dest *dest, void *void_state)<br>
>        }<br>
><br>
>        _mesa_set_destroy(dest->ssa.uses, NULL);<br>
> -      _mesa_set_destroy(dest->ssa.if_uses, NULL);<br>
><br>
>        memset(dest, 0, sizeof *dest);<br>
>        dest->reg.reg = reg;<br>
> @@ -590,23 +589,6 @@ resolve_registers_block(nir_block *block, void *void_state)<br>
>     }<br>
>     state->instr = NULL;<br>
><br>
> -   nir_if *following_if = nir_block_get_following_if(block);<br>
> -   if (following_if && following_if->condition.is_ssa) {<br>
> -      nir_register *reg = get_register_for_ssa_def(following_if->condition.ssa,<br>
> -                                                   state);<br>
> -      if (reg) {<br>
> -         memset(&following_if->condition, 0, sizeof following_if->condition);<br>
> -         following_if->condition.reg.reg = reg;<br>
> -<br>
> -         _mesa_set_add(reg->if_uses, following_if);<br>
> -      } else {<br>
> -         /* FIXME: We really shouldn't hit this.  We should be doing<br>
> -          * constant control flow propagation.<br>
> -          */<br>
> -         assert(following_if->condition.ssa->parent_instr->type == nir_instr_type_load_const);<br>
> -      }<br>
> -   }<br>
> -<br>
>     return true;<br>
>  }<br>
><br>
> diff --git a/src/glsl/nir/nir_live_variables.c b/src/glsl/nir/nir_live_variables.c<br>
> index 7402dc0..f10d352 100644<br>
> --- a/src/glsl/nir/nir_live_variables.c<br>
> +++ b/src/glsl/nir/nir_live_variables.c<br>
> @@ -200,10 +200,6 @@ nir_live_variables_impl(nir_function_impl *impl)<br>
>        memcpy(block->live_in, block->live_out,<br>
>               state.bitset_words * sizeof(BITSET_WORD));<br>
><br>
> -      nir_if *following_if = nir_block_get_following_if(block);<br>
> -      if (following_if)<br>
> -         set_src_live(&following_if->condition, block->live_in);<br>
> -<br>
>        nir_foreach_instr_reverse(block, instr) {<br>
>           /* Phi nodes are handled seperately so we want to skip them.  Since<br>
>            * we are going backwards and they are at the beginning, we can just<br>
> diff --git a/src/glsl/nir/nir_lower_to_source_mods.c b/src/glsl/nir/nir_lower_to_source_mods.c<br>
> index d6bf77f..f4283e3 100644<br>
> --- a/src/glsl/nir/nir_lower_to_source_mods.c<br>
> +++ b/src/glsl/nir/nir_lower_to_source_mods.c<br>
> @@ -81,8 +81,7 @@ nir_lower_to_source_mods_block(nir_block *block, void *state)<br>
>              alu->src[i].swizzle[j] = parent->src[0].swizzle[alu->src[i].swizzle[j]];<br>
>           }<br>
><br>
> -         if (parent->dest.dest.ssa.uses->entries == 0 &&<br>
> -             parent->dest.dest.ssa.if_uses->entries == 0)<br>
> +         if (parent->dest.dest.ssa.uses->entries == 0)<br>
>              nir_instr_remove(&parent->instr);<br>
>        }<br>
><br>
> @@ -124,9 +123,6 @@ nir_lower_to_source_mods_block(nir_block *block, void *state)<br>
>        if (nir_op_infos[alu->op].output_type != nir_type_float)<br>
>           continue;<br>
><br>
> -      if (alu->dest.dest.ssa.if_uses->entries != 0)<br>
> -         continue;<br>
> -<br>
>        bool all_children_are_sat = true;<br>
>        struct set_entry *entry;<br>
>        set_foreach(alu->dest.dest.ssa.uses, entry) {<br>
> diff --git a/src/glsl/nir/nir_opt_copy_propagate.c b/src/glsl/nir/nir_opt_copy_propagate.c<br>
> index ee78e5a..d3361dc 100644<br>
> --- a/src/glsl/nir/nir_opt_copy_propagate.c<br>
> +++ b/src/glsl/nir/nir_opt_copy_propagate.c<br>
> @@ -135,26 +135,12 @@ rewrite_src_instr(nir_src *src, nir_ssa_def *new_def, nir_instr *parent_instr)<br>
>     _mesa_set_add(new_def->uses, parent_instr);<br>
>  }<br>
><br>
> -static void<br>
> -rewrite_src_if(nir_if *if_stmt, nir_ssa_def *new_def)<br>
> -{<br>
> -   nir_ssa_def *old_def = if_stmt->condition.ssa;<br>
> -<br>
> -   if_stmt->condition.ssa = new_def;<br>
> -<br>
> -   struct set_entry *entry = _mesa_set_search(old_def->if_uses, if_stmt);<br>
> -   assert(entry);<br>
> -   _mesa_set_remove(old_def->if_uses, entry);<br>
> -<br>
> -   _mesa_set_add(new_def->if_uses, if_stmt);<br>
> -}<br>
> -<br>
>  static bool<br>
> -copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)<br>
> +copy_prop_src(nir_src *src, nir_instr *parent_instr)<br>
>  {<br>
>     if (!src->is_ssa) {<br>
>        if (src->reg.indirect)<br>
> -         return copy_prop_src(src, parent_instr, parent_if);<br>
> +         return copy_prop_src(src, parent_instr);<br>
>        return false;<br>
>     }<br>
><br>
> @@ -170,7 +156,7 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)<br>
>      * components in its source than it has in its destination.  That badly<br>
>      * messes up out-of-ssa.<br>
>      */<br>
> -   if (parent_instr && parent_instr->type == nir_instr_type_phi) {<br>
> +   if (parent_instr->type == nir_instr_type_phi) {<br>
>        nir_phi_instr *phi = nir_instr_as_phi(parent_instr);<br>
>        assert(phi->dest.is_ssa);<br>
>        if (phi->dest.ssa.num_components !=<br>
> @@ -178,10 +164,7 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)<br>
>           return false;<br>
>     }<br>
><br>
> -   if (parent_instr)<br>
> -      rewrite_src_instr(src, alu_instr->src[0].src.ssa, parent_instr);<br>
> -   else<br>
> -      rewrite_src_if(parent_if, alu_instr->src[0].src.ssa);<br>
> +   rewrite_src_instr(src, alu_instr->src[0].src.ssa, parent_instr);<br>
><br>
>     return true;<br>
>  }<br>
> @@ -192,8 +175,7 @@ copy_prop_alu_src(nir_alu_instr *parent_alu_instr, unsigned index)<br>
>     nir_alu_src *src = &parent_alu_instr->src[index];<br>
>     if (!src->src.is_ssa) {<br>
>        if (src->src.reg.indirect)<br>
> -         return copy_prop_src(src->src.reg.indirect, &parent_alu_instr->instr,<br>
> -                              NULL);<br>
> +         return copy_prop_src(src->src.reg.indirect, &parent_alu_instr->instr);<br>
>        return false;<br>
>     }<br>
><br>
> @@ -248,7 +230,7 @@ static bool<br>
>  copy_prop_src_cb(nir_src *src, void *_state)<br>
>  {<br>
>     copy_prop_state *state = (copy_prop_state *) _state;<br>
> -   while (copy_prop_src(src, state->parent_instr, NULL))<br>
> +   while (copy_prop_src(src, state->parent_instr))<br>
>        state->progress = true;<br>
><br>
>     return true;<br>
> @@ -266,7 +248,7 @@ copy_prop_instr(nir_instr *instr)<br>
>              progress = true;<br>
><br>
>        if (!alu_instr->dest.dest.is_ssa && alu_instr->dest.dest.reg.indirect)<br>
> -         while (copy_prop_src(alu_instr->dest.dest.reg.indirect, instr, NULL))<br>
> +         while (copy_prop_src(alu_instr->dest.dest.reg.indirect, instr))<br>
>              progress = true;<br>
><br>
>        return progress;<br>
> @@ -281,12 +263,6 @@ copy_prop_instr(nir_instr *instr)<br>
>  }<br>
><br>
>  static bool<br>
> -copy_prop_if(nir_if *if_stmt)<br>
> -{<br>
> -   return copy_prop_src(&if_stmt->condition, NULL, if_stmt);<br>
> -}<br>
> -<br>
> -static bool<br>
>  copy_prop_block(nir_block *block, void *_state)<br>
>  {<br>
>     bool *progress = (bool *) _state;<br>
> @@ -296,14 +272,6 @@ copy_prop_block(nir_block *block, void *_state)<br>
>           *progress = true;<br>
>     }<br>
><br>
> -   if (block->cf_node.node.next != NULL && /* check that we aren't the end node */<br>
> -       !nir_cf_node_is_last(&block->cf_node) &&<br>
> -       nir_cf_node_next(&block->cf_node)->type == nir_cf_node_if) {<br>
> -      nir_if *if_stmt = nir_cf_node_as_if(nir_cf_node_next(&block->cf_node));<br>
> -      if (copy_prop_if(if_stmt))<br>
> -         *progress = true;<br>
> -   }<br>
> -<br>
>     return true;<br>
>  }<br>
><br>
> diff --git a/src/glsl/nir/nir_opt_dce.c b/src/glsl/nir/nir_opt_dce.c<br>
> index e0ebdc6..3d3ea3f 100644<br>
> --- a/src/glsl/nir/nir_opt_dce.c<br>
> +++ b/src/glsl/nir/nir_opt_dce.c<br>
> @@ -120,13 +120,6 @@ init_block_cb(nir_block *block, void *_state)<br>
>     nir_foreach_instr(block, instr)<br>
>        init_instr(instr, worklist);<br>
><br>
> -   nir_if *following_if = nir_block_get_following_if(block);<br>
> -   if (following_if) {<br>
> -      if (following_if->condition.is_ssa &&<br>
> -          !following_if->condition.ssa->parent_instr->pass_flags)<br>
> -         worklist_push(worklist, following_if->condition.ssa->parent_instr);<br>
> -   }<br>
> -<br>
>     return true;<br>
>  }<br>
><br>
> diff --git a/src/glsl/nir/nir_opt_gcm.c b/src/glsl/nir/nir_opt_gcm.c<br>
> index b4f5fd3..d2553b7 100644<br>
> --- a/src/glsl/nir/nir_opt_gcm.c<br>
> +++ b/src/glsl/nir/nir_opt_gcm.c<br>
> @@ -304,18 +304,6 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state)<br>
>        }<br>
>     }<br>
><br>
> -   set_foreach(def->if_uses, entry) {<br>
> -      nir_if *if_stmt = (nir_if *)entry->key;<br>
> -<br>
> -      /* For if statements, we consider the block to be the one immediately<br>
> -       * preceding the if CF node.<br>
> -       */<br>
> -      nir_block *pred_block =<br>
> -         nir_cf_node_as_block(nir_cf_node_prev(&if_stmt->cf_node));<br>
> -<br>
> -      lca = nir_dominance_lca(lca, pred_block);<br>
> -   }<br>
> -<br>
>     /* Some instructions may never be used.  We'll just leave them scheduled<br>
>      * early and let dead code clean them up.<br>
>      */<br>
> diff --git a/src/glsl/nir/nir_opt_global_to_local.c b/src/glsl/nir/nir_opt_global_to_local.c<br>
> index 00db37b..f7b7a04 100644<br>
> --- a/src/glsl/nir/nir_opt_global_to_local.c<br>
> +++ b/src/glsl/nir/nir_opt_global_to_local.c<br>
> @@ -59,17 +59,6 @@ global_to_local(nir_register *reg)<br>
>        }<br>
>     }<br>
><br>
> -   set_foreach(reg->if_uses, entry) {<br>
> -      nir_if *if_stmt = (nir_if *) entry->key;<br>
> -      nir_function_impl *if_impl = nir_cf_node_get_function(&if_stmt->cf_node);<br>
> -      if (impl != NULL) {<br>
> -         if (impl != if_impl)<br>
> -            return false;<br>
> -      } else {<br>
> -         impl = if_impl;<br>
> -      }<br>
> -   }<br>
> -<br>
>     if (impl == NULL) {<br>
>        /* this instruction is never used/defined, delete it */<br>
>        nir_reg_remove(reg);<br>
> diff --git a/src/glsl/nir/nir_opt_peephole_select.c b/src/glsl/nir/nir_opt_peephole_select.c<br>
> index ab08f28..d404658 100644<br>
> --- a/src/glsl/nir/nir_opt_peephole_select.c<br>
> +++ b/src/glsl/nir/nir_opt_peephole_select.c<br>
> @@ -71,10 +71,6 @@ are_all_move_to_phi(nir_block *block)<br>
>        if (!mov->dest.dest.is_ssa)<br>
>           return false;<br>
><br>
> -      /* It cannot have any if-uses */<br>
> -      if (mov->dest.dest.ssa.if_uses->entries != 0)<br>
> -         return false;<br>
> -<br>
>        /* The only uses of this definition must be phi's in the successor */<br>
>        struct set_entry *entry;<br>
>        set_foreach(mov->dest.dest.ssa.uses, entry) {<br>
> @@ -103,11 +99,11 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)<br>
>     if (nir_cf_node_is_first(&block->cf_node))<br>
>        return true;<br>
><br>
> -   nir_cf_node *prev_node = nir_cf_node_prev(&block->cf_node);<br>
> -   if (prev_node->type != nir_cf_node_if)<br>
> +   nir_cf_node *if_node = nir_cf_node_prev(&block->cf_node);<br>
> +   if (if_node->type != nir_cf_node_if)<br>
>        return true;<br>
><br>
> -   nir_if *if_stmt = nir_cf_node_as_if(prev_node);<br>
> +   nir_if *if_stmt = nir_cf_node_as_if(if_node);<br>
>     nir_cf_node *then_node = nir_if_first_then_node(if_stmt);<br>
>     nir_cf_node *else_node = nir_if_first_else_node(if_stmt);<br>
><br>
> @@ -129,13 +125,21 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)<br>
>      * selects.<br>
>      */<br>
><br>
> +   nir_cf_node *prev_node = nir_cf_node_prev(if_node);<br>
> +   assert(prev_node->type == nir_cf_node_block);<br>
> +   nir_block *prev_block = nir_cf_node_as_block(prev_node);<br>
> +   nir_instr *if_instr = nir_block_last_instr(prev_block);<br>
> +   assert(if_instr->type == nir_instr_type_jump);<br>
> +   nir_jump_instr *if_jump_instr = nir_instr_as_jump(if_instr);<br>
> +   assert(if_jump_instr->type == nir_jump_if);<br>
> +<br>
>     nir_foreach_instr_safe(block, instr) {<br>
>        if (instr->type != nir_instr_type_phi)<br>
>           break;<br>
><br>
>        nir_phi_instr *phi = nir_instr_as_phi(instr);<br>
>        nir_alu_instr *sel = nir_alu_instr_create(state->mem_ctx, nir_op_bcsel);<br>
> -      nir_src_copy(&sel->src[0].src, &if_stmt->condition, state->mem_ctx);<br>
> +      nir_src_copy(&sel->src[0].src, &if_jump_instr->if_src, state->mem_ctx);<br>
>        /* Splat the condition to all channels */<br>
>        memset(sel->src[0].swizzle, 0, sizeof sel->src[0].swizzle);<br>
><br>
> @@ -172,6 +176,7 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)<br>
>        nir_instr_remove(&phi->instr);<br>
>     }<br>
><br>
> +   nir_instr_remove(&if_jump_instr->instr);<br>
>     nir_cf_node_remove(&if_stmt->cf_node);<br>
>     state->progress = true;<br>
><br>
> diff --git a/src/glsl/nir/nir_print.c b/src/glsl/nir/nir_print.c<br>
> index 6a3c6a0..44468eb 100644<br>
> --- a/src/glsl/nir/nir_print.c<br>
> +++ b/src/glsl/nir/nir_print.c<br>
> @@ -538,6 +538,11 @@ print_jump_instr(nir_jump_instr *instr, FILE *fp)<br>
>     case nir_jump_return:<br>
>        fprintf(fp, "return");<br>
>        break;<br>
> +<br>
> +   case nir_jump_if:<br>
> +      fprintf(fp, "if ");<br>
> +      print_src(&instr->if_src, fp);<br>
> +      break;<br>
>     }<br>
>  }<br>
><br>
> @@ -682,9 +687,7 @@ static void<br>
>  print_if(nir_if *if_stmt, print_var_state *state, unsigned tabs, FILE *fp)<br>
>  {<br>
>     print_tabs(tabs, fp);<br>
> -   fprintf(fp, "if ");<br>
> -   print_src(&if_stmt->condition, fp);<br>
> -   fprintf(fp, " {\n");<br>
> +   fprintf(fp, "if {\n");<br>
>     foreach_list_typed(nir_cf_node, node, node, &if_stmt->then_list) {<br>
>        print_cf_node(node, state, tabs + 1, fp);<br>
>     }<br>
> diff --git a/src/glsl/nir/nir_to_ssa.c b/src/glsl/nir/nir_to_ssa.c<br>
> index 47cf453..ebf7fc9 100644<br>
> --- a/src/glsl/nir/nir_to_ssa.c<br>
> +++ b/src/glsl/nir/nir_to_ssa.c<br>
> @@ -143,7 +143,6 @@ typedef struct {<br>
>     reg_state *states;<br>
>     void *mem_ctx;<br>
>     nir_instr *parent_instr;<br>
> -   nir_if *parent_if;<br>
>     nir_function_impl *impl;<br>
><br>
>     /* map from SSA value -> original register */<br>
> @@ -193,10 +192,8 @@ rewrite_use(nir_src *src, void *_state)<br>
>     src->is_ssa = true;<br>
>     src->ssa = get_ssa_src(src->reg.reg, state);<br>
><br>
> -   if (state->parent_instr)<br>
> -      _mesa_set_add(src->ssa->uses, state->parent_instr);<br>
> -   else<br>
> -      _mesa_set_add(src->ssa->if_uses, state->parent_if);<br>
> +   _mesa_set_add(src->ssa->uses, state->parent_instr);<br>
> +<br>
>     return true;<br>
>  }<br>
><br>
> @@ -433,15 +430,6 @@ rewrite_block(nir_block *block, rewrite_state *state)<br>
>        rewrite_instr_forward(instr, state);<br>
>     }<br>
><br>
> -   if (block != state->impl->end_block &&<br>
> -       !nir_cf_node_is_last(&block->cf_node) &&<br>
> -       nir_cf_node_next(&block->cf_node)->type == nir_cf_node_if) {<br>
> -      nir_if *if_stmt = nir_cf_node_as_if(nir_cf_node_next(&block->cf_node));<br>
> -      state->parent_instr = NULL;<br>
> -      state->parent_if = if_stmt;<br>
> -      rewrite_use(&if_stmt->condition, state);<br>
> -   }<br>
> -<br>
>     if (block->successors[0])<br>
>        rewrite_phi_sources(block->successors[0], block, state);<br>
>     if (block->successors[1])<br>
> diff --git a/src/glsl/nir/nir_validate.c b/src/glsl/nir/nir_validate.c<br>
> index a3fe9d6..31b65f0 100644<br>
> --- a/src/glsl/nir/nir_validate.c<br>
> +++ b/src/glsl/nir/nir_validate.c<br>
> @@ -46,7 +46,7 @@ typedef struct {<br>
>      * equivalent to the uses and defs in nir_register, but built up by the<br>
>      * validator. At the end, we verify that the sets have the same entries.<br>
>      */<br>
> -   struct set *uses, *if_uses, *defs;<br>
> +   struct set *uses, *defs;<br>
>     nir_function_impl *where_defined; /* NULL for global registers */<br>
>  } reg_validate_state;<br>
><br>
> @@ -55,7 +55,7 @@ typedef struct {<br>
>      * equivalent to the uses in nir_ssa_def, but built up by the validator.<br>
>      * At the end, we verify that the sets have the same entries.<br>
>      */<br>
> -   struct set *uses, *if_uses;<br>
> +   struct set *uses;<br>
>     nir_function_impl *where_defined;<br>
>  } ssa_def_validate_state;<br>
><br>
> @@ -107,16 +107,8 @@ validate_reg_src(nir_reg_src *src, validate_state *state)<br>
><br>
>     reg_validate_state *reg_state = (reg_validate_state *) entry->data;<br>
><br>
> -   if (state->instr) {<br>
> -      _mesa_set_add(reg_state->uses, state->instr);<br>
> -<br>
> -      assert(_mesa_set_search(src->reg->uses, state->instr));<br>
> -   } else {<br>
> -      assert(state->if_stmt);<br>
> -      _mesa_set_add(reg_state->if_uses, state->if_stmt);<br>
> -<br>
> -      assert(_mesa_set_search(src->reg->if_uses, state->if_stmt));<br>
> -   }<br>
> +   _mesa_set_add(reg_state->uses, state->instr);<br>
> +   assert(_mesa_set_search(src->reg->uses, state->instr));<br>
><br>
>     if (!src->reg->is_global) {<br>
>        assert(reg_state->where_defined == state->impl &&<br>
> @@ -149,16 +141,8 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state)<br>
>     assert(def_state->where_defined == state->impl &&<br>
>            "using an SSA value defined in a different function");<br>
><br>
> -   if (state->instr) {<br>
> -      _mesa_set_add(def_state->uses, state->instr);<br>
> -<br>
> -      assert(_mesa_set_search(def->uses, state->instr));<br>
> -   } else {<br>
> -      assert(state->if_stmt);<br>
> -      _mesa_set_add(def_state->if_uses, state->if_stmt);<br>
> -<br>
> -      assert(_mesa_set_search(def->if_uses, state->if_stmt));<br>
> -   }<br>
> +   _mesa_set_add(def_state->uses, state->instr);<br>
> +   assert(_mesa_set_search(def->uses, state->instr));<br>
><br>
>     /* TODO validate that the use is dominated by the definition */<br>
>  }<br>
> @@ -243,8 +227,6 @@ validate_ssa_def(nir_ssa_def *def, validate_state *state)<br>
>     def_state->where_defined = state->impl;<br>
>     def_state->uses = _mesa_set_create(def_state, _mesa_hash_pointer,<br>
>                                        _mesa_key_pointer_equal);<br>
> -   def_state->if_uses = _mesa_set_create(def_state, _mesa_hash_pointer,<br>
> -                                         _mesa_key_pointer_equal);<br>
>     _mesa_hash_table_insert(state->ssa_defs, def, def_state);<br>
>  }<br>
><br>
> @@ -457,6 +439,18 @@ validate_ssa_undef_instr(nir_ssa_undef_instr *instr, validate_state *state)<br>
>  }<br>
><br>
>  static void<br>
> +validate_jump_instr(nir_jump_instr *instr, validate_state *state)<br>
> +{<br>
> +   assert(&instr->instr == nir_block_last_instr(instr->instr.block));<br>
> +<br>
> +   if (instr->type == nir_jump_if) {<br>
> +      validate_src(&instr->if_src, state);<br>
> +      nir_cf_node *if_node = nir_cf_node_next(&instr->instr.block->cf_node);<br>
> +      assert(if_node->type == nir_cf_node_if);<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
>  validate_phi_instr(nir_phi_instr *instr, validate_state *state)<br>
>  {<br>
>     /*<br>
> @@ -508,6 +502,7 @@ validate_instr(nir_instr *instr, validate_state *state)<br>
>        break;<br>
><br>
>     case nir_instr_type_jump:<br>
> +      validate_jump_instr(nir_instr_as_jump(instr), state);<br>
>        break;<br>
><br>
>     default:<br>
> @@ -588,8 +583,18 @@ validate_block(nir_block *block, validate_state *state)<br>
>     }<br>
><br>
>     if (!exec_list_is_empty(&block->instr_list) &&<br>
> -       nir_block_last_instr(block)->type == nir_instr_type_jump)<br>
> -      assert(block->successors[1] == NULL);<br>
> +       nir_block_last_instr(block)->type == nir_instr_type_jump) {<br>
> +      switch (nir_instr_as_jump(nir_block_last_instr(block))->type) {<br>
> +      case nir_jump_break:<br>
> +      case nir_jump_continue:<br>
> +      case nir_jump_return:<br>
> +         assert(block->successors[1] == NULL);<br>
> +         break;<br>
> +      case nir_jump_if:<br>
> +         assert(nir_cf_node_next(&block->cf_node)->type == nir_cf_node_if);<br>
> +         break;<br>
> +      }<br>
> +   }<br>
>  }<br>
><br>
>  static void<br>
> @@ -607,12 +612,14 @@ validate_if(nir_if *if_stmt, validate_state *state)<br>
>     assert(&prev_block->successors[1]->cf_node ==<br>
>            nir_if_first_else_node(if_stmt));<br>
><br>
> +   nir_instr *if_instr = nir_block_last_instr(prev_block);<br>
> +   assert(if_instr->type == nir_instr_type_jump);<br>
> +   assert(nir_instr_as_jump(if_instr)->type == nir_jump_if);<br>
> +<br>
>     assert(!exec_node_is_tail_sentinel(if_stmt->cf_node.node.next));<br>
>     nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node);<br>
>     assert(next_node->type == nir_cf_node_block);<br>
><br>
> -   validate_src(&if_stmt->condition, state);<br>
> -<br>
>     assert(!exec_list_is_empty(&if_stmt->then_list));<br>
>     assert(!exec_list_is_empty(&if_stmt->else_list));<br>
><br>
> @@ -700,8 +707,6 @@ prevalidate_reg_decl(nir_register *reg, bool is_global, validate_state *state)<br>
>     reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state);<br>
>     reg_state->uses = _mesa_set_create(reg_state, _mesa_hash_pointer,<br>
>                                        _mesa_key_pointer_equal);<br>
> -   reg_state->if_uses = _mesa_set_create(reg_state, _mesa_hash_pointer,<br>
> -                                         _mesa_key_pointer_equal);<br>
>     reg_state->defs = _mesa_set_create(reg_state, _mesa_hash_pointer,<br>
>                                        _mesa_key_pointer_equal);<br>
><br>
> @@ -732,21 +737,6 @@ postvalidate_reg_decl(nir_register *reg, validate_state *state)<br>
>        abort();<br>
>     }<br>
><br>
> -   if (reg_state->if_uses->entries != reg->if_uses->entries) {<br>
> -      printf("extra entries in register if_uses:\n");<br>
> -      struct set_entry *entry;<br>
> -      set_foreach(reg->if_uses, entry) {<br>
> -         struct set_entry *entry2 =<br>
> -            _mesa_set_search(reg_state->if_uses, entry->key);<br>
> -<br>
> -         if (entry2 == NULL) {<br>
> -            printf("%p\n", entry->key);<br>
> -         }<br>
> -      }<br>
> -<br>
> -      abort();<br>
> -   }<br>
> -<br>
>     if (reg_state->defs->entries != reg->defs->entries) {<br>
>        printf("extra entries in register defs:\n");<br>
>        struct set_entry *entry;<br>
> @@ -801,21 +791,6 @@ postvalidate_ssa_def(nir_ssa_def *def, void *void_state)<br>
>        abort();<br>
>     }<br>
><br>
> -   if (def_state->if_uses->entries != def->if_uses->entries) {<br>
> -      printf("extra entries in SSA def uses:\n");<br>
> -      struct set_entry *entry;<br>
> -      set_foreach(def->if_uses, entry) {<br>
> -         struct set_entry *entry2 =<br>
> -            _mesa_set_search(def_state->if_uses, entry->key);<br>
> -<br>
> -         if (entry2 == NULL) {<br>
> -            printf("%p\n", entry->key);<br>
> -         }<br>
> -      }<br>
> -<br>
> -      abort();<br>
> -   }<br>
> -<br>
>     return true;<br>
>  }<br>
><br>
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
> index 388e636..a3841b9 100644<br>
> --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
> +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
> @@ -440,12 +440,6 @@ fs_visitor::nir_emit_cf_list(exec_list *list)<br>
>  void<br>
>  fs_visitor::nir_emit_if(nir_if *if_stmt)<br>
>  {<br>
> -   /* first, put the condition into f0 */<br>
> -   fs_inst *inst = emit(MOV(reg_null_d,<br>
> -                            retype(get_nir_src(if_stmt->condition),<br>
> -                                   BRW_REGISTER_TYPE_UD)));<br>
> -   inst->conditional_mod = BRW_CONDITIONAL_NZ;<br>
> -<br>
>     emit(IF(BRW_PREDICATE_NORMAL));<br>
><br>
>     nir_emit_cf_list(&if_stmt->then_list);<br>
> @@ -1759,6 +1753,15 @@ fs_visitor::nir_emit_jump(nir_jump_instr *instr)<br>
>     case nir_jump_continue:<br>
>        emit(BRW_OPCODE_CONTINUE);<br>
>        break;<br>
> +   case nir_jump_if: {<br>
> +      /* Move the condition to the flag register.  The nir_emit_if (which<br>
> +       * should immediately follow this) will use the flag register.<br>
> +       */<br>
> +      fs_reg cond = retype(get_nir_src(instr->if_src), BRW_REGISTER_TYPE_UD);<br>
> +      fs_inst *inst = emit(MOV(reg_null_d, cond));<br>
> +      inst->conditional_mod = BRW_CONDITIONAL_NZ;<br>
> +      break;<br>
> +   }<br>
>     case nir_jump_return:<br>
>     default:<br>
>        unreachable("unknown jump");<br>
> --<br>
> 2.3.0<br>
><br>
</div></div></blockquote></div><br></div></div>