@@ -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,21 @@ 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+ // Remove the branch
614+ self . buf . insts . remove ( start_index - 1 ) ;
615+ } else {
616+ self . label ( label) ;
617+ }
610618 }
611619 }
612620
@@ -761,17 +769,22 @@ impl<'a> BlockAsm<'a> {
761769 // Link blocks
762770 for ( i, basic_block) in basic_blocks. iter_mut ( ) . enumerate ( ) {
763771 let last_inst_index = BlockInstList :: deref ( basic_block. block_entry_end ) . value ;
772+ let cond = self . buf . insts [ last_inst_index] . cond ;
764773 match & mut self . buf . insts [ last_inst_index] . kind {
765- BlockInstKind :: Branch { label, block_index, cond } => {
774+ BlockInstKind :: Branch { label, block_index } => {
766775 let labelled_block_index = basic_block_label_mapping. get ( & label. 0 ) . unwrap ( ) ;
767776 basic_block. exit_blocks . push ( * labelled_block_index) ;
768777 * block_index = * labelled_block_index;
769- if * cond != Cond :: AL && i + 1 < basic_blocks_len {
778+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
770779 basic_block. exit_blocks . push ( i + 1 ) ;
771780 }
772781 }
773782 // 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 { .. } => { }
783+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: CallCommon { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
784+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
785+ basic_block. exit_blocks . push ( i + 1 ) ;
786+ }
787+ }
775788 _ if i + 1 < basic_blocks_len => basic_block. exit_blocks . push ( i + 1 ) ,
776789 _ => { }
777790 }
0 commit comments