@@ -950,33 +950,46 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
950950 let loc = self . srcloc ( branch) ;
951951 self . finish_ir_inst ( loc) ;
952952 // Add block param outputs for current block.
953- self . lower_branch_blockparam_args ( bindex) ;
953+ match self . vcode . block_order ( ) . succ_indices ( bindex) . 1 {
954+ & [ succ] => self . lower_branch_blockparam_args ( branch, 0 , succ) ,
955+ succs => {
956+ // If there are multiple edges, either the destination has
957+ // multiple predecessors and there is a split critical edge
958+ // block that can hold these block params, or it has one
959+ // predecessor and doesn't need block params.
960+ debug_assert ! ( succs
961+ . iter( )
962+ . zip( self . f. dfg. insts[ branch] . branch_destination( & self . f. dfg. jump_tables) )
963+ . all( |( succ, block_call) | {
964+ matches!(
965+ self . vcode. block_order( ) . lowered_order( ) [ succ. index( ) ] ,
966+ LoweredBlock :: CriticalEdge { .. }
967+ ) || block_call. args_slice( & self . f. dfg. value_lists) . is_empty( )
968+ } ) ) ;
969+ let succs: SmallVec < [ BlockIndex ; 2 ] > = SmallVec :: from_slice ( succs) ;
970+ for succ in succs {
971+ self . vcode . add_succ ( succ, & [ ] ) ;
972+ }
973+ }
974+ }
954975 Ok ( ( ) )
955976 }
956977
957- fn lower_branch_blockparam_args ( & mut self , block : BlockIndex ) {
958- // TODO: why not make `block_order` public?
959- for succ_idx in 0 ..self . vcode . block_order ( ) . succ_indices ( block) . 1 . len ( ) {
960- // Avoid immutable borrow by explicitly indexing.
961- let ( opt_inst, succs) = self . vcode . block_order ( ) . succ_indices ( block) ;
962- let inst = opt_inst. expect ( "lower_branch_blockparam_args called on a critical edge!" ) ;
963- let succ = succs[ succ_idx] ;
964-
965- // The use of `succ_idx` to index `branch_destination` is valid on the assumption that
966- // the traversal order defined in `visit_block_succs` mirrors the order returned by
967- // `branch_destination`. If that assumption is violated, the branch targets returned
968- // here will not match the clif.
969- let branches = self . f . dfg . insts [ inst] . branch_destination ( & self . f . dfg . jump_tables ) ;
970- let branch_args = branches[ succ_idx] . args_slice ( & self . f . dfg . value_lists ) ;
971-
972- let mut branch_arg_vregs: SmallVec < [ Reg ; 16 ] > = smallvec ! [ ] ;
973- for & arg in branch_args {
974- let arg = self . f . dfg . resolve_aliases ( arg) ;
975- let regs = self . put_value_in_regs ( arg) ;
976- branch_arg_vregs. extend_from_slice ( regs. regs ( ) ) ;
977- }
978- self . vcode . add_succ ( succ, & branch_arg_vregs[ ..] ) ;
978+ fn lower_branch_blockparam_args ( & mut self , inst : Inst , succ_idx : usize , succ : BlockIndex ) {
979+ // The use of `succ_idx` to index `branch_destination` is valid on the assumption that
980+ // the traversal order defined in `visit_block_succs` mirrors the order returned by
981+ // `branch_destination`. If that assumption is violated, the branch targets returned
982+ // here will not match the clif.
983+ let branches = self . f . dfg . insts [ inst] . branch_destination ( & self . f . dfg . jump_tables ) ;
984+ let branch_args = branches[ succ_idx] . args_slice ( & self . f . dfg . value_lists ) ;
985+
986+ let mut branch_arg_vregs: SmallVec < [ Reg ; 16 ] > = smallvec ! [ ] ;
987+ for & arg in branch_args {
988+ let arg = self . f . dfg . resolve_aliases ( arg) ;
989+ let regs = self . put_value_in_regs ( arg) ;
990+ branch_arg_vregs. extend_from_slice ( regs. regs ( ) ) ;
979991 }
992+ self . vcode . add_succ ( succ, & branch_arg_vregs[ ..] ) ;
980993 }
981994
982995 fn collect_branches_and_targets (
@@ -1028,44 +1041,29 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
10281041 // `lower_clif_block()` for rationale).
10291042
10301043 // End branches.
1031- if let Some ( bb) = lb. orig_block ( ) {
1032- if let Some ( branch) = self . collect_branches_and_targets ( bindex, bb, & mut targets) {
1033- self . lower_clif_branches ( backend, bindex, bb, branch, & targets) ?;
1034- self . finish_ir_inst ( self . srcloc ( branch) ) ;
1035- }
1036- } else {
1037- // If no orig block, this must be a pure edge block;
1038- // get the successor and emit a jump. Add block params
1039- // according to the one successor, and pass them
1040- // through; note that the successor must have an
1041- // original block.
1042- let ( _, succs) = self . vcode . block_order ( ) . succ_indices ( bindex) ;
1043- let succ = succs[ 0 ] ;
1044-
1045- let orig_succ = lowered_order[ succ. index ( ) ] ;
1046- let orig_succ = orig_succ
1047- . orig_block ( )
1048- . expect ( "Edge block succ must be body block" ) ;
1049-
1050- let mut branch_arg_vregs: SmallVec < [ Reg ; 16 ] > = smallvec ! [ ] ;
1051- for ty in self . f . dfg . block_param_types ( orig_succ) {
1052- let regs = self . vregs . alloc ( ty) ?;
1053- for & reg in regs. regs ( ) {
1054- branch_arg_vregs. push ( reg) ;
1055- let vreg = reg. to_virtual_reg ( ) . unwrap ( ) ;
1056- self . vcode . add_block_param ( vreg) ;
1044+ match lb {
1045+ & LoweredBlock :: Orig { block : bb } => {
1046+ if let Some ( branch) =
1047+ self . collect_branches_and_targets ( bindex, bb, & mut targets)
1048+ {
1049+ self . lower_clif_branches ( backend, bindex, bb, branch, & targets) ?;
1050+ self . finish_ir_inst ( self . srcloc ( branch) ) ;
10571051 }
1058- }
1059- self . vcode . add_succ ( succ, & branch_arg_vregs[ ..] ) ;
10601052
1061- self . emit ( I :: gen_jump ( MachLabel :: from_block ( succ) ) ) ;
1062- self . finish_ir_inst ( Default :: default ( ) ) ;
1063- }
1064-
1065- // Original block body.
1066- if let Some ( bb) = lb. orig_block ( ) {
1067- self . lower_clif_block ( backend, bb, ctrl_plane) ?;
1068- self . emit_value_label_markers_for_block_args ( bb) ;
1053+ // Original block body.
1054+ self . lower_clif_block ( backend, bb, ctrl_plane) ?;
1055+ self . emit_value_label_markers_for_block_args ( bb) ;
1056+ }
1057+ & LoweredBlock :: CriticalEdge { pred, succ_idx, .. } => {
1058+ // Emit a jump to the successor, placing the block params
1059+ // that the predecessor was going to pass along here.
1060+ let ( _, succs) = self . vcode . block_order ( ) . succ_indices ( bindex) ;
1061+ let succ = succs[ 0 ] ;
1062+ let branch = self . f . layout . last_inst ( pred) . unwrap ( ) ;
1063+ self . lower_branch_blockparam_args ( branch, succ_idx as usize , succ) ;
1064+ self . emit ( I :: gen_jump ( MachLabel :: from_block ( succ) ) ) ;
1065+ self . finish_ir_inst ( Default :: default ( ) ) ;
1066+ }
10691067 }
10701068
10711069 if bindex. index ( ) == 0 {
0 commit comments