@@ -625,20 +625,22 @@ pub fn optimize_module_direct(module: &Module) -> Result<Module, EgglogOptError>
625625 // For each selection construct, convert to RVSDG EffGamma
626626 for ( sel_idx, sel) in selection_constructs. iter ( ) . enumerate ( ) {
627627 // Skip selections that overlap with loop bodies or continue blocks.
628- // Check ALL blocks involved (header, then, else, merge) — not just the header —
629- // because SPIR-V blocks may not be laid out contiguously.
628+ // Check ALL blocks in the construct range [header, merge] — not just the
629+ // named targets — because intermediate blocks (e.g. continue targets) may
630+ // exist between branch targets and the merge block.
630631 {
631632 let label_map = & func_block_labels[ sel. func_idx ] ;
632- let in_loop = loop_block_set. contains ( & ( sel. func_idx , sel. header_block_idx ) )
633- || continue_block_set. contains ( & ( sel. func_idx , sel. header_block_idx ) )
634- || [ & sel. then_label , & sel. else_label , & sel. merge_label ]
635- . iter ( )
636- . any ( |label| {
637- label_map. get ( label) . map_or ( false , |& idx| {
638- loop_block_set. contains ( & ( sel. func_idx , idx) )
639- || continue_block_set. contains ( & ( sel. func_idx , idx) )
640- } )
641- } ) ;
633+ let merge_idx = label_map. get ( & sel. merge_label ) . copied ( ) ;
634+ let in_loop = if let Some ( merge_idx) = merge_idx {
635+ // Check all blocks from header to merge (inclusive)
636+ ( sel. header_block_idx ..=merge_idx) . any ( |idx| {
637+ loop_block_set. contains ( & ( sel. func_idx , idx) )
638+ || continue_block_set. contains ( & ( sel. func_idx , idx) )
639+ } )
640+ } else {
641+ // Can't resolve merge — skip to be safe
642+ true
643+ } ;
642644 if in_loop {
643645 continue ;
644646 }
@@ -746,21 +748,19 @@ pub fn optimize_module_direct(module: &Module) -> Result<Module, EgglogOptError>
746748 let mut rvsdg_switches: Vec < RvsdgSwitch > = Vec :: new ( ) ;
747749
748750 for sw in & switch_constructs {
749- // Skip switches that overlap with loop bodies or continue blocks
751+ // Skip switches that overlap with loop bodies or continue blocks.
752+ // Check ALL blocks in the construct range [header, merge].
750753 {
751754 let label_map = & func_block_labels[ sw. func_idx ] ;
752- let in_loop = loop_block_set. contains ( & ( sw. func_idx , sw. header_block_idx ) )
753- || continue_block_set. contains ( & ( sw. func_idx , sw. header_block_idx ) )
754- || sw. case_labels . iter ( ) . any ( |label| {
755- label_map. get ( label) . map_or ( false , |& idx| {
756- loop_block_set. contains ( & ( sw. func_idx , idx) )
757- || continue_block_set. contains ( & ( sw. func_idx , idx) )
758- } )
759- } )
760- || label_map. get ( & sw. merge_label ) . map_or ( false , |& idx| {
755+ let merge_idx = label_map. get ( & sw. merge_label ) . copied ( ) ;
756+ let in_loop = if let Some ( merge_idx) = merge_idx {
757+ ( sw. header_block_idx ..=merge_idx) . any ( |idx| {
761758 loop_block_set. contains ( & ( sw. func_idx , idx) )
762759 || continue_block_set. contains ( & ( sw. func_idx , idx) )
763- } ) ;
760+ } )
761+ } else {
762+ true
763+ } ;
764764 if in_loop {
765765 continue ;
766766 }
0 commit comments