[Mesa-dev] [PATCH 3/4] glsl: Slight change to the code generated by if-flattening
Ian Romanick
idr at freedesktop.org
Wed Aug 3 01:17:02 PDT 2011
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
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;
}
> 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);
>> + }
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk45A/4ACgkQX1gOwKyEAw/ULwCfQFRNLTaJpP/d6Yl/XDYVBZb3
igoAnjeB5Bj+Q46AAf2ctXQl3YT0lHFU
=khjV
-----END PGP SIGNATURE-----
More information about the mesa-dev
mailing list