~~This goes atop !764. The last three commits belong to this MR.~~
Since we want to get rid of loops and 'break's as much as possible, we try to move 'break's out of selection constructs as much as possible so it's easier to match them with loops. This MR introduces a few other tricks to help that.
-- v4: vkd3d-shader/ir: Move breaks out of selections again after having optimized loops. vkd3d-shader/ir: Append code to the non-breaking branch if there is breaking one. vkd3d-shader/ir: Prepare for changing the destination list in vsir_cfg_optimize_recurse().
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index e0928ff78..da23e2288 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4307,19 +4307,21 @@ static enum vkd3d_result vsir_cfg_append_loop(struct vsir_cfg *cfg,
static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list) { - struct vsir_cfg_structure_list new_list = {0}; + struct vsir_cfg_structure_list old_list = *list, *new_list = list; enum vkd3d_result ret; size_t i;
- for (i = 0; i < list->count; ++i) + memset(new_list, 0, sizeof(*new_list)); + + for (i = 0; i < old_list.count; ++i) { - struct vsir_cfg_structure *loop = &list->structures[i]; + struct vsir_cfg_structure *loop = &old_list.structures[i]; struct vsir_cfg_structure_list *loop_body;
if (loop->type != STRUCTURE_TYPE_LOOP) { - if ((ret = vsir_cfg_structure_list_append_from_region(&new_list, loop, 1)) < 0) - goto fail; + if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0) + goto out; memset(loop, 0, sizeof(*loop)); continue; } @@ -4328,8 +4330,8 @@ static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct
if (loop_body->count == 0) { - if ((ret = vsir_cfg_structure_list_append_from_region(&new_list, loop, 1)) < 0) - goto fail; + if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0) + goto out; memset(loop, 0, sizeof(*loop)); continue; } @@ -4337,22 +4339,19 @@ static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct vsir_cfg_remove_trailing_continue(cfg, loop_body, loop->u.loop.idx);
if ((ret = vsir_cfg_optimize_recurse(cfg, loop_body)) < 0) - goto fail; + goto out;
if ((ret = vsir_cfg_synthesize_selections(cfg, loop_body)) < 0) - goto fail; + goto out;
- if ((ret = vsir_cfg_append_loop(cfg, &new_list, loop)) < 0) - goto fail; + if ((ret = vsir_cfg_append_loop(cfg, new_list, loop)) < 0) + goto out; }
- vsir_cfg_structure_list_cleanup(list); - *list = new_list; + ret = VKD3D_OK;
- return VKD3D_OK; - -fail: - vsir_cfg_structure_list_cleanup(list); +out: + vsir_cfg_structure_list_cleanup(&old_list);
return ret; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index da23e2288..a95882797 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4315,7 +4315,7 @@ static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct
for (i = 0; i < old_list.count; ++i) { - struct vsir_cfg_structure *loop = &old_list.structures[i]; + struct vsir_cfg_structure *loop = &old_list.structures[i], *selection; struct vsir_cfg_structure_list *loop_body;
if (loop->type != STRUCTURE_TYPE_LOOP) @@ -4346,6 +4346,22 @@ static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct
if ((ret = vsir_cfg_append_loop(cfg, new_list, loop)) < 0) goto out; + + /* If the last pushed instruction is a selection and one of the branches terminates with a + * `break', start pushing to the other branch, in the hope of eventually push a `break' + * there too and be able to remove a loop. */ + if (new_list->count == 0) + continue; + + selection = &new_list->structures[new_list->count - 1]; + + if (selection->type == STRUCTURE_TYPE_SELECTION) + { + if (vsir_cfg_get_trailing_break(&selection->u.selection.if_body)) + new_list = &selection->u.selection.else_body; + else if (vsir_cfg_get_trailing_break(&selection->u.selection.else_body)) + new_list = &selection->u.selection.if_body; + } }
ret = VKD3D_OK;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index a95882797..6d428e22a 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -4200,6 +4200,25 @@ static enum vkd3d_result vsir_cfg_move_breaks_out_of_selections(struct vsir_cfg return VKD3D_OK; }
+static enum vkd3d_result vsir_cfg_move_breaks_out_of_selections_recursively(struct vsir_cfg *cfg, + struct vsir_cfg_structure_list *list) +{ + struct vsir_cfg_structure *trailing; + + if (list->count == 0) + return VKD3D_OK; + + trailing = &list->structures[list->count - 1]; + + if (trailing->type != STRUCTURE_TYPE_SELECTION) + return VKD3D_OK; + + vsir_cfg_move_breaks_out_of_selections_recursively(cfg, &trailing->u.selection.if_body); + vsir_cfg_move_breaks_out_of_selections_recursively(cfg, &trailing->u.selection.else_body); + + return vsir_cfg_move_breaks_out_of_selections(cfg, list); +} + static enum vkd3d_result vsir_cfg_synthesize_selections(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list) { @@ -4364,7 +4383,7 @@ static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct } }
- ret = VKD3D_OK; + ret = vsir_cfg_move_breaks_out_of_selections_recursively(cfg, list);
out: vsir_cfg_structure_list_cleanup(&old_list);
This merge request was approved by Henri Verbeet.