diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index dc54b983c0e..f2c99b19433 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -1,92 +1,49 @@ use crate::MirPass; -use rustc_middle::mir::{BasicBlock, Body, Statement, StatementKind, TerminatorKind}; +use rustc_middle::mir::{BasicBlockData, Body, Statement, StatementKind, TerminatorKind}; use rustc_middle::ty::TyCtxt; -use tracing::{info, instrument}; - pub struct CtfeLimit; impl<'tcx> MirPass<'tcx> for CtfeLimit { #[instrument(skip(self, _tcx, body))] fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let doms = body.basic_blocks.dominators(); - //info!("Got body with {} basic blocks: {:#?}", body.basic_blocks.len(), body.basic_blocks); - //info!("With doms: {doms:?}"); - - /* - for (index, basic_block) in body.basic_blocks.iter().enumerate() { - info!("bb{index}: {basic_block:#?}") - }*/ - for (index, basic_block) in body.basic_blocks.iter().enumerate() { - info!( - "bb{index} -> successors = {:?}", - basic_block.terminator().successors().collect::>() + let mut indices = Vec::new(); + for (node, node_data) in body.basic_blocks.iter_enumerated() { + if let TerminatorKind::Call { .. } = node_data.terminator().kind { + indices.push(node); + continue; + } + // Back edges in a CFG indicate loops + for (potential_dom, _) in body.basic_blocks.iter_enumerated() { + if doms.is_reachable(potential_dom) + && doms.is_reachable(node) + && doms.is_dominated_by(node, potential_dom) + && node_data + .terminator() + .successors() + .into_iter() + .any(|succ| succ == potential_dom) + { + indices.push(node); + continue; + } + } + } + for index in indices { + insert_counter( + body.basic_blocks_mut() + .get_mut(index) + .expect("basic_blocks index {index} should exist"), ); } - for (index, basic_block) in body.basic_blocks.iter().enumerate() { - info!("bb{index} -> unwind = {:?}", basic_block.terminator().unwind()) - } - - let mut dominators = Vec::new(); - for idom in 0..body.basic_blocks.len() { - let mut nodes = Vec::new(); - for inode in 0..body.basic_blocks.len() { - let dom = BasicBlock::from_usize(idom); - let node = BasicBlock::from_usize(inode); - if doms.is_reachable(dom) - && doms.is_reachable(node) - && doms.is_dominated_by(node, dom) - { - //info!("{idom} dominates {inode}"); - nodes.push(true); - } else { - nodes.push(false); - } - } - dominators.push(nodes); - } - /* - for idom in 0..body.basic_blocks.len() { - print!("{idom} | dom | "); - for inode in 0..body.basic_blocks.len() { - if dominators[idom][inode] { - print!("{inode} | "); - } else { - print!(" | "); - } - } - print!("\n"); - } - */ - - for (index, basic_block) in body.basic_blocks_mut().iter_mut().enumerate() { - // info!("bb{index}: {basic_block:#?}"); - //info!("bb{index} -> successors = {:?}", basic_block.terminator().successors().collect::>()); - let is_back_edge_or_fn_call = 'label: { - match basic_block.terminator().kind { - TerminatorKind::Call { .. } => { - break 'label true; - } - _ => (), - } - for successor in basic_block.terminator().successors() { - let s_index = successor.as_usize(); - if dominators[s_index][index] { - info!("{s_index} to {index} is a loop"); - break 'label true; - } - } - false - }; - if is_back_edge_or_fn_call { - basic_block.statements.push(Statement { - source_info: basic_block.terminator().source_info, - kind: StatementKind::ConstEvalCounter, - }); - info!("New basic block statements vector: {:?}", basic_block.statements); - } - } - info!("With doms: {doms:?}"); } } + +fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) { + basic_block_data.statements.push(Statement { + source_info: basic_block_data.terminator().source_info, + kind: StatementKind::ConstEvalCounter, + }); +} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs new file mode 100644 index 00000000000..33488bd1d1c --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs @@ -0,0 +1,33 @@ +// check-pass + +const fn foo() {} + +const fn call_foo() -> u32 { + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + 0 +} + +const X: u32 = call_foo(); + +fn main() { + println!("{X}"); +} diff --git a/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr new file mode 100644 index 00000000000..183bed3b75b --- /dev/null +++ b/src/test/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr @@ -0,0 +1,4 @@ +warning: Const eval counter limit (20) has been crossed + +warning: 1 warning emitted +