예제 #1
0
    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))
예제 #2
0
 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))
예제 #3
0
    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()))
예제 #4
0
    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()))
예제 #5
0
    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))
예제 #6
0
    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()))
예제 #7
0
    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))
예제 #8
0
    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))
예제 #9
0
    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))
예제 #10
0
    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()))
예제 #11
0
    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))
예제 #12
0
    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()))
예제 #13
0
    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))