Skip to content

Commit

Permalink
Add more codegen tests
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Nov 6, 2021
1 parent a3c9d12 commit 87ffbd6
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 15 deletions.
23 changes: 11 additions & 12 deletions examples/test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,26 @@ contract foo {
function test10(int a, int b) public returns (int) {
string ast = "Hello!";
string bst = "from Solang";
//string cst = ast + bst;
string cst = ast + bst;

// int p = a + get(a/(2*b), b);
int p = a + get(a/(2*b), b);

bool e = (ast == bst);// || p < 2;
bool e = (ast == bst) || p < 2;
bool e2 = e;
// if (ast + bst == cst) {
// require(a + get(a/(2*b), b) < 0);
// emit testEvent(a + get(a/(2*b) -p, b), p, ast+bst);
// }
if (ast + bst == cst) {
require(a + get(a/(2*b), b) < 0);
emit testEvent(a + get(a/(2*b) -p, b), p, ast+bst);
}

// if (ast == bst) {
// ast = ast + "a";
// }
if (ast == bst) {
ast = ast + "b";
}

// Error here + seg fault
while (ast == bst) {
ast = ast + "a";
}

return get(b, a/b);
return 2;//get(b, a/b);
}

function test11(int a, int b) public returns (int) {
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ pub struct BasicBlock {
pub name: String,
pub instr: Vec<Instr>,
pub defs: reaching_definitions::VarDefs,
pub loop_reaching_variables: HashSet<usize>,
pub transfers: Vec<Vec<reaching_definitions::Transfer>>,
}

Expand Down Expand Up @@ -368,6 +369,7 @@ impl ControlFlowGraph {
phis: None,
transfers: Vec::new(),
defs: HashMap::new(),
loop_reaching_variables: HashSet::new(),
});

pos
Expand Down
9 changes: 9 additions & 0 deletions src/codegen/reaching_definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ pub fn find(cfg: &mut ControlFlowGraph) {
} else {
cfg.blocks[edge].defs.insert(*var_no, defs.clone());
}

// If a definition from a block executed later reaches this block,
// this is a loop. This is an analysis we use later at the
// common subexpression elimination.
for (incoming_def , _) in defs {
if incoming_def.block_no > edge {
cfg.blocks[edge].loop_reaching_variables.insert(*var_no);
}
}
}
}
}
Expand Down
11 changes: 8 additions & 3 deletions src/codegen/subexpression_elimination/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub fn common_sub_expression_elimination(cfg: &mut ControlFlowGraph, ns: &mut Na
for block_no in &visiting_order {
let cur_block = &cfg.blocks[*block_no];
let mut cur_set = sets.remove(block_no).unwrap();
kill_loop_variables(cur_block, &mut cur_set);
for (pos, instr) in cur_block.instr.iter().enumerate() {
for transfer in &cur_block.transfers[pos] {
if let Transfer::Kill { var_no } = transfer {
Expand All @@ -112,8 +113,6 @@ pub fn common_sub_expression_elimination(cfg: &mut ControlFlowGraph, ns: &mut Na
}

cst.create_variables(ns, cfg);
// TODO: Is this necessary?
sets.clear();

let mut ave = AvailableExpression::default();
sets.insert(0, AvailableExpressionSet::default());
Expand All @@ -122,7 +121,7 @@ pub fn common_sub_expression_elimination(cfg: &mut ControlFlowGraph, ns: &mut Na
let mut cur_set = sets.remove(block_no).unwrap();
let mut cur_block = &mut cfg.blocks[*block_no];
let mut new_instructions: Vec<Instr> = Vec::new();

kill_loop_variables(cur_block, &mut cur_set);
for (pos, instr) in cur_block.instr.iter().enumerate() {
for transfer in &cur_block.transfers[pos] {
if let Transfer::Kill { var_no } = transfer {
Expand Down Expand Up @@ -161,6 +160,12 @@ fn add_neighbor_blocks(
}
}

fn kill_loop_variables(block: &BasicBlock, cur_set: &mut AvailableExpressionSet) {
for var_no in &block.loop_reaching_variables {
cur_set.kill(*var_no);
}
}

/// Find the correct visiting order for the CFG traversal. The visiting order should be the same
/// as the execution order.
fn find_visiting_order(cfg: &ControlFlowGraph) -> Vec<usize> {
Expand Down
86 changes: 86 additions & 0 deletions tests/codegen_testcases/common_subexpression_elimination.sol
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,90 @@ contract c1 {
ret = a*b;
}

// BEGIN-CHECK: c1::function::test10
function test10(int a, int b) public pure returns (int) {
int x;
x = a+b-54;
int d = x*(a+b);
int k = x+d;
bool e = k < 0;

do {
int t = a-b;
bool e1 = t > 3;
// CHECK: ty:int256 %x = (%x + %d)
x = x+d;
// CHECK: branchcond ((%x + %d) > int256 0), block1, block3
} while(x+d > 0);
int t = 3;
bool p = t < 2;

// CHECK: return ((%x - %d) + %t
return x-d + (a-b);
}


// function get(int a, int b) private pure returns (int) {
// return a+b+1;
// }

// event testEvent(int a, int b, string str);
// // BEGIN-CHECK: c1::function::test11
// function test11(int a, int b) public returns (int) {
// string ast = "Hello!";
// string bst = "from Solang";
// string cst = ast + bst;
// // CHECK: ty:int256 %1.cse_temp = ((arg #0) / (int256 2 * (arg #1)))
// // CHECK: call c1::c1::function::get__int256_int256 %1.cse_temp, (arg #1)
// int p = a + get(a/(2*b), b);

// bool e = (ast == bst) || p < 2;
// // CHECK: ty:bool %2.cse_temp = (strcmp (%ast) (%bst))
// // CHECK: branchcond %2.cse_temp, block2, block1
// bool e2 = e;
// // CHECK: branchcond (strcmp (%cst) (%cst)), block3, block4
// if (ast + bst == cst) {
// // CHECK: call c1::c1::function::get__int256_int256 %1.cse_temp, (arg #1)
// require(a + get(a/(2*b), b) < 0);
// emit testEvent(a + get(a/(2*b) -p, b), p, ast+bst);
// }

// // CHECK: branchcond %2.cse_temp, block7, block8
// if (ast == bst) {
// ast = ast + "b";
// }
// // CHECK: call c1::c1::function::get__int256_int256 (%1.cse_temp - %p), (arg #1)

// // CHECK: branchcond (strcmp (%ast) (%bst)), block10, block11
// while (ast == bst) {
// ast = ast + "a";
// }

// // CHECK: call c1::c1::function::get__int256_int256 (arg #1), ((arg #0) / (arg #1))
// return get(b, a/b);
// }

// BEGIN-CHECK: c1::function::test12
function test12(int a, int b) public returns (int) {
int x = a+b;
bool e = (x == a);
// NOT-CHECK: %1.cse_temp =
bool e2 = e;

// CHECK: branchcond (%x == (arg #0))
while(x == a) {
x = x+1;
// NOT-CHECK: cse_temp
x+=1;
x++;
x--;
x++;
x--;
--x;
++x;
}

return x;
}

}

0 comments on commit 87ffbd6

Please sign in to comment.