[Mesa-dev] [PATCH 3/4] glsl: Slight change to the code generated by if-flattening

Ian Romanick idr at freedesktop.org
Wed Aug 3 12:16:34 PDT 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 08/03/2011 01:17 AM, Ian Romanick wrote:
> On 08/02/2011 07:45 PM, Eric Anholt wrote:
>> On Tue,  2 Aug 2011 17:52:03 -0700, "Ian Romanick" <idr at freedesktop.org> wrote:
>>> From: Ian Romanick <ian.d.romanick at intel.com>
>>>
>>> Now the condition (for the then-clause) and the inverse condition (for
>>> the else-clause) get written to sepearate temporary variables.  In the
> 
>> "separate"
> 
>>> presense of complex conditions, this may result in more code being
>>> generated.
> 
>> I hope s/more/less/
> 
> More.  If the original if-statement was
> 
>     if (a && b && c && d && e) {
>         ...
>     } else {
>         ...
>     }
> 
> The lowered code will be
> 
>    if_to_cond_assign_then = a && b && c && d && e;
>    ...
>    if_to_cond_assign_else = !(a && b && c && d && e);
>    ...
> 
> Of course, pretty much the only time I see complex conditions like this
> in shaders is when one of our lowering passes does something stupid. :)
> 
> The assignments get generated in this way because of the way the
> follow-on patch changes lowering of nested if-statements.  In that
> patch, code like
> 
>     if (x) {
>         if (a && b && c && d && e) {
>             ...
>         } else {
>             ...
>         }
>     }
> 
> becomes
> 
>    if_to_cond_assign_then at 1 = x;
>    if_to_cond_assign_then at 2 = a && b && c && d && e && x;
>    ...
>    if_to_cond_assign_else at 2 = !(a && b && c && d && e) && x;
>    ...
> 
> I tried a couple of ways of generating the condition to a temporary, but
> it got complex to manage.  I basically was doing CSE by hand.
> 
> However, it now occurs to me that this change is completely bogus.  Ugh.
>  The following code will do the wrong thing:
> 
>     x = <some uniform containing the value 7>
>     if (x > 6) {
>         x = 5;
>     } else {
>         discard;
>     }

Scratch that.  That's what I get for 1) editing commit message through
57 versions of a patch and 2) responding to review comments at 1am.  The
code actually generated is:

    if_to_cond_assign_then at 1 = x;
    if_to_cond_assign_then at 2 = a && b && c && d && e && x;
    ...
    if_to_cond_assign_else at 2 = !if_to_cond_assign_then at 2 && x;
    ...

There are no extra instructions emitted (with or without CSE) in the
unnested case.

In the nested case if_to_cond_assign_then at 2 is live "too long" and may
cause extra register pressure.  There may also be one extra instruction
generated because of the redundant '&& x'.

I've updated the commit messages (again) to reflect the real reality.

>> And this is all because we don't CSE, right.  We should get on that :)
> 
> Yes.  That's the main reason I didn't put more time into optimal
> management of complex conditions.  Based on my above observation, it
> seems I'll have to do that any way.  Grr.
> 
>> Patch 1,2 get Reviewed-by: Eric Anholt <eric at anholt.net>
> 
>> Couple more comments below.
> 
>>> ---
>>>  src/glsl/lower_if_to_cond_assign.cpp |   62 ++++++++++++++++++++++-----------
>>>  1 files changed, 41 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/src/glsl/lower_if_to_cond_assign.cpp b/src/glsl/lower_if_to_cond_assign.cpp
>>> index 5c74bc1..3f82700 100644
>>> --- a/src/glsl/lower_if_to_cond_assign.cpp
>>> +++ b/src/glsl/lower_if_to_cond_assign.cpp
>>> @@ -136,7 +136,6 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
>>>        return visit_continue;
>>>  
>>>     bool found_control_flow = false;
>>> -   ir_variable *cond_var;
>>>     ir_assignment *assign;
>>>     ir_dereference_variable *deref;
>>>  
>>> @@ -154,31 +153,52 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
>>>  
>>>     void *mem_ctx = ralloc_parent(ir);
>>>  
>>> -   /* Store the condition to a variable so the assignment conditions are
>>> -    * simpler.
>>> +   /* Store the condition to a variable.  Move all of the instructions from
>>> +    * the then-clause if the if-statement.  Use the condition variable as a
> 
>> "of the if-statement"
> 
> Right.
> 
>>> +    * condition for all assignments.
>>>      */
>>> -   cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type,
>>> -				       "if_to_cond_assign_condition",
>>> -				       ir_var_temporary);
>>> -   ir->insert_before(cond_var);
>>> -
>>> -   deref = new(mem_ctx) ir_dereference_variable(cond_var);
>>> -   assign = new(mem_ctx) ir_assignment(deref,
>>> -				       ir->condition, NULL);
>>> +   ir_variable *const then_var =
>>> +      new(mem_ctx) ir_variable(glsl_type::bool_type,
>>> +			       "if_to_cond_assign_then",
>>> +			       ir_var_temporary);
>>> +   ir->insert_before(then_var);
>>> +
>>> +   ir_dereference_variable *then_cond =
>>> +      new(mem_ctx) ir_dereference_variable(then_var);
>>> +
>>> +   assign = new(mem_ctx) ir_assignment(then_cond, ir->condition);
>>>     ir->insert_before(assign);
>>>  
>>> -   /* Now, move all of the instructions out of the if blocks, putting
>>> -    * conditions on assignments.
>>> -    */
>>> -   move_block_to_cond_assign(mem_ctx, ir, deref,
>>> +   move_block_to_cond_assign(mem_ctx, ir, then_cond,
>>>  			     &ir->then_instructions);
>>>  
>>> -   ir_rvalue *inverse =
>>> -      new(mem_ctx) ir_expression(ir_unop_logic_not,
>>> -				 glsl_type::bool_type,
>>> -				 deref->clone(mem_ctx, NULL),
>>> -				 NULL);
>>> -   move_block_to_cond_assign(mem_ctx, ir, inverse, &ir->else_instructions);
>>> +   /* If there are instructions in the else-clause, store the inverse of the
>>> +    * condition to a variable.  Move all of the instructions from the
>>> +    * else-clause if the if-statement.  Use the (inverse) condition variable
>>> +    * as a condition for all assignments.
>>> +    */
>>> +   if (!ir->else_instructions.is_empty()) {
>>> +      ir_variable *const else_var =
>>> +	 new(mem_ctx) ir_variable(glsl_type::bool_type,
>>> +				  "if_to_cond_assign_else",
>>> +				  ir_var_temporary);
>>> +      ir->insert_before(else_var);
>>> +
>>> +      ir_dereference_variable *else_cond =
>>> +	 new(mem_ctx) ir_dereference_variable(else_var);
>>> +
>>> +      ir_rvalue *inverse =
>>> +	 new(mem_ctx) ir_expression(ir_unop_logic_not,
>>> +				    glsl_type::bool_type,
>>> +				    then_cond->clone(mem_ctx, NULL),
>>> +				    NULL);
> 
>> Could drop the bool_type on ir_expression()
> 
> Ah, right.  I had copy-and-pasted some other code from this file that
> predated that version of the constructor.
> 
>>> +      assign = new(mem_ctx) ir_assignment(else_cond, inverse);
>>> +      ir->insert_before(assign);
>>> +
>>> +      move_block_to_cond_assign(mem_ctx, ir, else_cond,
>>> +				&ir->else_instructions);
>>> +   }
_______________________________________________
mesa-dev mailing list
mesa-dev at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk45npEACgkQX1gOwKyEAw/I9QCbBbv4LSNfsbqPfO7VqxH+BXuS
sgMAn1FVzB4vJ3ITrF6JF87QGi7S52Zt
=+MpS
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list