Ejemplo n.º 1
0
    def test_inconsistent_merge_vardef(self):
        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(('$p', ), stmts.parse_expr('0')))
        f2 = G.make_node(stmts.let_stmt(('$p', ), 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)

        #cfg_view.show(G)
        rvsdg = cfg2rvsdg.convert(G, ('P', ), ('P', '$p'), ('P', '$p'))
Ejemplo n.º 2
0
    def test_stmt_parse(self):
        s = stmts.parse_stmt('null')
        self.assertEquals(stmts.null_stmt(), s)

        s = stmts.parse_stmt('let a := 1')
        self.assertEquals(stmts.let_stmt(('a', ), stmts.parse_expr('1')), s)

        s = stmts.parse_stmt('let a, b := f(x), 1')
        self.assertEquals(
            stmts.let_stmt(('a', 'b'), stmts.parse_expr('f(x), 1')), s)

        s = stmts.parse_stmt('branch 1')
        self.assertEquals(stmts.branch_stmt(stmts.parse_expr('1')), s)
Ejemplo n.º 3
0
        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
Ejemplo n.º 4
0
	def emit_opnode(self, node, cfg_pred_edges):
		assert len(node.output_names) == len(set(node.output_names))
		args = [self.var_mapping.get_ssavar((node.region,) + o) for o in node.operands]
		ress = [self.var_mapping.make_ssavar((node.region, node, o)) for o in node.output_names]
		args = [stmts.var_expr(v) for v in args]
		rhs = stmts.call_expr(node.operator, args)
		stmt = stmts.let_stmt(ress, rhs)
		cfg_node = self.cfg.make_node(stmt)
		self.node_mapping[node] = cfg_node
		self.connect_incoming(cfg_node, cfg_pred_edges)
		return ((cfg_node, 0),)
Ejemplo n.º 5
0
	def emit_literal_node(self, node, cfg_pred_edges):
		ress = tuple(self.var_mapping.make_ssavar((node.region, node, o)) for o in node.output_names)
		literals = [stmts.literal_expr(v) for v in node.values]
		if len(literals) > 1:
			literals = stmts.tuple_expr(literals)
		else:
			literals = literals[0]
		let_stmt = stmts.let_stmt(ress, literals)
		cfg_node = self.cfg.make_node(let_stmt)
		self.node_mapping[node] = cfg_node
		self.connect_incoming(cfg_node, cfg_pred_edges)
		return ((cfg_node, 0),)
Ejemplo n.º 6
0
 def _make_pseudo_loop_graph(self):
     G = cfg_model.cfg()
     entry = G.make_node('let v := a(P)')
     a = G.make_node('branch v')
     b = G.make_node('let P := b(P)')
     c = G.make_node(stmts.let_stmt(('$x', ), stmts.parse_expr('0')))
     d = G.make_node(stmts.let_stmt(('$x', ), stmts.parse_expr('1')))
     e = G.make_node(
         stmts.let_stmt(('P', ),
                        stmts.call_expr('e', (stmts.var_expr('$x'), ))))
     f = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('0')))
     g = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('1')))
     exit = G.make_node(stmts.null_stmt())
     G.make_edge(entry, a)
     G.make_edge(a, b, 0)
     G.make_edge(a, c, 1)
     G.make_edge(a, d, 2)
     G.make_edge(b, f)
     G.make_edge(c, e)
     G.make_edge(d, e)
     G.make_edge(e, g)
     G.make_edge(f, exit)
     G.make_edge(g, exit)
     return G
Ejemplo n.º 7
0
        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
