def test_acyclic_inconsistent_nested_branches(self): def refG(pred): invpred = 1 - pred G = cfg_model.cfg() a = G.make_node('branch p') b = G.make_node('branch p') c = G.make_node('let c := 0') letp_c = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_d = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_e = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(invpred)))) n = G.make_node(stmts.null_stmt()) d = G.make_node('let d := 0') e = G.make_node('let e := 0') rebranch = G.make_node(stmts.branch_stmt(stmts.var_expr('$p'))) f = G.make_node('let f := 0') empty = G.make_node(stmts.null_stmt()) g = G.make_node('let g := 0') G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(b, d, 0) G.make_edge(b, e, 1) G.make_edge(c, letp_c) G.make_edge(d, letp_d) G.make_edge(e, letp_e) G.make_edge(letp_d, n) G.make_edge(letp_e, n) G.make_edge(letp_c, rebranch) G.make_edge(n, rebranch) G.make_edge(rebranch, f, pred) G.make_edge(rebranch, empty, invpred) G.make_edge(f, g) G.make_edge(empty, g) return G G = cfg_model.cfg() a = G.make_node('branch p') b = G.make_node('branch p') c = G.make_node('let c := 0') d = G.make_node('let d := 0') e = G.make_node('let e := 0') f = G.make_node('let f := 0') g = G.make_node('let g := 0') G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(b, d, 0) G.make_edge(b, e, 1) G.make_edge(c, f) G.make_edge(d, f) G.make_edge(e, g) G.make_edge(f, g) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue( cfg_algorithm.equivalent(refG(1), newG) or cfg_algorithm.equivalent(refG(0), newG))
def test_acyclic_loop_pred_pseudo_pred(self): G = self._make_pseudo_loop_graph() newG = cfg2cfg.regularize_cfg_acyclic(G, True) ref0 = self._pseudo_loop_ref_graph(0, True) ref1 = self._pseudo_loop_ref_graph(1, True) self.assertTrue( cfg_algorithm.equivalent(ref0, newG) or cfg_algorithm.equivalent(ref1, newG))
def test_static_gamma(self): def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) l = cfg.make_node('let v3 := sub(v1, v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, l) cfg.make_edge(l, exit) return cfg rvsdg = rvsdg_model.rvsdg(('v1', 'v2')) static_decide = rvsdg.add_litnode((1, ), ('$r', )) alt1 = rvsdg_model.rvsdg(('v1', 'v2')) add = alt1.add_opnode('add', ('o1', 'o2'), ('v3', ), ((None, 'v1'), (None, 'v2'))) alt1.add_result('v3', (add, 'v3')) alt2 = rvsdg_model.rvsdg(('v1', 'v2')) add = alt2.add_opnode('sub', ('o1', 'o2'), ('v3', ), ((None, 'v1'), (None, 'v2'))) alt2.add_result('v3', (add, 'v3')) gamma = rvsdg.add_gamma((alt1, alt2), ((None, 'v1'), (None, 'v2')), (static_decide, '$r')) rvsdg.add_result('v3', (gamma, 'v3')) #rvsdg_view.show(rvsdg) cfg = rvsdg2cfg.convert(rvsdg) cfg_algorithm.prune(cfg) #cfg_view.show(cfg) self.assertTrue(cfg_algorithm.equivalent(cfg, refG()))
def test_simple_theta(self): def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let v1, z := dec(v1)') b = cfg.make_node('let v2 := sqr(v2)') c = cfg.make_node('branch z') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c) cfg.make_edge(c, a, index=1) cfg.make_edge(c, exit, index=0) return cfg rvsdg = rvsdg_model.rvsdg(('v1', 'v2')) loop_body = rvsdg_model.rvsdg(('v1', 'v2')) dec = loop_body.add_opnode('dec', ('v1', ), ('v1', 'z'), ((None, 'v1'), )) mul = loop_body.add_opnode('sqr', ('v2', ), ('v2', ), ((None, 'v2'), )) tst = loop_body.add_selectnode(((0, ), (1, )), 'z', ('$repeat', ), (dec, 'z')) loop_body.add_result('v1', (dec, 'v1')) loop_body.add_result('v2', (mul, 'v2')) loop_body.add_result('$repeat', (tst, '$repeat')) loop = rvsdg.add_theta(loop_body, ((None, 'v1'), (None, 'v2'))) rvsdg.add_result('v1', (loop, 'v1')) rvsdg.add_result('v2', (loop, 'v2')) #rvsdg_view.show(rvsdg) cfg = rvsdg2cfg.convert(rvsdg) #cfg_algorithm.prune(cfg) #cfg_view.show(cfg) self.assertTrue(cfg_algorithm.equivalent(cfg, refG()))
def test_acyclic_simple(self): # graph consisting of a single node, no branches G = cfg_model.cfg() G.make_node('let a := 0') newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue(cfg_algorithm.equivalent(G, newG))
def test_multi_exit_theta(self): def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let v2 := sqr(v2)') b = cfg.make_node('let c := cmp(v1, v2)') c = cfg.make_node('branch c') d = cfg.make_node('let r:= mov(v1)') e = cfg.make_node('let r:= mov(v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c) cfg.make_edge(c, d, index=0) cfg.make_edge(c, a, index=1) cfg.make_edge(c, e, index=2) cfg.make_edge(d, exit) cfg.make_edge(e, exit) return cfg rvsdg = rvsdg_model.rvsdg(('v1', 'v2')) unused = rvsdg.add_litnode((0, ), ('$d', )) loop_body = rvsdg_model.rvsdg(('v1', 'v2', '$d')) mul = loop_body.add_opnode('sqr', ('v2', ), ('v2', ), ((None, 'v2'), )) compare = loop_body.add_opnode('cmp', ('v1', 'v2'), ('c'), ((None, 'v1'), (mul, 'v2'))) tst = loop_body.add_selectnode(((0, 0), (1, 0), (0, 1)), 'c', ('$repeat', '$d'), (compare, 'c')) loop_body.add_result('v1', (None, 'v1')) loop_body.add_result('v2', (mul, 'v2')) loop_body.add_result('$d', (tst, '$d')) loop_body.add_result('$repeat', (tst, '$repeat')) loop = rvsdg.add_theta(loop_body, ((None, 'v1'), (None, 'v2'), (unused, '$d'))) alt1 = rvsdg_model.rvsdg(('v1', 'v2')) mov1 = alt1.add_opnode('mov', ('v1', ), ('r', ), ((None, 'v1'), )) alt1.add_result('r', (mov1, 'r')) alt2 = rvsdg_model.rvsdg(('v1', 'v2')) mov1 = alt2.add_opnode('mov', ('v2', ), ('r', ), ((None, 'v2'), )) alt2.add_result('r', (mov1, 'r')) gamma = rvsdg.add_gamma((alt1, alt2), ((loop, 'v1'), (loop, 'v2')), (loop, '$d')) rvsdg.add_result('r', (gamma, 'r')) #rvsdg_view.show(rvsdg) cfg = rvsdg2cfg.convert(rvsdg) #cfg_algorithm.prune(cfg) #cfg_view.show(cfg) #cfg_view.show(refG()) self.assertTrue(cfg_algorithm.equivalent(cfg, refG()))
def test_acyclic_linear(self): # graph consisting of a linear node, no branches G = cfg_model.cfg() a = G.make_node('let a := 0') b = G.make_node('let b := 0') c = G.make_node('let c := 0') G.make_edge(a, b) G.make_edge(b, c) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue(cfg_algorithm.equivalent(G, newG))
def test_acyclic_consistent_branch(self): # graph consisting of a single consistent branch G = cfg_model.cfg() a = G.make_node('branch p') b = G.make_node('let b := 0') c = G.make_node('let c := 0') d = G.make_node('let d := 0') G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(b, d) G.make_edge(c, d) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue(cfg_algorithm.equivalent(G, newG))
def test_acyclic_break_join(self): # graph consisting of two nested branches, but the three # paths opened up by the two branches are joined into a single # node; need to insert a "null" stmt to strictly join the # inner nested branch, but no new branch is required def refG(): G = cfg_model.cfg() n = G.make_node('branch p') n1 = G.make_node('branch p') n2 = G.make_node('let c := 0') n11 = G.make_node('let d := 0') n12 = G.make_node('let e := 0') n1c = G.make_node(stmts.null_stmt()) nc = G.make_node('let g := 0') G.make_edge(n, n1, 0) G.make_edge(n, n2, 1) G.make_edge(n1, n11, 0) G.make_edge(n1, n12, 1) G.make_edge(n11, n1c) G.make_edge(n12, n1c) G.make_edge(n1c, nc) G.make_edge(n2, nc) return G G = cfg_model.cfg() n = G.make_node('branch p') n1 = G.make_node('branch p') n2 = G.make_node('let c := 0') n11 = G.make_node('let d := 0') n12 = G.make_node('let e := 0') nc = G.make_node('let g := 0') G.make_edge(n, n1, 0) G.make_edge(n, n2, 1) G.make_edge(n1, n11, 0) G.make_edge(n1, n12, 1) G.make_edge(n11, nc) G.make_edge(n12, nc) G.make_edge(n2, nc) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue(cfg_algorithm.equivalent(refG(), newG))
def test_dynamic_gamma(self): def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) c = cfg.make_node('let r := cmp(v1, v2)') b = cfg.make_node('branch r') alt1 = cfg.make_node('let v3 := add(v1, v2)') alt2 = cfg.make_node('let v3 := sub(v1, v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, c) cfg.make_edge(c, b) cfg.make_edge(b, alt1, index=0) cfg.make_edge(b, alt2, index=1) cfg.make_edge(alt1, exit) cfg.make_edge(alt2, exit) return cfg rvsdg = rvsdg_model.rvsdg(('v1', 'v2')) compare = rvsdg.add_opnode('cmp', ('a', 'b'), ('r', ), ((None, 'v1'), (None, 'v2'))) dynamic_decide = rvsdg.add_selectnode(((0, ), (1, )), 'r', ('$r', ), (compare, 'r')) alt1 = rvsdg_model.rvsdg(('v1', 'v2')) add = alt1.add_opnode('add', ('o1', 'o2'), ('v3', ), ((None, 'v1'), (None, 'v2'))) alt1.add_result('v3', (add, 'v3')) alt2 = rvsdg_model.rvsdg(('v1', 'v2')) add = alt2.add_opnode('sub', ('o1', 'o2'), ('v3', ), ((None, 'v1'), (None, 'v2'))) alt2.add_result('v3', (add, 'v3')) gamma = rvsdg.add_gamma((alt1, alt2), ((None, 'v1'), (None, 'v2')), (dynamic_decide, '$r')) rvsdg.add_result('v3', (gamma, 'v3')) #rvsdg_view.show(rvsdg) cfg = rvsdg2cfg.convert(rvsdg) cfg_algorithm.prune(cfg) #cfg_view.show(cfg) self.assertTrue(cfg_algorithm.equivalent(cfg, refG()))
def test_acyclic_consistent_nested_branch(self): # graph consisting of two nested branches, both # consistently joined G = cfg_model.cfg() n = G.make_node('branch p') n1 = G.make_node('branch p') n2 = G.make_node('let c := 0') n11 = G.make_node('let d := 0') n12 = G.make_node('let e := 0') n1c = G.make_node('let f := 0') nc = G.make_node('let g := 0') G.make_edge(n, n1, 0) G.make_edge(n, n2, 1) G.make_edge(n1, n11, 0) G.make_edge(n1, n12, 1) G.make_edge(n11, n1c) G.make_edge(n12, n1c) G.make_edge(n1c, nc) G.make_edge(n2, nc) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue(cfg_algorithm.equivalent(G, newG))
def test_multi_entry_theta(self): def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let c := gt(v1, v2)') b = cfg.make_node('branch c') c1 = cfg.make_node('let v1 := sub(v1, v2)') c2 = cfg.make_node('let v2 := sub(v2, v1)') d = cfg.make_node('let c := cmp(v1, v2)') e = cfg.make_node('branch c') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c1, index=0) cfg.make_edge(b, c2, index=1) cfg.make_edge(c1, d) cfg.make_edge(c2, d) cfg.make_edge(d, e) cfg.make_edge(e, c1, index=0) cfg.make_edge(e, c2, index=2) cfg.make_edge(e, exit, index=1) return cfg rvsdg = rvsdg_model.rvsdg(('v1', 'v2')) loop_body = rvsdg_model.rvsdg(('v1', 'v2', '$d')) alt1 = rvsdg_model.rvsdg(('v1', 'v2')) sub1 = alt1.add_opnode('sub', ('v1', 'v2'), ('v1', ), ((None, 'v1'), (None, 'v2'))) alt1.add_result('v1', (sub1, 'v1')) alt1.add_result('v2', (None, 'v2')) alt2 = rvsdg_model.rvsdg(('v1', 'v2')) sub2 = alt2.add_opnode('sub', ('v2', 'v1'), ('v2', ), ((None, 'v2'), (None, 'v1'))) alt2.add_result('v1', (None, 'v1')) alt2.add_result('v2', (sub2, 'v2')) gamma = loop_body.add_gamma((alt1, alt2), ((None, 'v1'), (None, 'v2')), (None, '$d')) compare = loop_body.add_opnode('cmp', ('v1', 'v2'), ('c'), ((gamma, 'v1'), (gamma, 'v2'))) tst = loop_body.add_selectnode(((1, 0), (0, 0), (1, 1)), 'c', ('$repeat', '$d'), (compare, 'c')) loop_body.add_result('v1', (gamma, 'v1')) loop_body.add_result('v2', (gamma, 'v2')) loop_body.add_result('$d', (tst, '$d')) loop_body.add_result('$repeat', (tst, '$repeat')) compare = rvsdg.add_opnode('gt', ('v1', 'v2'), ('c'), ((None, 'v1'), (None, 'v2'))) tst = rvsdg.add_selectnode(((0, ), (1, )), 'c', ('$d', ), (compare, 'c')) loop = rvsdg.add_theta(loop_body, ((None, 'v1'), (None, 'v2'), (tst, '$d'))) rvsdg.add_result('v1', (loop, 'v1')) rvsdg.add_result('v2', (loop, 'v2')) #rvsdg_view.show(rvsdg) cfg = rvsdg2cfg.convert(rvsdg) #cfg_algorithm.prune(cfg) #cfg_view.show(cfg) #cfg_view.show(refG()) self.assertTrue(cfg_algorithm.equivalent(cfg, refG()))
def test_acyclic_inconsistent_defer(self): # graph consisting of two nested branches, with predicate # assignments before the exit node; must make sure to defer # processing of predicate assignments so that it still # ends up just before the end of the graph after regularization def refG(pred): invpred = 1 - pred G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let v := a(P)') b = G.make_node('branch v') c = G.make_node('let w := b(P)') d = G.make_node('branch w') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') e2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('0'))) f2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) letp_1 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_2 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_3 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(invpred)))) null_23 = G.make_node(stmts.null_stmt()) branchp = G.make_node(stmts.branch_stmt(stmts.var_expr('$p'))) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, letp_1, index=1) G.make_edge(letp_1, branchp) G.make_edge(c, d) G.make_edge(d, e, index=0) G.make_edge(e, letp_3) G.make_edge(d, letp_2, index=1) G.make_edge(letp_2, null_23) G.make_edge(letp_3, null_23) G.make_edge(null_23, branchp) G.make_edge(branchp, f, pred) G.make_edge(f, f2) G.make_edge(f2, exit) G.make_edge(branchp, e2, invpred) G.make_edge(e2, exit) return G G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let v := a(P)') b = G.make_node('branch v') c = G.make_node('let w := b(P)') d = G.make_node('branch w') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') e2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('0'))) f2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, f, index=1) G.make_edge(c, d) G.make_edge(d, e, index=0) G.make_edge(d, f, index=1) G.make_edge(e, e2) G.make_edge(f, f2) G.make_edge(e2, exit) G.make_edge(f2, exit) newG = cfg2cfg.regularize_cfg_acyclic(G) self.assertTrue( cfg_algorithm.equivalent(refG(1), newG) or cfg_algorithm.equivalent(refG(0), newG))