Clean up CtfeLimit MirPass

This commit is contained in:
Bryan Garza 2022-12-29 03:38:34 +00:00
parent 360db516cc
commit 026a67377f
3 changed files with 72 additions and 78 deletions

View File

@ -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::<Vec<BasicBlock>>()
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::<Vec<BasicBlock>>());
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,
});
}

View File

@ -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}");
}

View File

@ -0,0 +1,4 @@
warning: Const eval counter limit (20) has been crossed
warning: 1 warning emitted