use crate::codegen::cfg::{ControlFlowGraph, Instr};
use crate::codegen::subexpression_elimination::{
kill_loop_variables, AvailableExpression, AvailableExpressionSet,
};
use crate::codegen::Expression;
use num_rational::BigRational;
use num_traits::Zero;
use std::collections::HashMap;
#[derive(Default, Clone)]
pub(super) struct AnticipatedExpressions<'a> {
reverse_sets: HashMap<usize, AvailableExpressionSet<'a>>,
reverse_dag: Vec<Vec<usize>>,
traversing_order: Vec<(usize, bool)>,
depth: Vec<u16>,
}
const SOURCE_FLOW: u16 = 1000;
impl<'a> AnticipatedExpressions<'a> {
pub(super) fn new(
dag: &Vec<Vec<usize>>,
reverse_dag: Vec<Vec<usize>>,
traversing_order: Vec<(usize, bool)>,
) -> AnticipatedExpressions {
let mut depth: Vec<u16> = vec![u16::MAX; dag.len()];
AnticipatedExpressions::blocks_depth(dag, 0, 0, &mut depth);
AnticipatedExpressions {
reverse_sets: HashMap::new(),
reverse_dag,
traversing_order,
depth,
}
}
fn blocks_depth(dag: &Vec<Vec<usize>>, block: usize, level: u16, depth: &mut [u16]) -> u16 {
if level < depth[block] {
depth[block] = level;
} else {
return level;
}
dag[block]
.iter()
.map(|child| AnticipatedExpressions::blocks_depth(dag, *child, level + 1, depth))
.min()
.unwrap_or(u16::MAX)
}
pub(super) fn calculate_anticipated_expressions<'b: 'a>(
&mut self,
instructions: &'b [Vec<Instr>],
cfg: &ControlFlowGraph,
) {
let mut reverse_ave = AvailableExpression::default();
for (block_no, cycle) in &self.traversing_order {
reverse_ave.set_cur_block(*block_no);
let mut cur_set = self.reverse_sets.get(block_no).cloned().unwrap_or_default();
kill_loop_variables(&cfg.blocks[*block_no], &mut cur_set, *cycle);
for instr in instructions[*block_no].iter().rev() {
cur_set.process_instruction(instr, &mut reverse_ave, &mut None);
}
for edge in &self.reverse_dag[*block_no] {
if let Some(set) = self.reverse_sets.get_mut(edge) {
set.union_sets(&cur_set);
} else {
self.reverse_sets.insert(*edge, cur_set.deep_clone());
}
}
}
}
pub(super) fn calculate_flow(&self, block_1: usize, block_2: usize) -> Vec<BigRational> {
let mut flow: Vec<BigRational> = vec![BigRational::zero(); self.reverse_dag.len()];
flow[block_1] = BigRational::from_integer(SOURCE_FLOW.into());
flow[block_2] = BigRational::from_integer(SOURCE_FLOW.into());
for (block_no, _) in &self.traversing_order {
if !self.reverse_dag[*block_no].is_empty() {
let divided_flow = &flow[*block_no]
/ (BigRational::from_integer(self.reverse_dag[*block_no].len().into()));
for child in &self.reverse_dag[*block_no] {
flow[*child] += ÷d_flow;
}
}
}
flow
}
pub(super) fn find_ancestor(
&self,
block_1: usize,
block_2: usize,
expr: &Expression,
) -> Option<usize> {
if block_1 == block_2 {
return Some(block_1);
}
let flow = self.calculate_flow(block_1, block_2);
let mut candidate = usize::MAX;
for (block_no, flow_magnitude) in flow.iter().enumerate() {
if (candidate == usize::MAX || self.depth[block_no] > self.depth[candidate])
&& BigRational::from_integer((2 * SOURCE_FLOW).into()) == *flow_magnitude
&& self
.reverse_sets
.get(&block_no)
.unwrap()
.find_expression(expr)
.is_some()
{
candidate = block_no;
}
}
if candidate < usize::MAX {
Some(candidate)
} else {
None
}
}
}
#[test]
fn test_depth() {
let dag = vec![
vec![1, 2], vec![3, 4], vec![3, 4], vec![], vec![], ];
let mut depth: Vec<u16> = vec![u16::MAX; 5];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 1, 2, 2]);
let dag = vec![
vec![1, 2, 4], vec![2, 3], vec![4], vec![], vec![], ];
let mut depth: Vec<u16> = vec![u16::MAX; 5];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 1, 2, 1]);
let dag = vec![
vec![1, 4], vec![2, 3], vec![], vec![5], vec![5], vec![], ];
let mut depth: Vec<u16> = vec![u16::MAX; 6];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 2, 2, 1, 2]);
let dag = vec![
vec![1, 6], vec![2, 4], vec![3, 4], vec![], vec![5], vec![], vec![4, 7, 8], vec![5], vec![], ];
let mut depth: Vec<u16> = vec![u16::MAX; 9];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 2, 3, 2, 3, 1, 2, 2]);
let dag = vec![
vec![1, 3], vec![2, 4], vec![7, 8, 6], vec![2, 6], vec![7, 5], vec![], vec![], vec![], vec![], ];
let mut depth: Vec<u16> = vec![u16::MAX; 9];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 2, 1, 2, 3, 2, 3, 3]);
let dag = vec![
vec![1], vec![2], vec![3], vec![1], ];
let mut depth: Vec<u16> = vec![u16::MAX; 4];
AnticipatedExpressions::blocks_depth(&dag, 0, 0, &mut depth);
assert_eq!(depth, vec![0, 1, 2, 3]);
}