@@ -863,22 +863,72 @@ impl<'a> FuncLifting<'a> {
863863 // HACK(eddyb) this takes advantage of `blocks` being an `IndexMap`,
864864 // to iterate at the same time as mutating other entries.
865865 for block_idx in ( 0 ..blocks. len ( ) ) . rev ( ) {
866- let BlockLifting { terminator : original_terminator, .. } = & blocks[ block_idx] ;
866+ // HACK(eddyb) elide empty cases of an `if`-`else`/`switch`, as
867+ // SPIR-V allows their targets to just be the whole merge block
868+ // (the same one that `OpSelectionMerge` describes).
869+ let block = & blocks[ block_idx] ;
870+ if let ( cfg:: ControlInstKind :: SelectBranch ( _) , Some ( Merge :: Selection ( merge_point) ) ) =
871+ ( & * block. terminator . kind , block. terminator . merge )
872+ {
873+ for target_idx in 0 ..block. terminator . targets . len ( ) {
874+ let block = & blocks[ block_idx] ;
875+ let target = block. terminator . targets [ target_idx] ;
876+ if !block
877+ . terminator
878+ . target_phi_values
879+ . get ( & target)
880+ . copied ( )
881+ . unwrap_or_default ( )
882+ . is_empty ( )
883+ {
884+ continue ;
885+ }
886+
887+ let target_is_trivial_branch = {
888+ let BlockLifting {
889+ phis,
890+ insts,
891+ terminator :
892+ Terminator { attrs, kind, inputs, targets, target_phi_values, merge } ,
893+ } = & blocks[ & target] ;
894+
895+ ( phis. is_empty ( )
896+ && insts. iter ( ) . all ( |insts| insts. is_empty ( ) )
897+ && * attrs == AttrSet :: default ( )
898+ && matches ! ( * * kind, cfg:: ControlInstKind :: Branch )
899+ && inputs. is_empty ( )
900+ && targets. len ( ) == 1
901+ && target_phi_values. is_empty ( )
902+ && merge. is_none ( ) )
903+ . then ( || targets[ 0 ] )
904+ } ;
905+ if let Some ( target_of_target) = target_is_trivial_branch {
906+ // FIXME(eddyb) what does it mean for this to not be true?
907+ // (can it even happen?)
908+ if target_of_target == merge_point {
909+ blocks[ block_idx] . terminator . targets [ target_idx] = target_of_target;
910+ * use_counts. get_mut ( & target) . unwrap ( ) -= 1 ;
911+ * use_counts. get_mut ( & target_of_target) . unwrap ( ) += 1 ;
912+ }
913+ }
914+ }
915+ }
867916
917+ let block = & blocks[ block_idx] ;
868918 let is_trivial_branch = {
869919 let Terminator { attrs, kind, inputs, targets, target_phi_values, merge } =
870- original_terminator ;
920+ & block . terminator ;
871921
872- * attrs == AttrSet :: default ( )
922+ ( * attrs == AttrSet :: default ( )
873923 && matches ! ( * * kind, cfg:: ControlInstKind :: Branch )
874924 && inputs. is_empty ( )
875925 && targets. len ( ) == 1
876926 && target_phi_values. is_empty ( )
877- && merge. is_none ( )
927+ && merge. is_none ( ) )
928+ . then ( || targets[ 0 ] )
878929 } ;
879930
880- if is_trivial_branch {
881- let target = original_terminator. targets [ 0 ] ;
931+ if let Some ( target) = is_trivial_branch {
882932 let target_use_count = use_counts. get_mut ( & target) . unwrap ( ) ;
883933
884934 if * target_use_count == 1 {
0 commit comments