@@ -664,6 +664,17 @@ impl<'a> BlockAsm<'a> {
664664 }
665665 }
666666
667+ fn resolve_actual_block_count ( already_processed : & mut NoHashSet < usize > , basic_blocks : & mut [ BasicBlock ] , block_i : usize , count : & mut usize ) {
668+ * count += 1 ;
669+ already_processed. insert ( block_i) ;
670+ for i in 0 ..basic_blocks[ block_i] . exit_blocks . len ( ) {
671+ let exit_i = basic_blocks[ block_i] . exit_blocks [ i] ;
672+ if !already_processed. contains ( & exit_i) {
673+ Self :: resolve_actual_block_count ( already_processed, basic_blocks, exit_i, count) ;
674+ }
675+ }
676+ }
677+
667678 fn resolve_df_ordering (
668679 already_processed : & mut Bitset < { 1024 / 32 } > ,
669680 completed : & mut Bitset < { 1024 / 32 } > ,
@@ -697,7 +708,7 @@ impl<'a> BlockAsm<'a> {
697708 * completed += block_i;
698709 }
699710
700- fn assemble_basic_blocks ( & mut self , block_start_pc : u32 , thumb : bool ) -> ( Vec < BasicBlock > , Vec < usize > ) {
711+ fn assemble_basic_blocks ( & mut self , block_start_pc : u32 , thumb : bool ) -> ( Vec < BasicBlock > , Vec < usize > , NoHashSet < usize > ) {
701712 for i in 0 ..self . buf . insts . len ( ) {
702713 self . insts_link . insert_end ( i) ;
703714 }
@@ -737,7 +748,7 @@ impl<'a> BlockAsm<'a> {
737748 }
738749 last_label = None ;
739750 }
740- BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
751+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: CallCommon { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
741752 basic_blocks. push ( BasicBlock :: new ( self , basic_block_start, current_node) ) ;
742753 basic_block_start = BlockInstList :: deref ( current_node) . next ;
743754 if let Some ( last_label) = last_label {
@@ -773,16 +784,13 @@ impl<'a> BlockAsm<'a> {
773784 }
774785 }
775786 // Don't add exit when last command in basic block is a breakout
776- BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
777- if i + 1 < basic_blocks_len {
778- basic_block. exit_blocks . push ( i + 1 ) ;
779- }
780- }
781- _ => {
782- if i + 1 < basic_blocks_len {
787+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: CallCommon { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
788+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
783789 basic_block. exit_blocks . push ( i + 1 ) ;
784790 }
785791 }
792+ _ if i + 1 < basic_blocks_len => basic_block. exit_blocks . push ( i + 1 ) ,
793+ _ => { }
786794 }
787795 }
788796
@@ -828,11 +836,15 @@ impl<'a> BlockAsm<'a> {
828836 basic_block. remove_dead_code ( self ) ;
829837 }
830838
839+ let mut reachable_blocks = NoHashSet :: default ( ) ;
840+ let mut actual_block_count = 0 ;
841+ Self :: resolve_actual_block_count ( & mut reachable_blocks, & mut basic_blocks, 0 , & mut actual_block_count) ;
842+
831843 let mut df_already_processed = Bitset :: < { 1024 / 32 } > :: new ( ) ;
832844 let mut df_completed = Bitset :: < { 1024 / 32 } > :: new ( ) ;
833- let mut df_ordering = vec ! [ 0 ; basic_blocks_len ] ;
845+ let mut df_ordering = vec ! [ 0 ; actual_block_count ] ;
834846 let mut df_ordering_start = 0 ;
835- let mut df_ordering_end = basic_blocks_len - 1 ;
847+ let mut df_ordering_end = actual_block_count - 1 ;
836848 Self :: resolve_df_ordering (
837849 & mut df_already_processed,
838850 & mut df_completed,
@@ -843,7 +855,7 @@ impl<'a> BlockAsm<'a> {
843855 & mut df_ordering_end,
844856 ) ;
845857
846- ( basic_blocks, df_ordering)
858+ ( basic_blocks, df_ordering, reachable_blocks )
847859 }
848860
849861 fn assemble_intervals ( basic_blocks : & [ BasicBlock ] , ordering : & [ usize ] ) -> NoHashMap < u16 , ( usize , usize ) > {
@@ -872,7 +884,7 @@ impl<'a> BlockAsm<'a> {
872884 }
873885
874886 pub fn emit_opcodes ( & mut self , block_start_pc : u32 , thumb : bool ) -> usize {
875- let ( mut basic_blocks, basic_blocks_order) = self . assemble_basic_blocks ( block_start_pc, thumb) ;
887+ let ( mut basic_blocks, basic_blocks_order, reachable_blocks ) = self . assemble_basic_blocks ( block_start_pc, thumb) ;
876888
877889 if IS_DEBUG && unsafe { BLOCK_LOG } {
878890 for ( i, basic_block) in basic_blocks. iter ( ) . enumerate ( ) {
@@ -919,7 +931,7 @@ impl<'a> BlockAsm<'a> {
919931 }
920932
921933 for ( i, basic_block) in basic_blocks. iter_mut ( ) . enumerate ( ) {
922- if unlikely ( i != 0 && basic_block . enter_blocks . is_empty ( ) ) {
934+ if unlikely ( i != 0 && !reachable_blocks . contains ( & i ) ) {
923935 continue ;
924936 }
925937 self . buf . reg_allocator . init_inputs ( * basic_block. get_required_inputs ( ) ) ;
@@ -944,7 +956,7 @@ impl<'a> BlockAsm<'a> {
944956 for ( i, basic_block) in basic_blocks. iter ( ) . enumerate ( ) {
945957 let opcodes_len = self . buf . opcodes . len ( ) ;
946958 self . buf . block_opcode_offsets . push ( opcodes_len) ;
947- if unlikely ( i != 0 && basic_block . enter_blocks . is_empty ( ) ) {
959+ if unlikely ( i != 0 && !reachable_blocks . contains ( & i ) ) {
948960 continue ;
949961 }
950962 let opcodes = basic_block. emit_opcodes ( self , opcodes_len, used_host_regs) ;
0 commit comments