@@ -56,7 +56,7 @@ pub struct BlockAsm<'a> {
5656 tmp_shift_imm_reg : BlockReg ,
5757 tmp_func_call_reg : BlockReg ,
5858
59- cond_block_end_label_stack : Vec < BlockLabel > ,
59+ cond_block_end_label_stack : Vec < ( BlockLabel , Cond , usize ) > ,
6060
6161 guest_reg_init_offset : Option < usize > ,
6262 is_common_fun : bool ,
@@ -377,7 +377,7 @@ impl<'a> BlockAsm<'a> {
377377 }
378378
379379 pub fn branch ( & mut self , label : BlockLabel , cond : Cond ) {
380- self . insert_inst ( BlockInstKind :: Branch { label, block_index : 0 , cond } )
380+ self . insert_inst ( BlockInst :: new ( cond , BlockInstKind :: Branch { label, block_index : 0 } ) )
381381 }
382382
383383 pub fn save_context ( & mut self ) {
@@ -567,7 +567,7 @@ impl<'a> BlockAsm<'a> {
567567 }
568568 Some ( label) => * label,
569569 } ;
570- self . insert_inst ( BlockInstKind :: Branch { label, block_index : 0 , cond } ) ;
570+ self . insert_inst ( BlockInst :: new ( cond , BlockInstKind :: Branch { label, block_index : 0 } ) ) ;
571571 }
572572
573573 pub fn generic_guest_inst ( & mut self , inst_info : & mut InstInfo ) {
@@ -600,13 +600,22 @@ impl<'a> BlockAsm<'a> {
600600 if cond != Cond :: AL {
601601 let label = self . new_label ( ) ;
602602 self . branch ( label, !cond) ;
603- self . cond_block_end_label_stack . push ( label) ;
603+ self . cond_block_end_label_stack . push ( ( label, cond , self . buf . insts . len ( ) ) ) ;
604604 }
605605 }
606606
607607 pub fn end_cond_block ( & mut self ) {
608- if let Some ( label) = self . cond_block_end_label_stack . pop ( ) {
609- self . label ( label) ;
608+ if let Some ( ( label, cond, start_index) ) = self . cond_block_end_label_stack . pop ( ) {
609+ let cond_block_size = self . buf . insts . len ( ) - start_index;
610+ let ( _, outputs) = self . buf . insts [ start_index] . get_io ( ) ;
611+ if cond_block_size == 1 && self . buf . insts [ start_index] . cond == Cond :: AL && !outputs. contains ( BlockReg :: Fixed ( Reg :: CPSR ) ) && !outputs. contains ( Reg :: CPSR . into ( ) ) {
612+ self . buf . insts [ start_index] . cond = cond;
613+ self . buf . insts [ start_index] . invalidate_io_cache ( ) ;
614+ // Remove the branch
615+ self . buf . insts . remove ( start_index - 1 ) ;
616+ } else {
617+ self . label ( label) ;
618+ }
610619 }
611620 }
612621
@@ -761,17 +770,22 @@ impl<'a> BlockAsm<'a> {
761770 // Link blocks
762771 for ( i, basic_block) in basic_blocks. iter_mut ( ) . enumerate ( ) {
763772 let last_inst_index = BlockInstList :: deref ( basic_block. block_entry_end ) . value ;
773+ let cond = self . buf . insts [ last_inst_index] . cond ;
764774 match & mut self . buf . insts [ last_inst_index] . kind {
765- BlockInstKind :: Branch { label, block_index, cond } => {
775+ BlockInstKind :: Branch { label, block_index } => {
766776 let labelled_block_index = basic_block_label_mapping. get ( & label. 0 ) . unwrap ( ) ;
767777 basic_block. exit_blocks . push ( * labelled_block_index) ;
768778 * block_index = * labelled_block_index;
769- if * cond != Cond :: AL && i + 1 < basic_blocks_len {
779+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
770780 basic_block. exit_blocks . push ( i + 1 ) ;
771781 }
772782 }
773783 // Don't add exit when last command in basic block is a breakout
774- BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: CallCommon { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => { }
784+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: CallCommon { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
785+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
786+ basic_block. exit_blocks . push ( i + 1 ) ;
787+ }
788+ }
775789 _ if i + 1 < basic_blocks_len => basic_block. exit_blocks . push ( i + 1 ) ,
776790 _ => { }
777791 }
0 commit comments