22//! (thus indicating there is a loop in the CFG), or whose terminator is a function call.
33use crate :: MirPass ;
44
5+ use rustc_data_structures:: graph:: dominators:: Dominators ;
56use rustc_middle:: mir:: {
6- BasicBlock , BasicBlockData , BasicBlocks , Body , Statement , StatementKind , TerminatorKind ,
7+ BasicBlock , BasicBlockData , Body , Statement , StatementKind , TerminatorKind ,
78} ;
89use rustc_middle:: ty:: TyCtxt ;
910
@@ -12,13 +13,14 @@ pub struct CtfeLimit;
1213impl < ' tcx > MirPass < ' tcx > for CtfeLimit {
1314 #[ instrument( skip( self , _tcx, body) ) ]
1415 fn run_pass ( & self , _tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
16+ let doms = body. basic_blocks . dominators ( ) ;
1517 let indices: Vec < BasicBlock > = body
1618 . basic_blocks
1719 . iter_enumerated ( )
1820 . filter_map ( |( node, node_data) | {
1921 if matches ! ( node_data. terminator( ) . kind, TerminatorKind :: Call { .. } )
2022 // Back edges in a CFG indicate loops
21- || has_back_edge ( & body . basic_blocks , node, & node_data)
23+ || has_back_edge ( & doms , node, & node_data)
2224 {
2325 Some ( node)
2426 } else {
@@ -37,17 +39,16 @@ impl<'tcx> MirPass<'tcx> for CtfeLimit {
3739}
3840
3941fn has_back_edge (
40- basic_blocks : & BasicBlocks < ' _ > ,
42+ doms : & Dominators < BasicBlock > ,
4143 node : BasicBlock ,
4244 node_data : & BasicBlockData < ' _ > ,
4345) -> bool {
44- let doms = basic_blocks. dominators ( ) ;
45- basic_blocks. indices ( ) . any ( |potential_dom| {
46- doms. is_reachable ( potential_dom)
47- && doms. is_reachable ( node)
48- && doms. is_dominated_by ( node, potential_dom)
49- && node_data. terminator ( ) . successors ( ) . into_iter ( ) . any ( |succ| succ == potential_dom)
50- } )
46+ if !doms. is_reachable ( node) {
47+ return false ;
48+ }
49+ // Check if any of the dominators of the node are also the node's successor.
50+ doms. dominators ( node)
51+ . any ( |dom| node_data. terminator ( ) . successors ( ) . into_iter ( ) . any ( |succ| succ == dom) )
5152}
5253
5354fn insert_counter ( basic_block_data : & mut BasicBlockData < ' _ > ) {
0 commit comments