@@ -2603,60 +2603,74 @@ impl Function {
26032603 self . copy_param_types ( ) ;
26042604
26052605 let mut reachable = BlockSet :: with_capacity ( self . blocks . len ( ) ) ;
2606+
2607+ // Maintain both a worklist and a fast membership check to avoid linear search
2608+ let mut worklist: VecDeque < BlockId > = VecDeque :: with_capacity ( self . blocks . len ( ) ) ;
2609+ let mut in_worklist = BlockSet :: with_capacity ( self . blocks . len ( ) ) ;
2610+ macro_rules! worklist_add {
2611+ ( $block: expr) => {
2612+ if in_worklist. insert( $block) {
2613+ worklist. push_back( $block) ;
2614+ }
2615+ } ;
2616+ }
2617+
26062618 for entry_block in self . entry_blocks ( ) {
26072619 reachable. insert ( entry_block) ;
2620+ worklist_add ! ( entry_block) ;
2621+ }
2622+
2623+ // Helper to propagate types along a branch edge and enqueue the target if anything changed
2624+ macro_rules! enqueue {
2625+ ( $self: ident, $target: expr) => {
2626+ let newly_reachable = reachable. insert( $target. target) ;
2627+ let mut target_changed = newly_reachable;
2628+ for ( idx, arg) in $target. args. iter( ) . enumerate( ) {
2629+ let param = $self. blocks[ $target. target. 0 ] . params[ idx] ;
2630+ let new = self . insn_types[ param. 0 ] . union ( self . insn_types[ arg. 0 ] ) ;
2631+ if !self . insn_types[ param. 0 ] . bit_equal( new) {
2632+ self . insn_types[ param. 0 ] = new;
2633+ target_changed = true ;
2634+ }
2635+ }
2636+ if target_changed {
2637+ worklist_add!( $target. target) ;
2638+ }
2639+ } ;
26082640 }
26092641
2610- // Walk the graph, computing types until fixpoint
2611- let rpo = self . rpo ( ) ;
2612- loop {
2613- let mut changed = false ;
2614- for & block in & rpo {
2615- if !reachable. get ( block) { continue ; }
2616- for insn_id in & self . blocks [ block. 0 ] . insns {
2617- let insn_type = match self . find ( * insn_id) {
2618- Insn :: IfTrue { val, target : BranchEdge { target, args } } => {
2619- assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
2620- if self . type_of ( val) . could_be ( Type :: from_cbool ( true ) ) {
2621- reachable. insert ( target) ;
2622- for ( idx, arg) in args. iter ( ) . enumerate ( ) {
2623- let param = self . blocks [ target. 0 ] . params [ idx] ;
2624- self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
2625- }
2626- }
2627- continue ;
2628- }
2629- Insn :: IfFalse { val, target : BranchEdge { target, args } } => {
2630- assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
2631- if self . type_of ( val) . could_be ( Type :: from_cbool ( false ) ) {
2632- reachable. insert ( target) ;
2633- for ( idx, arg) in args. iter ( ) . enumerate ( ) {
2634- let param = self . blocks [ target. 0 ] . params [ idx] ;
2635- self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
2636- }
2637- }
2638- continue ;
2642+ // Walk the graph, computing types until worklist is empty
2643+ while let Some ( block) = worklist. pop_front ( ) {
2644+ in_worklist. remove ( block) ;
2645+ if !reachable. get ( block) { continue ; }
2646+
2647+ for insn_id in & self . blocks [ block. 0 ] . insns {
2648+ let insn_type = match self . find ( * insn_id) {
2649+ Insn :: IfTrue { val, target } => {
2650+ assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
2651+ if self . type_of ( val) . could_be ( Type :: from_cbool ( true ) ) {
2652+ enqueue ! ( self , target) ;
26392653 }
2640- Insn :: Jump ( BranchEdge { target, args } ) => {
2641- reachable. insert ( target) ;
2642- for ( idx, arg) in args. iter ( ) . enumerate ( ) {
2643- let param = self . blocks [ target. 0 ] . params [ idx] ;
2644- self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
2645- }
2646- continue ;
2654+ continue ;
2655+ }
2656+ Insn :: IfFalse { val, target } => {
2657+ assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
2658+ if self . type_of ( val) . could_be ( Type :: from_cbool ( false ) ) {
2659+ enqueue ! ( self , target) ;
26472660 }
2648- insn if insn. has_output ( ) => self . infer_type ( * insn_id) ,
2649- _ => continue ,
2650- } ;
2651- if !self . type_of ( * insn_id) . bit_equal ( insn_type) {
2652- self . insn_types [ insn_id. 0 ] = insn_type;
2653- changed = true ;
2661+ continue ;
26542662 }
2663+ Insn :: Jump ( target) => {
2664+ enqueue ! ( self , target) ;
2665+ continue ;
2666+ }
2667+ insn if insn. has_output ( ) => self . infer_type ( * insn_id) ,
2668+ _ => continue ,
2669+ } ;
2670+ if !self . type_of ( * insn_id) . bit_equal ( insn_type) {
2671+ self . insn_types [ insn_id. 0 ] = insn_type;
26552672 }
26562673 }
2657- if !changed {
2658- break ;
2659- }
26602674 }
26612675 }
26622676
0 commit comments