@@ -550,7 +550,7 @@ fn compute_phi_join_locals<'tcx>(
550550}
551551
552552/// Detect all Range-based `for` loops in the MIR body.
553- fn detect_range_loop < ' tcx > ( mir : & Body < ' tcx > ) -> Vec < RangeLoopInfo > {
553+ fn detect_range_loop < ' tcx > ( instance : Instance < ' tcx > , mir : & Body < ' tcx > ) -> Vec < RangeLoopInfo > {
554554 use rustc_middle:: mir:: TerminatorKind ;
555555
556556 let mut loops = Vec :: new ( ) ;
@@ -560,7 +560,7 @@ fn detect_range_loop<'tcx>(mir: &Body<'tcx>) -> Vec<RangeLoopInfo> {
560560 // Back edge: bb → target (target is the loop header)
561561 let header_bb = * target;
562562 let back_edge_bb = bb;
563- if let Some ( info) = try_build_range_loop_info ( mir, header_bb, back_edge_bb) {
563+ if let Some ( info) = try_build_range_loop_info ( instance , mir, header_bb, back_edge_bb) {
564564 loops. push ( info) ;
565565 }
566566 }
@@ -570,6 +570,7 @@ fn detect_range_loop<'tcx>(mir: &Body<'tcx>) -> Vec<RangeLoopInfo> {
570570}
571571
572572fn try_build_range_loop_info < ' tcx > (
573+ instance : Instance < ' tcx > ,
573574 mir : & Body < ' tcx > ,
574575 header_bb : BasicBlock ,
575576 back_edge_bb : BasicBlock ,
@@ -592,32 +593,28 @@ fn try_build_range_loop_info<'tcx>(
592593 // Pattern 1: SwitchInt header with explicit Lt comparison (older Rust MIR).
593594 if let TerminatorKind :: SwitchInt { discr, targets } = & header_data. terminator ( ) . kind {
594595 let cases: Vec < ( u128 , BasicBlock ) > = targets. iter ( ) . collect ( ) ;
595- println ! ( "[LOOP-DETECT] header={:?} back_edge={:?} SwitchInt cases={:?} otherwise={:?} discr={:?}" ,
596- header_bb, back_edge_bb, cases, targets. otherwise( ) , discr) ;
597596 if cases. len ( ) == 1 && cases[ 0 ] . 0 == 0 {
598597 let exit_bb = cases[ 0 ] . 1 ;
599598 let body_entry_bb = targets. otherwise ( ) ;
600599 if let Operand :: Move ( p) | Operand :: Copy ( p) = discr {
601600 if p. projection . is_empty ( ) {
602601 let discr_local = p. local ;
603- if let Some ( ( counter_local, bl) ) =
604- find_lt_locals_in_stmts ( & header_data. statements , discr_local)
602+ if let Some ( ( counter_local, bl, bc ) ) =
603+ find_lt_locals_in_stmts ( & header_data. statements , discr_local, instance )
605604 {
606- println ! ( "[LOOP-DETECT] Pattern1 detected: counter={:?} bound_local={:?}" , counter_local, bl) ;
607605 break ' detect HeaderInfo {
608606 body_entry_bb,
609607 exit_bb,
610608 counter_local_hint : Some ( counter_local) ,
611- bound_local : Some ( bl ) ,
612- bound_const : None ,
609+ bound_local : bl ,
610+ bound_const : bc ,
613611 switch_bb : None ,
614612 next_result_local : None ,
615613 } ;
616614 }
617615 }
618616 }
619617 }
620- println ! ( "[LOOP-DETECT] FAIL Pattern1: cases={:?}" , cases) ;
621618 }
622619
623620 // Pattern 2: Call header (Range::next) followed by SwitchInt on discriminant (Rust 1.93+).
@@ -627,8 +624,6 @@ fn try_build_range_loop_info<'tcx>(
627624 let switch_data = & mir. basic_blocks [ * switch_bb_cand] ;
628625 if let TerminatorKind :: SwitchInt { targets, .. } = & switch_data. terminator ( ) . kind {
629626 let cases: Vec < ( u128 , BasicBlock ) > = targets. iter ( ) . collect ( ) ;
630- println ! ( "[LOOP-DETECT] header={:?} back_edge={:?} Call+SwitchInt cases={:?} otherwise={:?}" ,
631- header_bb, back_edge_bb, cases, targets. otherwise( ) ) ;
632627 // Discriminant 0 = None (exit), discriminant 1 = Some (body)
633628 if cases. len ( ) == 2 && cases[ 0 ] . 0 == 0 && cases[ 1 ] . 0 == 1
634629 && destination. projection . is_empty ( )
@@ -637,7 +632,6 @@ fn try_build_range_loop_info<'tcx>(
637632 let body_entry_bb = cases[ 1 ] . 1 ;
638633 let next_result_local = destination. local ;
639634 if let Some ( ( bc, bl) ) = find_range_bound ( mir, header_bb) {
640- println ! ( "[LOOP-DETECT] Pattern2 detected: bound_const={:?} bound_local={:?}" , bc, bl) ;
641635 break ' detect HeaderInfo {
642636 body_entry_bb,
643637 exit_bb,
@@ -650,37 +644,30 @@ fn try_build_range_loop_info<'tcx>(
650644 }
651645 }
652646 }
653- println ! ( "[LOOP-DETECT] FAIL Pattern2: switch_bb={:?}" , switch_bb_cand) ;
654647 }
655648
656- println ! ( "[LOOP-DETECT] header={:?} back_edge={:?}: no pattern matched" , header_bb, back_edge_bb) ;
657649 return None ;
658650 } ;
659651
660652 // Collect body blocks in topological (execution) order
661653 let body_bbs = collect_body_blocks_ordered ( mir, hinfo. body_entry_bb , header_bb) ;
662- println ! ( "[LOOP-DETECT] body_bbs={:?} back_edge_in_body={}" , body_bbs, body_bbs. contains( & back_edge_bb) ) ;
663654 if !body_bbs. contains ( & back_edge_bb) {
664655 return None ;
665656 }
666657
667658 // Find the induction local: extracted from Option::Some via downcast projection
668- let induction_result = find_induction_local_in_bbs ( mir, & body_bbs) ;
669- println ! ( "[LOOP-DETECT] induction_local={:?}" , induction_result) ;
670- let induction_local = induction_result?;
659+ let induction_local = find_induction_local_in_bbs ( mir, & body_bbs) ?;
671660
672661 let counter_local = hinfo. counter_local_hint . unwrap_or ( induction_local) ;
673662
674663 // Find loop-carried locals (used before assigned in topological order).
675664 let mut iter_carry_locals = find_iter_carry_locals ( mir, & body_bbs) ;
676- println ! ( "[LOOP-DETECT] iter_carry_locals (before filter)={:?}" , iter_carry_locals) ;
677665
678666 // For the Call-header pattern, exclude the Range::next result local (next_result_local)
679667 // from iter-carry: it is synthesised by scf.for, not a user-defined loop-carried value.
680668 if let Some ( nrl) = hinfo. next_result_local {
681669 iter_carry_locals. retain ( |& l| l != nrl) ;
682670 }
683- println ! ( "[LOOP-DETECT] iter_carry_locals (final)={:?}" , iter_carry_locals) ;
684671
685672 Some ( RangeLoopInfo {
686673 header_bb,
@@ -744,11 +731,14 @@ fn try_const_operand_as_i64(c: &ConstOperand<'_>) -> Option<i64> {
744731 c. const_ . try_to_scalar_int ( ) . map ( |s| s. to_bits_unchecked ( ) as i64 )
745732}
746733
747- /// Find the Lt statement that assigns `discr_local` and extract (counter_local, bound_local).
734+ /// Find the Lt statement that assigns `discr_local` and extract
735+ /// `(counter_local, bound_local_or_const)` where the bound is either a local or a constant.
736+ /// Returns `(counter, Some(bound_local), None)` or `(counter, None, Some(bound_const))`.
748737fn find_lt_locals_in_stmts < ' tcx > (
749738 stmts : & [ Statement < ' tcx > ] ,
750739 discr_local : Local ,
751- ) -> Option < ( Local , Local ) > {
740+ instance : Instance < ' tcx > ,
741+ ) -> Option < ( Local , Option < Local > , Option < i64 > ) > {
752742 for stmt in stmts {
753743 if let StatementKind :: Assign ( assign) = & stmt. kind {
754744 let ( dest, rvalue) = assign. as_ref ( ) ;
@@ -759,14 +749,34 @@ fn find_lt_locals_in_stmts<'tcx>(
759749 Operand :: Move ( p) | Operand :: Copy ( p) if p. projection . is_empty ( ) => p. local ,
760750 _ => return None ,
761751 } ;
762- let bound_local = match rhs {
763- Operand :: Move ( p) | Operand :: Copy ( p) if p. projection . is_empty ( ) => p. local ,
764- _ => return None ,
765- } ;
766- // Resolve the counter_copy (might be a copy of the real counter)
767752 let counter_local = find_copy_source_in_stmts ( stmts, counter_copy)
768753 . unwrap_or ( counter_copy) ;
769- return Some ( ( counter_local, bound_local) ) ;
754+ match rhs {
755+ Operand :: Move ( p) | Operand :: Copy ( p) if p. projection . is_empty ( ) => {
756+ return Some ( ( counter_local, Some ( p. local ) , None ) ) ;
757+ }
758+ Operand :: Constant ( c) => {
759+ // Try simple scalar first (works for literal constants)
760+ if let Some ( v) = try_const_operand_as_i64 ( c) {
761+ return Some ( ( counter_local, None , Some ( v) ) ) ;
762+ }
763+ // Handle ConstKind::Param (const generic — resolve via instance substs)
764+ use rustc_middle:: mir:: Const as MirConst ;
765+ if let MirConst :: Ty ( ty, const_val) = c. const_ {
766+ if ty. is_integral ( ) {
767+ if let ConstKind :: Param ( param) = const_val. kind ( ) {
768+ let subst = instance. args . const_at ( param. index as usize ) ;
769+ let cv = subst. to_value ( ) ;
770+ if let Some ( si) = cv. try_to_leaf ( ) {
771+ return Some ( ( counter_local, None , Some ( si. to_bits_unchecked ( ) as i64 ) ) ) ;
772+ }
773+ }
774+ }
775+ }
776+ return None ;
777+ }
778+ _ => return None ,
779+ }
770780 }
771781 }
772782 }
@@ -1431,7 +1441,7 @@ impl<'a> TritonCodegen<'a> {
14311441
14321442 // Detect all Range-based `for` loops. Loop body blocks live in the scf.for region, not
14331443 // in the function region, so we skip creating MLIR blocks for them here.
1434- let loop_infos = detect_range_loop ( mir) ;
1444+ let loop_infos = detect_range_loop ( * instance , mir) ;
14351445
14361446 // The set of MIR blocks that belong to any scf.for region.
14371447 let mut loop_region_blocks: HashSet < BasicBlock > = HashSet :: new ( ) ;
0 commit comments