|
@@ -2,7 +2,8 @@
|
|
|
|
|
|
|
|
#![cfg(test)]
|
|
#![cfg(test)]
|
|
|
|
|
|
|
|
-use crate::codegen::cfg::Instr;
|
|
|
|
|
|
|
+use crate::codegen::cfg::{ASTFunction, BasicBlock, ControlFlowGraph, Instr};
|
|
|
|
|
+use crate::codegen::subexpression_elimination::anticipated_expressions::AnticipatedExpressions;
|
|
|
use crate::codegen::subexpression_elimination::common_subexpression_tracker::CommonSubExpressionTracker;
|
|
use crate::codegen::subexpression_elimination::common_subexpression_tracker::CommonSubExpressionTracker;
|
|
|
use crate::codegen::subexpression_elimination::{AvailableExpression, AvailableExpressionSet};
|
|
use crate::codegen::subexpression_elimination::{AvailableExpression, AvailableExpressionSet};
|
|
|
use crate::codegen::Expression;
|
|
use crate::codegen::Expression;
|
|
@@ -33,7 +34,7 @@ fn add_variable_function_arg() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&var).is_some());
|
|
assert!(set.find_expression(&var).is_some());
|
|
|
assert!(set.find_expression(&arg).is_some());
|
|
assert!(set.find_expression(&arg).is_some());
|
|
@@ -59,7 +60,7 @@ fn add_constants() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&var).is_some());
|
|
assert!(set.find_expression(&var).is_some());
|
|
|
assert!(set.find_expression(&num).is_some());
|
|
assert!(set.find_expression(&num).is_some());
|
|
@@ -95,7 +96,7 @@ fn add_commutative() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&expr).is_some());
|
|
assert!(set.find_expression(&expr).is_some());
|
|
|
assert!(set.find_expression(&expr_other).is_some());
|
|
assert!(set.find_expression(&expr_other).is_some());
|
|
@@ -130,7 +131,7 @@ fn non_commutative() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&sub).is_some());
|
|
assert!(set.find_expression(&sub).is_some());
|
|
|
assert!(set.find_expression(&num).is_some());
|
|
assert!(set.find_expression(&num).is_some());
|
|
@@ -159,7 +160,7 @@ fn unary_operation() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&cast).is_some());
|
|
assert!(set.find_expression(&cast).is_some());
|
|
|
assert!(set.find_expression(&exp).is_some());
|
|
assert!(set.find_expression(&exp).is_some());
|
|
@@ -189,7 +190,7 @@ fn not_tracked() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&minus).is_none());
|
|
assert!(set.find_expression(&minus).is_none());
|
|
|
assert!(set.find_expression(&exp).is_none());
|
|
assert!(set.find_expression(&exp).is_none());
|
|
@@ -214,7 +215,7 @@ fn invalid() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&arg).is_none());
|
|
assert!(set.find_expression(&arg).is_none());
|
|
|
assert!(set.find_expression(&exp).is_none());
|
|
assert!(set.find_expression(&exp).is_none());
|
|
@@ -289,7 +290,7 @@ fn complex_expression() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&pot).is_some());
|
|
assert!(set.find_expression(&pot).is_some());
|
|
|
assert!(set.find_expression(&unary).is_some());
|
|
assert!(set.find_expression(&unary).is_some());
|
|
@@ -349,7 +350,7 @@ fn string() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
assert!(set.find_expression(&concat).is_some());
|
|
assert!(set.find_expression(&concat).is_some());
|
|
|
assert!(set.find_expression(&compare).is_some());
|
|
assert!(set.find_expression(&compare).is_some());
|
|
@@ -429,7 +430,7 @@ fn kill() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
set.kill(2);
|
|
set.kill(2);
|
|
|
|
|
|
|
|
// Available expressions
|
|
// Available expressions
|
|
@@ -518,8 +519,8 @@ fn clone() {
|
|
|
let mut set = AvailableExpressionSet::default();
|
|
let mut set = AvailableExpressionSet::default();
|
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
- let set_2 = set.clone_for_parent_block(1);
|
|
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
+ let set_2 = set.clone_for_parent_block();
|
|
|
|
|
|
|
|
// Available expressions
|
|
// Available expressions
|
|
|
assert!(set_2.find_expression(&unary).is_some());
|
|
assert!(set_2.find_expression(&unary).is_some());
|
|
@@ -608,21 +609,6 @@ fn intersect() {
|
|
|
value: vec![var2.clone(), var3.clone()],
|
|
value: vec![var2.clone(), var3.clone()],
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let mut ave = AvailableExpression::default();
|
|
|
|
|
- let mut set = AvailableExpressionSet::default();
|
|
|
|
|
- let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
- let cfg_dag = vec![vec![1, 2], vec![], vec![1]];
|
|
|
|
|
- cst.set_dag(cfg_dag);
|
|
|
|
|
-
|
|
|
|
|
- ave.set_cur_block(0);
|
|
|
|
|
- cst.set_cur_block(0);
|
|
|
|
|
- set.process_instruction(&instr, &mut ave, &mut cst);
|
|
|
|
|
- set.process_instruction(&instr2, &mut ave, &mut cst);
|
|
|
|
|
- let mut set_2 = set.clone_for_parent_block(0);
|
|
|
|
|
- cst.set_cur_block(2);
|
|
|
|
|
- ave.set_cur_block(2);
|
|
|
|
|
- set.kill(1);
|
|
|
|
|
-
|
|
|
|
|
let sum2 = Expression::Add(
|
|
let sum2 = Expression::Add(
|
|
|
Loc::Codegen,
|
|
Loc::Codegen,
|
|
|
Type::Int(8),
|
|
Type::Int(8),
|
|
@@ -645,10 +631,38 @@ fn intersect() {
|
|
|
value: Box::new(sub2.clone()),
|
|
value: Box::new(sub2.clone()),
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- set.process_instruction(&instr3, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ let mut ave = AvailableExpression::default();
|
|
|
|
|
+ let mut set = AvailableExpressionSet::default();
|
|
|
|
|
+ let mut cst = CommonSubExpressionTracker::default();
|
|
|
|
|
+ let cfg_dag = vec![vec![1, 2], vec![], vec![1]];
|
|
|
|
|
+ let reverse_dag = vec![vec![], vec![0, 2], vec![0]];
|
|
|
|
|
+ let traversing_order = vec![(1, false), (2, false), (0, false)];
|
|
|
|
|
+ let mut anticipated = AnticipatedExpressions::new(&cfg_dag, reverse_dag, traversing_order);
|
|
|
|
|
+
|
|
|
|
|
+ let instructions = vec![
|
|
|
|
|
+ vec![instr.clone(), instr2.clone()],
|
|
|
|
|
+ vec![instr3.clone()],
|
|
|
|
|
+ vec![instr3.clone()],
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let mut cfg = ControlFlowGraph::new("name".to_string(), ASTFunction::None);
|
|
|
|
|
+ cfg.blocks = vec![BasicBlock::default(); 3];
|
|
|
|
|
+ anticipated.calculate_anticipated_expressions(&instructions, &cfg);
|
|
|
|
|
+ cst.set_anticipated(anticipated);
|
|
|
|
|
+
|
|
|
|
|
+ ave.set_cur_block(0);
|
|
|
|
|
+ cst.set_cur_block(0);
|
|
|
|
|
+ set.process_instruction(&instr, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
+ set.process_instruction(&instr2, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
+ let mut set_2 = set.clone().clone_for_parent_block();
|
|
|
|
|
+ cst.set_cur_block(2);
|
|
|
|
|
+ ave.set_cur_block(2);
|
|
|
|
|
+ set.kill(1);
|
|
|
|
|
+
|
|
|
|
|
+ set.process_instruction(&instr3, &mut ave, &mut Some(&mut cst));
|
|
|
cst.set_cur_block(1);
|
|
cst.set_cur_block(1);
|
|
|
ave.set_cur_block(1);
|
|
ave.set_cur_block(1);
|
|
|
- set_2.process_instruction(&instr3, &mut ave, &mut cst);
|
|
|
|
|
|
|
+ set_2.process_instruction(&instr3, &mut ave, &mut Some(&mut cst));
|
|
|
|
|
|
|
|
set_2.intersect_sets(&set, &cst);
|
|
set_2.intersect_sets(&set, &cst);
|
|
|
|
|
|
|
@@ -674,3 +688,381 @@ fn intersect() {
|
|
|
// Child of expression created on both sets should not be available
|
|
// Child of expression created on both sets should not be available
|
|
|
assert!(set_2.find_expression(&sub2).is_none());
|
|
assert!(set_2.find_expression(&sub2).is_none());
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#[test]
|
|
|
|
|
+fn test_flow() {
|
|
|
|
|
+ // Case 1:
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 2], // 0 -> 1, 2
|
|
|
|
|
+ vec![3, 4], // 1 -> 3, 4
|
|
|
|
|
+ vec![3, 4], // 2 -> 3, 4
|
|
|
|
|
+ vec![], // 3
|
|
|
|
|
+ vec![], // 4
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![],
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![0], // 2 -> 0
|
|
|
|
|
+ vec![1, 2], // 3 -> 1, 2
|
|
|
|
|
+ vec![1, 2], // 4 -> 1, 2
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![(0, false), (1, false), (2, false), (3, false), (4, false)];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let anticipated = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let flow = anticipated.calculate_flow(3, 4);
|
|
|
|
|
+ assert_eq!(flow, vec![2000.0, 1000.0, 1000.0, 1000.0, 1000.0]);
|
|
|
|
|
+
|
|
|
|
|
+ // Case 2:
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 2, 4], // 0 -> 1, 2, 4
|
|
|
|
|
+ vec![2, 3], // 1 -> 2, 3
|
|
|
|
|
+ vec![4], // 2 -> 4
|
|
|
|
|
+ vec![], // 3
|
|
|
|
|
+ vec![], // 4
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![1, 0], // 2 -> 1, 0
|
|
|
|
|
+ vec![1], // 3 -> 1
|
|
|
|
|
+ vec![0, 2], // 4 -> 0, 2
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![(0, false), (1, false), (2, false), (3, false), (4, false)];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let anticipated_expressions = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(3, 4);
|
|
|
|
|
+ assert_eq!(flow, vec![2000.0, 1250.0, 500.0, 1000.0, 1000.0]);
|
|
|
|
|
+
|
|
|
|
|
+ // Case 3
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 4], // 0 -> 1, 4
|
|
|
|
|
+ vec![2, 3], // 1 -> 2, 3
|
|
|
|
|
+ vec![], // 2
|
|
|
|
|
+ vec![5], // 3 -> 5
|
|
|
|
|
+ vec![5], // 4 -> 5
|
|
|
|
|
+ vec![], // 5
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![1], // 2 -> 1
|
|
|
|
|
+ vec![1], // 3 -> 1
|
|
|
|
|
+ vec![0], // 4 -> 0
|
|
|
|
|
+ vec![3, 4], // 5 -> 3, 4
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![
|
|
|
|
|
+ (0, false),
|
|
|
|
|
+ (1, false),
|
|
|
|
|
+ (4, false),
|
|
|
|
|
+ (2, false),
|
|
|
|
|
+ (3, false),
|
|
|
|
|
+ (5, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let anticipated_expressions = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(4, 5);
|
|
|
|
|
+ assert_eq!(flow, vec![2000.0, 500.0, 0.0, 500.0, 1500.0, 1000.0]);
|
|
|
|
|
+
|
|
|
|
|
+ // Case 4
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 6], // 0 -> 1, 6
|
|
|
|
|
+ vec![2, 4], // 1 -> 2, 4
|
|
|
|
|
+ vec![3, 4], // 2 -> 3, 4
|
|
|
|
|
+ vec![], // 3
|
|
|
|
|
+ vec![5], // 4 -> 5
|
|
|
|
|
+ vec![], // 5
|
|
|
|
|
+ vec![4, 7, 8], // 6 -> 4, 7, 8
|
|
|
|
|
+ vec![5], // 7 -> 5
|
|
|
|
|
+ vec![], // 8
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![1], // 2 -> 1
|
|
|
|
|
+ vec![2], // 3 -> 2
|
|
|
|
|
+ vec![2, 1, 6], // 4 -> 2, 1, 6
|
|
|
|
|
+ vec![4], // 5 -> 4
|
|
|
|
|
+ vec![0], // 6 -> 0
|
|
|
|
|
+ vec![6], // 7 -> 6
|
|
|
|
|
+ vec![6], // 8 -> 6
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![
|
|
|
|
|
+ (0, false),
|
|
|
|
|
+ (1, false),
|
|
|
|
|
+ (6, false),
|
|
|
|
|
+ (8, false),
|
|
|
|
|
+ (7, false),
|
|
|
|
|
+ (2, false),
|
|
|
|
|
+ (3, false),
|
|
|
|
|
+ (4, false),
|
|
|
|
|
+ (5, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let anticipated_expressions = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(5, 8);
|
|
|
|
|
+ for (item_no, flow_mag) in flow.iter().enumerate() {
|
|
|
|
|
+ if item_no == 0 {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() < 0.000001);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() > 0.000001);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(3, 5);
|
|
|
|
|
+ for (item_no, flow_mag) in flow.iter().enumerate() {
|
|
|
|
|
+ if item_no == 0 {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() < 0.000001);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() > 0.000001);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Case 5
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 3], // 0 -> 1, 3
|
|
|
|
|
+ vec![2, 4], // 1 -> 2, 4
|
|
|
|
|
+ vec![7, 8, 6], // 2 -> 7, 8, 6
|
|
|
|
|
+ vec![2, 6], // 3 -> 2, 6
|
|
|
|
|
+ vec![7, 5], // 4 -> 7, 5
|
|
|
|
|
+ vec![], // 5
|
|
|
|
|
+ vec![], // 6
|
|
|
|
|
+ vec![], // 7
|
|
|
|
|
+ vec![], // 8
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![1, 3], // 2 -> 1, 3
|
|
|
|
|
+ vec![0], // 3 -> 0
|
|
|
|
|
+ vec![1], // 4 -> 1
|
|
|
|
|
+ vec![4], // 5 -> 4
|
|
|
|
|
+ vec![2, 3], // 6 -> 2, 3
|
|
|
|
|
+ vec![4, 2], // 7 -> 2, 4
|
|
|
|
|
+ vec![2], // 8 -> 2
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![
|
|
|
|
|
+ (0, false),
|
|
|
|
|
+ (1, false),
|
|
|
|
|
+ (3, false),
|
|
|
|
|
+ (4, false),
|
|
|
|
|
+ (2, false),
|
|
|
|
|
+ (5, false),
|
|
|
|
|
+ (6, false),
|
|
|
|
|
+ (7, false),
|
|
|
|
|
+ (8, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let anticipated_expressions = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(8, 6);
|
|
|
|
|
+ for (item_no, flow_mag) in flow.iter().enumerate() {
|
|
|
|
|
+ if item_no == 0 {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() < 0.000001);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() > 0.000001);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ let flow = anticipated_expressions.calculate_flow(8, 3);
|
|
|
|
|
+ for (item_no, flow_mag) in flow.iter().enumerate() {
|
|
|
|
|
+ if item_no == 0 {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() < 0.000001);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assert!((*flow_mag - 2000.0).abs() > 0.000001);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[test]
|
|
|
|
|
+fn unite_expressions() {
|
|
|
|
|
+ let var = Expression::Variable(Loc::Codegen, Type::Int(8), 1);
|
|
|
|
|
+ let cte = Expression::NumberLiteral(Loc::Codegen, Type::Int(8), BigInt::from(3));
|
|
|
|
|
+ let arg = Expression::FunctionArg(Loc::Codegen, Type::Int(9), 5);
|
|
|
|
|
+
|
|
|
|
|
+ let sum = Expression::Add(
|
|
|
|
|
+ Loc::Codegen,
|
|
|
|
|
+ Type::Int(8),
|
|
|
|
|
+ false,
|
|
|
|
|
+ Box::new(var.clone()),
|
|
|
|
|
+ Box::new(cte.clone()),
|
|
|
|
|
+ );
|
|
|
|
|
+ let sub = Expression::Subtract(
|
|
|
|
|
+ Loc::Codegen,
|
|
|
|
|
+ Type::Int(3),
|
|
|
|
|
+ false,
|
|
|
|
|
+ Box::new(cte.clone()),
|
|
|
|
|
+ Box::new(arg.clone()),
|
|
|
|
|
+ );
|
|
|
|
|
+ let div = Expression::SignedDivide(Loc::Codegen, Type::Int(8), Box::new(sum), Box::new(sub));
|
|
|
|
|
+ let mul = Expression::Multiply(
|
|
|
|
|
+ Loc::Codegen,
|
|
|
|
|
+ Type::Int(8),
|
|
|
|
|
+ false,
|
|
|
|
|
+ Box::new(var),
|
|
|
|
|
+ Box::new(cte.clone()),
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ let shift = Expression::ShiftRight(
|
|
|
|
|
+ Loc::Codegen,
|
|
|
|
|
+ Type::Int(2),
|
|
|
|
|
+ Box::new(mul),
|
|
|
|
|
+ Box::new(div),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ let modu = Expression::SignedModulo(Loc::Codegen, Type::Int(8), Box::new(cte), Box::new(arg));
|
|
|
|
|
+
|
|
|
|
|
+ let mut set_1 = AvailableExpressionSet::default();
|
|
|
|
|
+ let mut ave = AvailableExpression::default();
|
|
|
|
|
+ let _ = set_1.gen_expression_aux(&shift, &mut ave, &mut None);
|
|
|
|
|
+
|
|
|
|
|
+ let mut set_2 = AvailableExpressionSet::default();
|
|
|
|
|
+ let _ = set_2.gen_expression_aux(&modu, &mut ave, &mut None);
|
|
|
|
|
+
|
|
|
|
|
+ assert!(set_1.find_expression(&shift).is_some());
|
|
|
|
|
+ assert!(set_1.find_expression(&modu).is_none());
|
|
|
|
|
+ assert!(set_2.find_expression(&shift).is_none());
|
|
|
|
|
+ assert!(set_2.find_expression(&modu).is_some());
|
|
|
|
|
+
|
|
|
|
|
+ set_1.union_sets(&set_2);
|
|
|
|
|
+
|
|
|
|
|
+ let id_1 = set_1.find_expression(&shift);
|
|
|
|
|
+ assert!(id_1.is_some());
|
|
|
|
|
+ let id_2 = set_1.find_expression(&modu);
|
|
|
|
|
+ assert!(id_2.is_some());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[test]
|
|
|
|
|
+fn ancestor_found() {
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1], // 0 -> 1
|
|
|
|
|
+ vec![2, 3], // 1 -> 2, 3
|
|
|
|
|
+ vec![], // 2
|
|
|
|
|
+ vec![], // 3
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![1], // 2 -> 1
|
|
|
|
|
+ vec![1], // 3 -> 1
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![(0, false), (1, false), (2, false), (3, false)];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let mut anticipated = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let var1 = Expression::Variable(Loc::Implicit, Type::Uint(32), 0);
|
|
|
|
|
+ let var2 = Expression::Variable(Loc::Implicit, Type::Uint(32), 1);
|
|
|
|
|
+ let addition = Expression::Add(
|
|
|
|
|
+ Loc::Implicit,
|
|
|
|
|
+ Type::Uint(32),
|
|
|
|
|
+ false,
|
|
|
|
|
+ Box::new(var1.clone()),
|
|
|
|
|
+ Box::new(var2.clone()),
|
|
|
|
|
+ );
|
|
|
|
|
+ let instr = vec![
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 0,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Uint(32), 9.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 1,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Uint(32), 8.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::Branch { block: 1 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ vec![Instr::BranchCond {
|
|
|
|
|
+ cond: Expression::LessEqual(Loc::Implicit, Box::new(var1), Box::new(var2)),
|
|
|
|
|
+ true_block: 2,
|
|
|
|
|
+ false_block: 3,
|
|
|
|
|
+ }],
|
|
|
|
|
+ vec![Instr::Set {
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ res: 3,
|
|
|
|
|
+ expr: addition.clone(),
|
|
|
|
|
+ }],
|
|
|
|
|
+ vec![Instr::Set {
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ res: 4,
|
|
|
|
|
+ expr: addition.clone(),
|
|
|
|
|
+ }],
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut cfg = ControlFlowGraph::new("func".to_string(), ASTFunction::None);
|
|
|
|
|
+ cfg.blocks = vec![BasicBlock::default(); 4];
|
|
|
|
|
+ anticipated.calculate_anticipated_expressions(&instr, &cfg);
|
|
|
|
|
+ let ancestor = anticipated.find_ancestor(2, 3, &addition);
|
|
|
|
|
+ assert_eq!(ancestor, Some(1));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[test]
|
|
|
|
|
+fn ancestor_not_found() {
|
|
|
|
|
+ let dag = vec![
|
|
|
|
|
+ vec![1, 2], // 0 -> 1, 2
|
|
|
|
|
+ vec![3], // 1 -> 3
|
|
|
|
|
+ vec![], // 2
|
|
|
|
|
+ vec![], // 3
|
|
|
|
|
+ ];
|
|
|
|
|
+ let reverse_dag = vec![
|
|
|
|
|
+ vec![], // 0
|
|
|
|
|
+ vec![0], // 1 -> 0
|
|
|
|
|
+ vec![0], // 2 -> 0
|
|
|
|
|
+ vec![1], // 3 -> 1
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut traversing_order = vec![(0, false), (0, false), (2, false), (3, false)];
|
|
|
|
|
+ traversing_order.reverse();
|
|
|
|
|
+ let mut anticipated = AnticipatedExpressions::new(&dag, reverse_dag, traversing_order);
|
|
|
|
|
+ let var1 = Expression::Variable(Loc::Implicit, Type::Int(32), 0);
|
|
|
|
|
+ let var2 = Expression::Variable(Loc::Implicit, Type::Int(32), 1);
|
|
|
|
|
+ let expr = Expression::Multiply(
|
|
|
|
|
+ Loc::Implicit,
|
|
|
|
|
+ Type::Int(32),
|
|
|
|
|
+ false,
|
|
|
|
|
+ Box::new(var1.clone()),
|
|
|
|
|
+ Box::new(var2.clone()),
|
|
|
|
|
+ );
|
|
|
|
|
+ let instr = vec![
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 0,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Int(32), 8.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 1,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Int(32), 7.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::BranchCond {
|
|
|
|
|
+ cond: Expression::MoreEqual(Loc::Implicit, Box::new(var1), Box::new(var2)),
|
|
|
|
|
+ true_block: 1,
|
|
|
|
|
+ false_block: 2,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 0,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Int(32), 10.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::Set {
|
|
|
|
|
+ res: 1,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: Expression::NumberLiteral(Loc::Implicit, Type::Int(32), 27.into()),
|
|
|
|
|
+ },
|
|
|
|
|
+ Instr::Branch { block: 3 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ vec![Instr::Set {
|
|
|
|
|
+ res: 2,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: expr.clone(),
|
|
|
|
|
+ }],
|
|
|
|
|
+ vec![Instr::Set {
|
|
|
|
|
+ res: 3,
|
|
|
|
|
+ loc: Loc::Implicit,
|
|
|
|
|
+ expr: expr.clone(),
|
|
|
|
|
+ }],
|
|
|
|
|
+ ];
|
|
|
|
|
+ let mut cfg = ControlFlowGraph::new("func".to_string(), ASTFunction::None);
|
|
|
|
|
+ cfg.blocks = vec![BasicBlock::default(); 4];
|
|
|
|
|
+ anticipated.calculate_anticipated_expressions(&instr, &cfg);
|
|
|
|
|
+ let ancestor = anticipated.find_ancestor(2, 3, &expr);
|
|
|
|
|
+ assert!(ancestor.is_none());
|
|
|
|
|
+}
|