Ejemplo n.º 8
0
 def _pseudo_loop_ref_graph(self, pred, dummy_predicate=False):
     invpred = 1 - pred
     G = cfg_model.cfg()
     entry = G.make_node('let v := a(P)')
     a = G.make_node('branch v')
     b = G.make_node('let P := b(P)')
     if dummy_predicate:
         bp = G.make_node(
             stmts.let_stmt(('$p', '$x'),
                            stmts.parse_expr('%d,-1' % invpred)))
     else:
         bp = G.make_node(
             stmts.let_stmt(('$p', ), stmts.parse_expr('%d' % invpred)))
     c = G.make_node(
         stmts.let_stmt((
             '$p',
             '$x',
         ), stmts.parse_expr('%d, 0' % pred)))
     d = G.make_node(
         stmts.let_stmt((
             '$p',
             '$x',
         ), stmts.parse_expr('%d, 1' % pred)))
     rebranch = G.make_node(stmts.branch_stmt(stmts.var_expr('$p')))
     e = G.make_node(
         stmts.let_stmt(('P', ),
                        stmts.call_expr('e', (stmts.var_expr('$x'), ))))
     f = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('0')))
     g = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('1')))
     exit = G.make_node(stmts.null_stmt())
     G.make_edge(entry, a)
     G.make_edge(a, b, 0)
     G.make_edge(a, c, 1)
     G.make_edge(a, d, 2)
     G.make_edge(b, bp)
     G.make_edge(bp, rebranch)
     G.make_edge(c, rebranch)
     G.make_edge(d, rebranch)
     G.make_edge(rebranch, e, pred)
     G.make_edge(rebranch, f, invpred)
     G.make_edge(e, g)
     G.make_edge(f, exit)
     G.make_edge(g, exit)
     return G
Ejemplo n.º 9
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))
Ejemplo n.º 10
0
def acyclic_cfg_branch_xformed_partition(
        cfg, insert_dummy_predicate_assignments=False, mangle_cfg=False):
    #assert len(cfg.entries) == 1 and len(cfg.exits) == 1

    head_nodeset, branches, tail_nodeset = acyclic_cfg_branch_partition(
        cfg, mangle_cfg)

    if mangle_cfg:
        _splice_off_cfg(cfg, head_nodeset)

    global artificial_branch_letps
    global artificial_branchjoin_nulls
    global artificial_branches

    orig_tail_cont = list(
        set((edge[2] for branch in branches for edge in branch[2])))
    dont_rebranch = len(orig_tail_cont) <= 1

    # determine if any successor node uses a predicate defined immediately
    # before
    predicate_def = None
    for node in orig_tail_cont:
        predicate_def = _stmt_used_predicate(node.stmt)
        if predicate_def:
            break
        if _stmt_is_predicate_use(node.stmt):
            predicate_use_target = node
            break

    #assert all(node in tail_nodeset for node in orig_tail_cont)
    if mangle_cfg:
        tail, tail_cont = cfg, orig_tail_cont
    else:
        tail, tail_cont = cfg.subgraph(tail_nodeset, orig_tail_cont)
    if len(tail_cont) > 1:
        rebranch = tail.make_node(stmts.branch_stmt(stmts.var_expr('$p')))
        artificial_branches += 1
        for n in range(len(tail_cont)):
            tail.make_edge(rebranch, tail_cont[n], n)

    xformed_branches = []
    for ik, Nk, Ok in branches:
        if Nk:
            if mangle_cfg:
                sub_cfg = _splice_off_cfg(cfg, Nk)
                exits = [edge[0] for edge in Ok]
            else:
                sub_cfg, exits = cfg.subgraph(Nk, [edge[0] for edge in Ok])
            Xk = []
            exit_nodes = []
            for (old_edge, node) in zip(Ok, exits):
                edge_index = old_edge[1]
                tgt_index = orig_tail_cont.index(old_edge[2])
                if insert_dummy_predicate_assignments and predicate_def and not _stmt_is_predicate_assignment(
                        node.stmt):
                    let_node = sub_cfg.make_node(
                        stmts.let_stmt((predicate_def, ),
                                       stmts.parse_expr('-1')))
                    sub_cfg.make_edge(node, let_node, edge_index)
                    node = let_node
                    edge_index = 0
                if not dont_rebranch:
                    expr = stmts.parse_expr('%d' % tgt_index)
                    if _stmt_is_predicate_assignment(node.stmt):
                        let_node = sub_cfg.make_node(
                            stmts.let_stmt(('$p', ) + node.stmt.vars,
                                           stmts.tuple_expr(
                                               (expr, node.stmt.expr))))
                        artificial_branch_letps += 1
                        if node.incoming:
                            edge, = node.incoming
                            idx = edge.index
                            origin = edge.origin
                            edge.remove()
                            sub_cfg.make_edge(origin, let_node, idx)
                        node.remove()
                    else:
                        let_node = sub_cfg.make_node(
                            stmts.let_stmt(('$p', ), expr))
                        artificial_branch_letps += 1
                        sub_cfg.make_edge(node, let_node, edge_index)
                    node = let_node
                    edge_index = 0
                Xk.append((node, edge_index))

            if len(Xk) != 1:
                join_node = sub_cfg.make_node(stmts.null_stmt())
                artificial_branchjoin_nulls += 1
                for node, index in Xk:
                    sub_cfg.make_edge(node, join_node, index)
        else:
            tgt_index = orig_tail_cont.index(ik.target)
            sub_cfg = cfg_model.cfg()
            if dont_rebranch:
                if insert_dummy_predicate_assignments and predicate_def:
                    sub_cfg.make_node(
                        stmts.let_stmt((predicate_def, ),
                                       stmts.parse_expr('-1')))
                else:
                    sub_cfg.make_node(stmts.null_stmt())
            else:
                artificial_branch_letps += 1
                if insert_dummy_predicate_assignments and predicate_def:
                    sub_cfg.make_node(
                        stmts.let_stmt((
                            '$p',
                            predicate_def,
                        ), stmts.parse_expr('%d, -1' % tgt_index)))
                else:
                    sub_cfg.make_node(
                        stmts.let_stmt(('$p', ),
                                       stmts.parse_expr('%d' % tgt_index)))

        xformed_branches.append((ik.index, sub_cfg))

    nbranches = len(branches)
    if nbranches == 0:
        assert not tail.nodes
        assert not xformed_branches
    elif nbranches == 1:
        assert not tail.nodes
    else:
        assert tail.nodes

    head = cfg.subgraph(head_nodeset)[0]
    return head, xformed_branches, tail
