vkd3d-shader/ir: Materialize SSA registers to temporaries.

For simplicity PHI nodes are not currently handled.

The goal for this pass is to make the CFG structurizer simpler, because
it doesn't have to care about the more rigid rules SSA registers have
to satisfy than TEMP registers.

It is likely that the generated code will be harder for downstream
compilers to optimize and execute efficiently, so once a complete
structurizer is in place this pass should be removed, or at least
greatly reduced in scope.
This commit is contained in:
Giovanni Mascellani 2024-01-09 15:56:45 +01:00 committed by Alexandre Julliard
parent eb723a8d2b
commit e0d3e9c376
Notes: Alexandre Julliard 2024-02-06 23:42:19 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Conor McCarthy (@cmccarthy)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/607

View File

@ -2637,6 +2637,84 @@ fail:
return VKD3D_ERROR_OUT_OF_MEMORY;
}
static void materialize_ssas_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src);
/* This is idempotent: it can be safely applied more than once on the
* same register. */
static void materialize_ssas_to_temps_process_reg(struct vkd3d_shader_parser *parser, struct vkd3d_shader_register *reg)
{
unsigned int i;
if (reg->type == VKD3DSPR_SSA)
{
reg->type = VKD3DSPR_TEMP;
reg->idx[0].offset += parser->program.temp_count;
}
for (i = 0; i < reg->idx_count; ++i)
if (reg->idx[i].rel_addr)
materialize_ssas_to_temps_process_src_param(parser, reg->idx[i].rel_addr);
}
static void materialize_ssas_to_temps_process_dst_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_dst_param *dst)
{
materialize_ssas_to_temps_process_reg(parser, &dst->reg);
}
static void materialize_ssas_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src)
{
materialize_ssas_to_temps_process_reg(parser, &src->reg);
}
static enum vkd3d_result materialize_ssas_to_temps(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_instruction *instructions = NULL;
size_t ins_capacity = 0, ins_count = 0, i;
if (!reserve_instructions(&instructions, &ins_capacity, parser->program.instructions.count))
goto fail;
for (i = 0; i < parser->program.instructions.count; ++i)
{
struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i];
size_t j;
if (ins->handler_idx == VKD3DSIH_PHI)
{
WARN("Unhandled PHI when materializing SSA registers.\n");
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
"Unhandled PHI when materializing SSA registers.");
vkd3d_free(instructions);
return VKD3D_ERROR_NOT_IMPLEMENTED;
}
for (j = 0; j < ins->dst_count; ++j)
materialize_ssas_to_temps_process_dst_param(parser, &ins->dst[j]);
for (j = 0; j < ins->src_count; ++j)
materialize_ssas_to_temps_process_src_param(parser, &ins->src[j]);
if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1))
goto fail;
instructions[ins_count++] = *ins;
}
vkd3d_free(parser->program.instructions.elements);
parser->program.instructions.elements = instructions;
parser->program.instructions.capacity = ins_capacity;
parser->program.instructions.count = ins_count;
parser->program.temp_count += parser->program.ssa_count;
parser->program.ssa_count = 0;
return VKD3D_OK;
fail:
vkd3d_free(instructions);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
const struct vkd3d_shader_compile_info *compile_info)
{
@ -2652,6 +2730,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
{
if ((result = lower_switch_to_if_ladder(&parser->program)) < 0)
return result;
if ((result = materialize_ssas_to_temps(parser)) < 0)
return result;
}
else
{