@@ -863,22 +863,72 @@ impl<'a> FuncLifting<'a> {
863
863
// HACK(eddyb) this takes advantage of `blocks` being an `IndexMap`,
864
864
// to iterate at the same time as mutating other entries.
865
865
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
+ }
867
916
917
+ let block = & blocks[ block_idx] ;
868
918
let is_trivial_branch = {
869
919
let Terminator { attrs, kind, inputs, targets, target_phi_values, merge } =
870
- original_terminator ;
920
+ & block . terminator ;
871
921
872
- * attrs == AttrSet :: default ( )
922
+ ( * attrs == AttrSet :: default ( )
873
923
&& matches ! ( * * kind, cfg:: ControlInstKind :: Branch )
874
924
&& inputs. is_empty ( )
875
925
&& targets. len ( ) == 1
876
926
&& target_phi_values. is_empty ( )
877
- && merge. is_none ( )
927
+ && merge. is_none ( ) )
928
+ . then ( || targets[ 0 ] )
878
929
} ;
879
930
880
- if is_trivial_branch {
881
- let target = original_terminator. targets [ 0 ] ;
931
+ if let Some ( target) = is_trivial_branch {
882
932
let target_use_count = use_counts. get_mut ( & target) . unwrap ( ) ;
883
933
884
934
if * target_use_count == 1 {
0 commit comments