Ejemplo n.º 11
0
def _convert_loop_cluster(cfg, cluster, vars):
    """Convert loop to single-entry/single-exit."""

    assert len(cfg.entries) == 1
    assert len(cfg.exits) == 1

    # Filter out predicates; that's a bit hackish, but whatever
    vars = tuple([v for v in vars if v[0] != '$'])

    loop_repeat_pred = '$repeat'
    loop_cross_pred = '$demux'

    entry_edges = set(
        itertools.chain(*((e for e in n.incoming if e.origin not in cluster)
                          for n in cluster)))
    exit_edges = set(
        itertools.chain(*((e for e in n.outgoing if e.target not in cluster)
                          for n in cluster)))

    exits = set(e.target for e in exit_edges)
    entries = set(e.target for e in entry_edges)
    for e in exit_edges:
        e.remove()
    for e in entry_edges:
        e.remove()

    entries_ordered = tuple(entries)
    entry_index_map = dict(zip(entries_ordered, range(len(entries_ordered))))

    exits_ordered = tuple(exits)
    exit_index_map = dict(zip(exits_ordered, range(len(exits_ordered))))

    # build inner graph

    global artificial_loop_entry_mux
    global artificial_loop_exit_mux
    global artificial_loop_repeat
    global artificial_loop_letqrs
    global artificial_loop_letqs
    global artificial_loop_letrs

    # create loop head, demux to real entry points
    loop_stmt = stmts.branch_stmt(stmts.var_expr(loop_cross_pred))
    loop_head = cfg.make_node(loop_stmt)
    if len(entries) > 1:
        artificial_loop_exit_mux += 1
    for node, index in entry_index_map.items():
        cfg.make_edge(loop_head, node, index)

    # create loop tail and set/clear loop repetition predicate
    loop_tail = cfg.make_node('null')
    # note: exit node accounted below

    exit_aux_lets = 0

    # divert exit edges to setting the crossing predicate and exiting from loop
    for e in exit_edges:
        origin, target, index = e.origin, e.target, e.index
        let_stmt = stmts.let_stmt(
            (loop_repeat_pred, loop_cross_pred),
            stmts.tuple_expr((stmts.literal_expr(0),
                              stmts.literal_expr(exit_index_map[target]))))
        s = cfg.make_node(let_stmt)
        exit_aux_lets += 1
        cfg.make_edge(origin, s, index)
        cfg.make_edge(s, loop_tail)

    repeat_aux_lets = 0

    nrepetition_edges = 0
    # divert repetition edges to setting the crossing predicate and repeating the loop
    for entry in entries:
        # do nothing if no outgoing edges remain
        if all(e.target not in cluster for e in entry.outgoing):
            continue
        for e in tuple(entry.incoming):
            if e.origin not in cluster: continue
            e.remove()
            nrepetition_edges += 1
            origin, target, index = e.origin, e.target, e.index
            let_stmt = stmts.let_stmt(
                (loop_repeat_pred, loop_cross_pred),
                stmts.tuple_expr(
                    (stmts.literal_expr(1),
                     stmts.literal_expr(entry_index_map[target]))))
            s = cfg.make_node(let_stmt)
            repeat_aux_lets += 1
            cfg.make_edge(origin, s, index)
            cfg.make_edge(s, loop_tail)
    if nrepetition_edges > 1 or len(entries) > 1 or len(exits) > 1:
        artificial_loop_repeat += 1
    if nrepetition_edges:
        if len(entries) > 1:
            artificial_loop_letqrs += repeat_aux_lets
        else:
            artificial_loop_letrs += repeat_aux_lets
        if len(exits) > 1:
            artificial_loop_letqrs += exit_aux_lets
        else:
            artificial_loop_letrs += exit_aux_lets
    else:
        if len(entries) > 1:
            artificial_loop_letqs += repeat_aux_lets
        if len(exits) > 1:
            artificial_loop_letqs += exit_aux_lets

    # inner graph now between loop_head and loop_tail, convert it
    # to rvsdg region, and build stmt

    inner_cfg = _splice_off_cfg(cfg, loop_head, loop_tail)

    argvars = vars + (loop_cross_pred, )
    resvars = argvars + (loop_repeat_pred, )
    resnames = argvars + ('$repeat', )
    assert len(inner_cfg.entries) == 1, len(inner_cfg.exits) == 1
    inner_rvsdg = _convert(inner_cfg, argvars, resvars, resnames)
    loop_expr = stmts.rvsdg_loop_expr(
        inner_rvsdg, 'loop',
        tuple(stmts.var_expr(v) for v in vars + (loop_cross_pred, )))
    loop_stmt = stmts.let_stmt(vars + (loop_cross_pred, ), loop_expr)

    # build outer graph
    loop_node = cfg.make_node(loop_stmt)
    exit_demux = cfg.make_node(
        stmts.branch_stmt(stmts.var_expr(loop_cross_pred)))
    if len(exits) > 1:
        artificial_loop_exit_mux += 1
    cfg.make_edge(loop_node, exit_demux)

    for e in entry_edges:
        origin, target, index = e.origin, e.target, e.index
        let_stmt = stmts.let_stmt((loop_cross_pred, ),
                                  stmts.literal_expr(entry_index_map[target]))
        s = cfg.make_node(let_stmt)
        if len(entries) > 1:
            artificial_loop_letqs += 1
        cfg.make_edge(origin, s, index)
        cfg.make_edge(s, loop_node)

    for node, index in exit_index_map.items():
        cfg.make_edge(exit_demux, node, index)
Ejemplo n.º 12
0
	def maybe_assign(self, origin, target, cfg_pred_edges):
		if origin == target:
			return cfg_pred_edges
		cfg_node = self.cfg.make_node(stmts.let_stmt((target,), stmts.var_expr(origin)))
		self.connect_incoming(cfg_node, cfg_pred_edges)
		return ((cfg_node, 0),)