@@ -2979,62 +2979,69 @@ impl BlockContext<'_> {
2979
2979
ref accept,
2980
2980
ref reject,
2981
2981
} => {
2982
- let condition_id = self . cached [ condition] ;
2982
+ // In spirv 1.6, in a conditional branch the two block ids
2983
+ // of the branches can't have the same label. If `accept`
2984
+ // and `reject` are both empty (e.g. in `if (condition) {}`)
2985
+ // merge id will be both labels. Because both branches are
2986
+ // empty, we can skip the if statement.
2987
+ if !( accept. is_empty ( ) && reject. is_empty ( ) ) {
2988
+ let condition_id = self . cached [ condition] ;
2989
+
2990
+ let merge_id = self . gen_id ( ) ;
2991
+ block. body . push ( Instruction :: selection_merge (
2992
+ merge_id,
2993
+ spirv:: SelectionControl :: NONE ,
2994
+ ) ) ;
2983
2995
2984
- let merge_id = self . gen_id ( ) ;
2985
- block. body . push ( Instruction :: selection_merge (
2986
- merge_id,
2987
- spirv:: SelectionControl :: NONE ,
2988
- ) ) ;
2996
+ let accept_id = if accept. is_empty ( ) {
2997
+ None
2998
+ } else {
2999
+ Some ( self . gen_id ( ) )
3000
+ } ;
3001
+ let reject_id = if reject. is_empty ( ) {
3002
+ None
3003
+ } else {
3004
+ Some ( self . gen_id ( ) )
3005
+ } ;
2989
3006
2990
- let accept_id = if accept. is_empty ( ) {
2991
- None
2992
- } else {
2993
- Some ( self . gen_id ( ) )
2994
- } ;
2995
- let reject_id = if reject. is_empty ( ) {
2996
- None
2997
- } else {
2998
- Some ( self . gen_id ( ) )
2999
- } ;
3007
+ self . function . consume (
3008
+ block,
3009
+ Instruction :: branch_conditional (
3010
+ condition_id,
3011
+ accept_id. unwrap_or ( merge_id) ,
3012
+ reject_id. unwrap_or ( merge_id) ,
3013
+ ) ,
3014
+ ) ;
3000
3015
3001
- self . function . consume (
3002
- block,
3003
- Instruction :: branch_conditional (
3004
- condition_id,
3005
- accept_id. unwrap_or ( merge_id) ,
3006
- reject_id. unwrap_or ( merge_id) ,
3007
- ) ,
3008
- ) ;
3016
+ if let Some ( block_id) = accept_id {
3017
+ // We can ignore the `BlockExitDisposition` returned here because,
3018
+ // even if `merge_id` is not actually reachable, it is always
3019
+ // referred to by the `OpSelectionMerge` instruction we emitted
3020
+ // earlier.
3021
+ let _ = self . write_block (
3022
+ block_id,
3023
+ accept,
3024
+ BlockExit :: Branch { target : merge_id } ,
3025
+ loop_context,
3026
+ debug_info,
3027
+ ) ?;
3028
+ }
3029
+ if let Some ( block_id) = reject_id {
3030
+ // We can ignore the `BlockExitDisposition` returned here because,
3031
+ // even if `merge_id` is not actually reachable, it is always
3032
+ // referred to by the `OpSelectionMerge` instruction we emitted
3033
+ // earlier.
3034
+ let _ = self . write_block (
3035
+ block_id,
3036
+ reject,
3037
+ BlockExit :: Branch { target : merge_id } ,
3038
+ loop_context,
3039
+ debug_info,
3040
+ ) ?;
3041
+ }
3009
3042
3010
- if let Some ( block_id) = accept_id {
3011
- // We can ignore the `BlockExitDisposition` returned here because,
3012
- // even if `merge_id` is not actually reachable, it is always
3013
- // referred to by the `OpSelectionMerge` instruction we emitted
3014
- // earlier.
3015
- let _ = self . write_block (
3016
- block_id,
3017
- accept,
3018
- BlockExit :: Branch { target : merge_id } ,
3019
- loop_context,
3020
- debug_info,
3021
- ) ?;
3022
- }
3023
- if let Some ( block_id) = reject_id {
3024
- // We can ignore the `BlockExitDisposition` returned here because,
3025
- // even if `merge_id` is not actually reachable, it is always
3026
- // referred to by the `OpSelectionMerge` instruction we emitted
3027
- // earlier.
3028
- let _ = self . write_block (
3029
- block_id,
3030
- reject,
3031
- BlockExit :: Branch { target : merge_id } ,
3032
- loop_context,
3033
- debug_info,
3034
- ) ?;
3043
+ block = Block :: new ( merge_id) ;
3035
3044
}
3036
-
3037
- block = Block :: new ( merge_id) ;
3038
3045
}
3039
3046
Statement :: Switch {
3040
3047
selector,
0 commit comments