@@ -863,22 +863,70 @@ 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+ && target_of_target == merge_point
907+ {
908+ blocks[ block_idx] . terminator . targets [ target_idx] = target_of_target;
909+ * use_counts. get_mut ( & target) . unwrap ( ) -= 1 ;
910+ * use_counts. get_mut ( & target_of_target) . unwrap ( ) += 1 ;
911+ }
912+ }
913+ }
867914
915+ let block = & blocks[ block_idx] ;
868916 let is_trivial_branch = {
869917 let Terminator { attrs, kind, inputs, targets, target_phi_values, merge } =
870- original_terminator ;
918+ & block . terminator ;
871919
872- * attrs == AttrSet :: default ( )
920+ ( * attrs == AttrSet :: default ( )
873921 && matches ! ( * * kind, cfg:: ControlInstKind :: Branch )
874922 && inputs. is_empty ( )
875923 && targets. len ( ) == 1
876924 && target_phi_values. is_empty ( )
877- && merge. is_none ( )
925+ && merge. is_none ( ) )
926+ . then ( || targets[ 0 ] )
878927 } ;
879928
880- if is_trivial_branch {
881- let target = original_terminator. targets [ 0 ] ;
929+ if let Some ( target) = is_trivial_branch {
882930 let target_use_count = use_counts. get_mut ( & target) . unwrap ( ) ;
883931
884932 if * target_use_count == 1 {
0 commit comments