mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 04:48:08 +02:00
spirv: Fix handling of OpBranchConditional with same THEN and ELSE
When an OpBranchConditional that had two equal branches was parsed, we were treating it as a regular OpBranch. However this doesn't work well when there's an associated OpSelectionMerge. We ended up skipping marking the merge block as such, and depending on what was inside the construct we would end up trying to process the block twice. Fix this by keeping the vtn_if around, but when emitting NIR identify the two equal branch case. Fixes:9c2a11430e("spirv: Rewrite CFG construction") Closes: #3786, #4580 Reviewed-by: Yevhenii Kolesnikov <yevhenii.kolesnikov@globallogic.com> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> Acked-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9297> (cherry picked from commit64cb143b92)
This commit is contained in:
parent
b6d704d5a1
commit
aaee162781
3 changed files with 24 additions and 24 deletions
|
|
@ -337,7 +337,7 @@
|
|||
"description": "spirv: Fix handling of OpBranchConditional with same THEN and ELSE",
|
||||
"nominated": true,
|
||||
"nomination_type": 1,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": "9c2a11430e101b820ce8d605f3cc5b0593bb4c5e"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -722,26 +722,11 @@ vtn_process_block(struct vtn_builder *b,
|
|||
cond_val->type->type != glsl_bool_type(),
|
||||
"Condition must be a Boolean type scalar");
|
||||
|
||||
struct vtn_block *then_block = vtn_block(b, block->branch[2]);
|
||||
struct vtn_block *else_block = vtn_block(b, block->branch[3]);
|
||||
|
||||
if (then_block == else_block) {
|
||||
/* This is uncommon but it can happen. We treat this the same way as
|
||||
* an unconditional branch.
|
||||
*/
|
||||
block->branch_type = vtn_handle_branch(b, cf_parent, then_block);
|
||||
|
||||
if (block->branch_type == vtn_branch_type_none)
|
||||
return then_block;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct vtn_if *if_stmt = rzalloc(b, struct vtn_if);
|
||||
|
||||
if_stmt->node.type = vtn_cf_node_type_if;
|
||||
if_stmt->node.parent = cf_parent;
|
||||
if_stmt->condition = block->branch[1];
|
||||
if_stmt->header_block = block;
|
||||
list_inithead(&if_stmt->then_body);
|
||||
list_inithead(&if_stmt->else_body);
|
||||
|
||||
|
|
@ -759,16 +744,20 @@ vtn_process_block(struct vtn_builder *b,
|
|||
if_stmt->control = block->merge[2];
|
||||
}
|
||||
|
||||
struct vtn_block *then_block = vtn_block(b, block->branch[2]);
|
||||
if_stmt->then_type = vtn_handle_branch(b, &if_stmt->node, then_block);
|
||||
if (if_stmt->then_type == vtn_branch_type_none) {
|
||||
vtn_add_cfg_work_item(b, work_list, &if_stmt->node,
|
||||
&if_stmt->then_body, then_block);
|
||||
}
|
||||
|
||||
if_stmt->else_type = vtn_handle_branch(b, &if_stmt->node, else_block);
|
||||
if (if_stmt->else_type == vtn_branch_type_none) {
|
||||
vtn_add_cfg_work_item(b, work_list, &if_stmt->node,
|
||||
&if_stmt->else_body, else_block);
|
||||
struct vtn_block *else_block = vtn_block(b, block->branch[3]);
|
||||
if (then_block != else_block) {
|
||||
if_stmt->else_type = vtn_handle_branch(b, &if_stmt->node, else_block);
|
||||
if (if_stmt->else_type == vtn_branch_type_none) {
|
||||
vtn_add_cfg_work_item(b, work_list, &if_stmt->node,
|
||||
&if_stmt->else_body, else_block);
|
||||
}
|
||||
}
|
||||
|
||||
return if_stmt->merge_block;
|
||||
|
|
@ -1101,10 +1090,22 @@ vtn_emit_cf_list_structured(struct vtn_builder *b, struct list_head *cf_list,
|
|||
|
||||
case vtn_cf_node_type_if: {
|
||||
struct vtn_if *vtn_if = vtn_cf_node_as_if(node);
|
||||
const uint32_t *branch = vtn_if->header_block->branch;
|
||||
vtn_assert((branch[0] & SpvOpCodeMask) == SpvOpBranchConditional);
|
||||
|
||||
/* If both branches are the same, just emit the first block, which is
|
||||
* the only one we filled when building the CFG.
|
||||
*/
|
||||
if (branch[2] == branch[3]) {
|
||||
vtn_emit_cf_list_structured(b, &vtn_if->then_body,
|
||||
switch_fall_var, has_switch_break, handler);
|
||||
break;
|
||||
}
|
||||
|
||||
bool sw_break = false;
|
||||
|
||||
nir_if *nif =
|
||||
nir_push_if(&b->nb, vtn_get_nir_ssa(b, vtn_if->condition));
|
||||
nir_push_if(&b->nb, vtn_get_nir_ssa(b, branch[1]));
|
||||
|
||||
nif->control = vtn_selection_control(b, vtn_if);
|
||||
|
||||
|
|
|
|||
|
|
@ -181,14 +181,13 @@ struct vtn_loop {
|
|||
struct vtn_if {
|
||||
struct vtn_cf_node node;
|
||||
|
||||
uint32_t condition;
|
||||
|
||||
enum vtn_branch_type then_type;
|
||||
struct list_head then_body;
|
||||
|
||||
enum vtn_branch_type else_type;
|
||||
struct list_head else_body;
|
||||
|
||||
struct vtn_block *header_block;
|
||||
struct vtn_block *merge_block;
|
||||
|
||||
SpvSelectionControlMask control;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue