[Mesa-dev] [PATCH RFC 07/11] glsl: add SSA infrastructure
Connor Abbott
cwabbott0 at gmail.com
Wed Feb 5 09:08:21 PST 2014
On Tue, Jan 28, 2014 at 2:45 PM, Paul Berry <stereotype441 at gmail.com> wrote:
> On 22 January 2014 09:16, Connor Abbott <cwabbott0 at gmail.com> wrote:
>
>> diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
>> index cb732a5..7075579 100644
>> --- a/src/glsl/ir_clone.cpp
>> +++ b/src/glsl/ir_clone.cpp
>> @@ -40,7 +40,15 @@ ir_rvalue::clone(void *mem_ctx, struct hash_table *ht)
>> const
>> ir_variable *
>> ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
>> {
>> - ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name,
>> + ir_variable *var;
>> +
>> + if (ht) {
>> + var = (ir_variable *)hash_table_find(ht, this);
>> + if (var)
>> + return var;
>> + }
>>
>
> Can you add a comment explaining why it's necessary to do a hashtable
> lookup now? (I'm guessing it's because a phi node can refer to an SSA
> temporary that occurs later in the instruction stream, and therefore when
> we go to clone an SSA temporary variable, it's possible that we've already
> cloned it, but I'm not 100% certain about that).
>
Yeah, that's right. Phi nodes at the beginning of loops must be able to
refer to SSA temporaries created during the loop, which means that
variables may be referenced by ir_phi_loop_begin before they are defined.
So, if we clone an ir_phi_loop_begin object, and therefore clone a variable
that it references that's defined inside the loop, we need to make sure
that we use the same variable when we clone it's definition.
>
>
>> +
>> + var = new(mem_ctx) ir_variable(this->type, this->name,
>> (ir_variable_mode)
>> this->data.mode);
>>
>
> Let's fix up this line to align the opening paren with the initial "t" in
> "this->type".
>
>
>> +
>> +ir_phi *
>> +ir_phi::clone(void *mem_ctx, struct hash_table *ht) const
>> +{
>> + /* shouldn't get here */
>> + assert(0);
>> + return new(mem_ctx) ir_phi();
>> +}
>>
>
> There's no need to implement this function. If we leave it out (and leave
> out the corresponding declaration of clone() in ir.h's declaration of the
> ir_phi class), then ir_phi will be an abstract base class, and the compiler
> will make sure we never instantiate it.
>
>
>> +static ir_phi_jump_src *
>> +clone_phi_jump_src(ir_phi_jump_src *src, void *mem_ctx, struct
>> hash_table *ht)
>> +{
>> + ir_phi_jump_src *new_src = new(mem_ctx) ir_phi_jump_src();
>> + new_src->src = src->src->clone(mem_ctx, ht);
>> + new_src->jump = src->jump->clone(mem_ctx, ht);
>> + return new_src;
>>
>
> Let's make a constructor for ir_phi_jump_src that takes src and jump as
> arguments, so that we can just do:
>
> return new(mem_ctx) ir_phi_jump_src(src->src->clone(mem_ctx, ht),
> src->jump->clone(mem_ctx, ht));
>
> +
>> +
>> +void
>> +ir_print_visitor::visit(ir_phi *ir)
>> +{
>> + printf("error");
>> +}
>>
>
> I think if we make ir_phi an abstract base class (like I suggested
> earlier) we can drop this function entirely, as well as all the other
> visit(class ir_phi *) functions introduced in this patch.
>
>
>> +
>> +
>> +void
>> +ir_print_visitor::visit(ir_phi_if *ir)
>> +{
>> + printf("(phi\n");
>>
>
> For consistency with the class names, I'd prefer for this to be:
>
> printf("(phi_if\n");
>
>
>> +
>> + indentation++;
>> + indent();
>> + ir->dest->accept(this);
>> + printf("\n");
>> +
>> + indent();
>> + if (ir->if_src) {
>> + printf("%s ", unique_name(ir->if_src));
>> + } else {
>> + printf("(undefined) ");
>> + }
>> + if (ir->else_src) {
>> + printf("%s)", unique_name(ir->else_src));
>> + } else {
>> + printf("(undefined))");
>> + }
>>
>
> Would it be worth modifying unique_name() so that it returns "(undefined)"
> if it's passed a null pointer? That would allow us to simplify the 10
> lines above to:
>
> printf("%s %s", unique_name(ir->if_src), unique_name(ir->else_src));
>
> As well as similar simplifications in the functions below.
>
>
>> + indentation--;
>> +}
>> +
>> +void
>> +ir_print_visitor::print_phi_jump_src(ir_phi_jump_src *src)
>> +{
>> + printf("(%s ", unique_name(src->jump));
>>
>
> I think this is going to make the output IR difficult to follow, since it
> won't be obvious that "(break at 1 ...)" represents a phi node rather than a
> break instruction. I'd recommend changing this to:
>
> printf("(phi_jump_src %s ", unique_name(src->jump));
>
>
>> + if (src->src) {
>> + printf(" %s)\n", unique_name(src->src));
>> + } else {
>> + printf(" (undefined))\n");
>> + }
>> +}
>> +
>> +void
>> +ir_print_visitor::visit(ir_phi_loop_begin *ir)
>> +{
>> + printf("(phi\n");
>>
>
> As with ir_phi_if, I'd recommend changing this to:
>
> printf("(phi_loop_begin\n");
>
> A similar comment applies to ir_print_visitor::visit(ir_phi_loop_end *).
>
>
>> +
>> + indentation++;
>> + indent();
>> + ir->dest->accept(this);
>> + printf("\n");
>> +
>> + indent();
>> + if (ir->enter_src) {
>> + printf("%s ", unique_name(ir->enter_src));
>> + } else {
>> + printf("(undefined) ");
>> + }
>> + if (ir->repeat_src) {
>> + printf("%s\n", unique_name(ir->repeat_src));
>> + } else {
>> + printf("(undefined)\n");
>> + }
>> +
>> + foreach_list(n, &ir->continue_srcs) {
>> + ir_phi_jump_src *src = (ir_phi_jump_src *) n;
>> + indent();
>> + print_phi_jump_src(src);
>> + }
>> +
>> + indentation--;
>> + indent();
>> + printf(")");
>> +}
>> +
>> +
>> +
>> +
>> +ir_visitor_status
>> +ir_validate::visit(ir_phi_loop_begin *ir)
>> +{
>> + validate_phi_dest(ir, this->ht);
>> +
>> + /*
>> + * note: ir_phi_loop_begin is a special case in that variables may
>> be, and in
>> + * fact normally are, defined *after* they are used in everything
>> except
>> + * enter_src
>> + */
>> +
>> + if (ir->enter_src) {
>> + validate_var_use(ir->enter_src, this->ht, (void *) ir,
>> "ir_phi_loop_begin");
>> + }
>> +
>> + if ((ir->repeat_src == NULL) && (ir->repeat_src->as_variable() ==
>> NULL)) {
>>
>
> I think you mean "||" instead of "&&" here.
>
>
>> + printf("ir_phi_loop_begin @ %p does not specify a variable %p\n",
>> + (void *) ir, (void *) ir->repeat_src);
>> + abort();
>> + }
>> +
>> + foreach_list(n, &ir->continue_srcs) {
>> + ir_phi_jump_src *src = (ir_phi_jump_src *) n;
>> +
>> + if ((src->src == NULL) && (src->src->as_variable() == NULL)) {
>>
>
> Similar problem here.
>
>
>> + printf("ir_phi_loop_begin @ %p does not specify a variable %p\n",
>> + (void *) ir, (void *) src->src);
>> + abort();
>> + }
>> + }
>> +
>> + return visit_continue;
>> +}
>>
>
> I can think of a few other validation checks that would be nice to have:
>
> - Verify that variables of type ir_var_temporary_ssa can only appear
> inside an ir_assignment, ir_phi, or an ir_call (they don't appear isolated
> in the instruction stream like non-SSA variables).
>
> - Verify that variables whose type is not ir_var_temporary_ssa have all of
> the fields ssa_assignment, ssa_phi, and ssa_call set to null.
>
> How difficult would it be to add those checks?
>
>
> That completes my review of this patch. Incidentally, although I've had a
> lot of comments, I really like what I've seen so far in this series. Nice
> work!
>
> I'll try to get through the rest of the series as soon as I can.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20140205/c12d7223/attachment.html>
More information about the mesa-dev
mailing list