[PATCH v5] d3dcompiler: Return an instruction list instead of a single instruction from nodes representing expressions.
Zebediah Figura
zfigura at codeweavers.com
Tue Feb 18 11:10:48 CST 2020
On 2/14/20 12:11 PM, Matteo Bruni wrote:
> On Thu, Feb 13, 2020 at 6:01 AM Zebediah Figura <z.figura12 at gmail.com> wrote:
>>
>> From: Zebediah Figura <zfigura at codeweavers.com>
>>
>> Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
>> ---
>> v2: don't drop all of the struct initializer elements on the floor
>> v3: style tweak, clarify loop_condition()
>> v4: fix append_conditional_break(); remove confusing uses of append_unop()
>> v5: don't drop all of the variable initializer instructions on the floor
>
> Patch looks great! There should be a separate signoff email on the
> way, but it also made me think about a few random things WRT the
> compiler in general. Nothing to necessarly act on. Anyway, a couple of
> comments inline...
>
>> -static struct hlsl_ir_if *loop_condition(struct list *cond_list)
>> +static BOOL append_conditional_break(struct list *cond_list)
>> {
>> - struct hlsl_ir_node *cond, *not_cond;
>> - struct hlsl_ir_if *out_cond;
>> + struct hlsl_ir_node *condition, *not;
>> struct hlsl_ir_jump *jump;
>> - unsigned int count = list_count(cond_list);
>> + struct hlsl_ir_if *iff;
>>
>> - if (!count)
>> - return NULL;
>> - if (count != 1)
>> - ERR("Got multiple expressions in a for condition.\n");
>> + /* E.g. "for (i = 0; ; ++i)". */
>> + if (!list_count(cond_list))
>> + return TRUE;
>>
>> - cond = LIST_ENTRY(list_head(cond_list), struct hlsl_ir_node, entry);
>> - out_cond = d3dcompiler_alloc(sizeof(*out_cond));
>> - if (!out_cond)
>> + condition = node_from_list(cond_list);
>> + if (!(not = new_unary_expr(HLSL_IR_UNOP_LOGIC_NOT, condition, condition->loc)))
>> {
>> ERR("Out of memory.\n");
>> - return NULL;
>> + return FALSE;
>> }
>> - out_cond->node.type = HLSL_IR_IF;
>> - if (!(not_cond = new_unary_expr(HLSL_IR_UNOP_LOGIC_NOT, cond, cond->loc)))
>> + list_add_tail(cond_list, ¬->entry);
>> +
>> + if (!(iff = d3dcompiler_alloc(sizeof(*iff))))
>> {
>> ERR("Out of memory.\n");
>> - d3dcompiler_free(out_cond);
>> - return NULL;
>> + return FALSE;
>> }
>> - out_cond->condition = not_cond;
>> - jump = d3dcompiler_alloc(sizeof(*jump));
>> - if (!jump)
>> + iff->node.type = HLSL_IR_IF;
>> + iff->condition = not;
>> + list_add_tail(cond_list, &iff->node.entry);
>> +
>> + if (!(iff->then_instrs = d3dcompiler_alloc(sizeof(*iff->then_instrs))))
>> {
>> ERR("Out of memory.\n");
>> - d3dcompiler_free(out_cond);
>> - d3dcompiler_free(not_cond);
>> - return NULL;
>> + return FALSE;
>> }
>> - jump->node.type = HLSL_IR_JUMP;
>> - jump->type = HLSL_IR_JUMP_BREAK;
>> - out_cond->then_instrs = d3dcompiler_alloc(sizeof(*out_cond->then_instrs));
>> - if (!out_cond->then_instrs)
>> + list_init(iff->then_instrs);
>
> then_instrs and else_instrs lists could be stored inline in struct
> hlsl_ir_jump. We'd need to be more careful when copying or moving the
> instruction around though.
I think you're right, yes.
>
>> +
>> + if (!(jump = d3dcompiler_alloc(sizeof(*jump))))
>> {
>> ERR("Out of memory.\n");
>> - d3dcompiler_free(out_cond);
>> - d3dcompiler_free(not_cond);
>> - d3dcompiler_free(jump);
>> - return NULL;
>> + return FALSE;
>> }
>> - list_init(out_cond->then_instrs);
>> - list_add_head(out_cond->then_instrs, &jump->node.entry);
>> -
>> - return out_cond;
>> + jump->node.type = HLSL_IR_JUMP;
>> + jump->type = HLSL_IR_JUMP_BREAK;
>> + list_add_head(iff->then_instrs, &jump->node.entry);
>> + return TRUE;
>> }
>
> Something unrelated to the patch that occurred to me while reading
> this. It seems like it might be useful to have "builder" functions
> (one for each instruction type) that allocate an instruction and
> initialize it with the relevant values.
> I suspect though that I tried something like that in the past and
> didn't like the end result too much so maybe not. I guess what I'm
> saying is, keep it in mind going forward and see if it makes sense.
Yeah, I tend to prefer that approach. It's not something I'd done yet,
but I probably will at least try.
>
> BTW, one nice (if mostly incidental) thing about the switch to a flat
> IR is clear here: you don't need to release the intermediate
> instructions on error.
>
>> @@ -1764,18 +1793,17 @@ selection_statement: KW_IF '(' expr ')' if_body
>> }
>> instr->node.type = HLSL_IR_IF;
>> set_location(&instr->node.loc, &@1);
>> - instr->condition = $3;
>> + instr->condition = node_from_list($3);
>> instr->then_instrs = $5.then_instrs;
>> instr->else_instrs = $5.else_instrs;
>> - if ($3->data_type->dimx > 1 || $3->data_type->dimy > 1)
>> + if (instr->condition->data_type->dimx > 1 || instr->condition->data_type->dimy > 1)
>> {
>> hlsl_report_message(instr->node.loc.file, instr->node.loc.line,
>> instr->node.loc.col, HLSL_LEVEL_ERROR,
>> "if condition requires a scalar");
>> }
>> - $$ = d3dcompiler_alloc(sizeof(*$$));
>> - list_init($$);
>> - list_add_head($$, &instr->node.entry);
>> + $$ = $3;
>> + list_add_tail($$, &instr->node.entry);
>> }
>
> We could have then_instrs and else_instrs (and the likes in the other
> control flow instructions) be "basic block" structures instead of
> plain lists, with room for additional data. Not sure how useful it
> would be in practice, you probably have a better idea by now.
>
Actually control flow is not really something I'd put a lot of thought
into yet :-/
That said, I think most of what needs to go into a basic block structure
tends to be for optimization purposes (where optimization can even mean
"not having a terrible RA"), which is not something I've been hugely
concerned with as yet.
More information about the wine-devel
mailing list