diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 5a71fd98209..9a8a88ae9a8 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -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); diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 8e27298a026..f2cfe144405 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -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;