def test_expr_parse(self): e = stmts.parse_expr('a') self.assertEquals(stmts.var_expr('a'), e) e = stmts.parse_expr('1') self.assertEquals(stmts.literal_expr(1), e) e = stmts.parse_expr('f(x)') self.assertEquals(stmts.call_expr('f', (stmts.var_expr('x'), )), e) e = stmts.parse_expr('a, f(x)') self.assertEquals( stmts.tuple_expr((stmts.var_expr('a'), stmts.parse_expr('f(x)'))), e)
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
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),)
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
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
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
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
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)
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),)
def emit_branchnode(self, node, predicate, cfg_pred_edges): stmt = stmts.branch_stmt(stmts.var_expr(predicate)) cfg_node = self.cfg.make_node(stmt) self.node_mapping[node] = cfg_node self.connect_incoming(cfg_node, cfg_pred_edges) return cfg_node