1- use rustc_index:: IndexSlice ;
1+ use rustc_index:: { IndexSlice , IndexVec } ;
22use rustc_infer:: infer:: NllRegionVariableOrigin ;
33use rustc_middle:: mir:: visit:: { MutVisitor , TyContext } ;
4- use rustc_middle:: mir:: { Body , ConstOperand , Location , Promoted } ;
4+ use rustc_middle:: mir:: * ;
55use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypeFoldable , fold_regions} ;
66use rustc_span:: Symbol ;
7+ use thin_vec:: ThinVec ;
78use tracing:: { debug, instrument} ;
89
910use crate :: BorrowckInferCtxt ;
@@ -21,12 +22,68 @@ pub(crate) fn renumber_mir<'tcx>(
2122 let mut renumberer = RegionRenumberer { infcx } ;
2223
2324 for body in promoted. iter_mut ( ) {
25+ split_critical_edges ( body) ;
2426 renumberer. visit_body_preserves_cfg ( body) ;
2527 }
2628
29+ split_critical_edges ( body) ;
2730 renumberer. visit_body_preserves_cfg ( body) ;
2831}
2932
33+ #[ instrument( skip( body) , level = "debug" ) ]
34+ fn split_critical_edges ( body : & mut Body < ' _ > ) {
35+ let predecessors: IndexVec < BasicBlock , _ > =
36+ body. basic_blocks . predecessors ( ) . iter ( ) . map ( |preds| preds. len ( ) ) . collect ( ) ;
37+ debug ! ( ?predecessors) ;
38+
39+ let mut new_blocks = vec ! [ ] ;
40+ for bb in predecessors. indices ( ) {
41+ let term = body. basic_blocks [ bb] . terminator ( ) ;
42+ if term. successors ( ) . count ( ) <= 1 {
43+ continue ;
44+ }
45+ if term. successors ( ) . all ( |s| predecessors[ s] <= 1 ) {
46+ continue ;
47+ }
48+
49+ debug ! (
50+ "{bb:?} has critical edges: {:?}" ,
51+ term. successors( ) . map( |s| ( s, predecessors[ s] ) ) . collect:: <Vec <_>>( ) ,
52+ ) ;
53+
54+ let original_succ: Vec < _ > = term. successors ( ) . collect ( ) ;
55+ new_blocks. push ( ( bb, original_succ) ) ;
56+ }
57+
58+ if new_blocks. is_empty ( ) {
59+ return ;
60+ }
61+
62+ debug ! ( ?new_blocks) ;
63+ let basic_blocks = body. basic_blocks . as_mut ( ) ;
64+ for ( bb, successors) in new_blocks. iter_mut ( ) {
65+ let source_info = basic_blocks[ * bb] . terminator ( ) . source_info ;
66+ for target in successors. iter_mut ( ) {
67+ if predecessors[ * target] <= 1 {
68+ continue ;
69+ }
70+
71+ let is_cleanup = basic_blocks[ * target] . is_cleanup ;
72+ let terminator = Terminator {
73+ source_info,
74+ kind : TerminatorKind :: Goto { target : * target } ,
75+ attributes : ThinVec :: new ( ) ,
76+ } ;
77+ * target = basic_blocks. push ( BasicBlockData :: new ( Some ( terminator) , is_cleanup) )
78+ }
79+ }
80+
81+ for ( bb, new_succ) in new_blocks {
82+ let mut new_succ = new_succ. into_iter ( ) ;
83+ basic_blocks[ bb] . terminator_mut ( ) . successors_mut ( |succ| * succ = new_succ. next ( ) . unwrap ( ) ) ;
84+ }
85+ }
86+
3087// The fields are used only for debugging output in `sccs_info`.
3188#[ derive( Copy , Clone , Debug , Eq , PartialEq , Hash ) ]
3289pub ( crate ) enum RegionCtxt {
0 commit comments