[Mesa-dev] [PATCH 17/20] i965: Preserve CFG when deleting dead control flow.

Pohjolainen, Topi topi.pohjolainen at intel.com
Tue Aug 19 00:49:19 PDT 2014


On Thu, Jul 24, 2014 at 07:54:24PM -0700, Matt Turner wrote:
> This pass deletes an IF/ELSE/ENDIF or IF/ENDIF sequence, or the ELSE in
> an ELSE/ENDIF sequence.
> 
> In the typical case (where IF and ENDIF) aren't the only instructions in
> their basic blocks, we can simply remove the instructions (implicitly
> deleting the block containing only the ELSE), and attempt to merge
> blocks B0 and B2 together.
> 
> B0: ...
>     (+f0) if(8)
> B1: else(8)
> B2: endif(8)
>     ...
> 
> If the IF or ENDIF instructions are the only instructions in their
> respective basic blocks (which are deleted by the removal of the
> instructions), we'll want to instead merge the next blocks.
> 
> Both B0 and B2 are possibly removed by the removal of if & endif.
> Same situation for if/endif. E.g., in the following example we'd remove
> blocks B1 and B2, and then attempt to combine B0 and B3.
> 
> B0: ...
> B1: (+f0) if(8)
> B2: endif(8)
> B3: ...
> ---
>  .../drivers/dri/i965/brw_dead_control_flow.cpp     | 44 ++++++++++++++++++----
>  1 file changed, 36 insertions(+), 8 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_dead_control_flow.cpp b/src/mesa/drivers/dri/i965/brw_dead_control_flow.cpp
> index e6ace5c..56dc79e 100644
> --- a/src/mesa/drivers/dri/i965/brw_dead_control_flow.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_dead_control_flow.cpp
> @@ -42,7 +42,8 @@ dead_control_flow_eliminate(backend_visitor *v)
>  
>     v->calculate_cfg();
>  
> -   foreach_block (block, v->cfg) {
> +   foreach_block_safe (block, v->cfg) {
> +      bblock_t *if_block = NULL, *else_block = NULL, *endif_block = block;
>        bool found = false;
>  
>        /* ENDIF instructions, by definition, can only be found at the start of
> @@ -56,6 +57,7 @@ dead_control_flow_eliminate(backend_visitor *v)
>        backend_instruction *prev_inst = (backend_instruction *) endif_inst->prev;
>        if (prev_inst->opcode == BRW_OPCODE_ELSE) {
>           else_inst = prev_inst;
> +         else_block = (bblock_t *)endif_block->link.prev;
>           found = true;
>  
>           prev_inst = (backend_instruction *) prev_inst->prev;
> @@ -63,6 +65,8 @@ dead_control_flow_eliminate(backend_visitor *v)
>  
>        if (prev_inst->opcode == BRW_OPCODE_IF) {
>           if_inst = prev_inst;
> +         if_block = else_block != NULL ? (bblock_t *)else_block->link.prev
> +                                       : (bblock_t *)endif_block->link.prev;
>           found = true;
>        } else {
>           /* Don't remove the ENDIF if we didn't find a dead IF. */
> @@ -70,18 +74,42 @@ dead_control_flow_eliminate(backend_visitor *v)
>        }
>  
>        if (found) {
> -         if (if_inst)
> -            if_inst->remove();
> -         if (else_inst)
> -            else_inst->remove();
> -         if (endif_inst)
> -            endif_inst->remove();
> +         bblock_t *earlier_block = NULL, *later_block = NULL;
> +
> +         if (if_inst) {
> +            if (if_block->start_ip == if_block->end_ip) {
> +               earlier_block = (bblock_t *)if_block->link.prev;
> +            } else {
> +               earlier_block = if_block;
> +            }
> +            if_inst->remove(if_block);
> +         }
> +
> +         if (else_inst) {
> +            else_block->if_block->else_block = NULL;
> +            else_inst->remove(else_block);
> +         }
> +
> +         if (endif_inst) {
> +            if (endif_block->start_ip == endif_block->end_ip) {
> +               later_block = (bblock_t *)endif_block->link.next;
> +            } else {
> +               later_block = endif_block;
> +            }
> +            endif_inst->remove(endif_block);
> +         }
> +
> +         assert((earlier_block == NULL) == (later_block == NULL));
> +         if (earlier_block && earlier_block->can_combine_with(later_block)) {
> +            earlier_block->combine_with(later_block);

Now that we are using foreach_block_safe(), isn't next pointing to later_block
which gets removed here when its merged into earlier_block? I could be missing
something as I had some difficulty with the documentation in the previous
patch.

> +         }
> +
>           progress = true;
>        }
>     }
>  
>     if (progress)
> -      v->invalidate_live_intervals();
> +      v->invalidate_live_intervals(false);
>  
>     return progress;
>  }
> -- 
> 1.8.5.5
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list