def save_graph_summ (self, fname): node_ids = {} def is_triv (n): if n not in self.nodes: return False node = self.nodes[n] if node.kind == 'Basic': return (True, node.cont) elif node.kind == 'Cond' and node.right == 'Err': return (True, node.left) else: return False for n in self.nodes: if n in node_ids: continue ns = [] while is_triv (n): ns.append (n) n = is_triv (n)[1] for n2 in ns: node_ids[n2] = n nodes = {} for n in self.nodes: if is_triv (n): continue nodes[n] = syntax.copy_rename (self.nodes[n], ({}, node_ids)) cols = mk_graph_cols (self.node_tags) save_graph (nodes, fname, cols = cols, node_tags = self.node_tags)
def save_graph_summ(self, fname): node_ids = {} def is_triv(n): if n not in self.nodes: return False if len(self.preds[n]) != 1: return False node = self.nodes[n] if node.kind == 'Basic': return (True, node.cont) elif node.kind == 'Cond' and node.right == 'Err': return (True, node.left) else: return False for n in self.nodes: if n in node_ids: continue ns = [] while is_triv(n): ns.append(n) n = is_triv(n)[1] for n2 in ns: node_ids[n2] = n nodes = {} for n in self.nodes: if is_triv(n): continue nodes[n] = syntax.copy_rename(self.nodes[n], ({}, node_ids)) cols = mk_graph_cols(self.node_tags) save_graph(nodes, fname, cols=cols, node_tags=self.node_tags)
def rename_vars (function): preds = logic.compute_preds (function.nodes) var_deps = logic.compute_var_deps (function.nodes, lambda x: function.outputs, preds) vs = set () dont_rename_vs = set () for n in var_deps: rev_renames = {} for (v, t) in var_deps[n]: v2 = recommended_rename (v) rev_renames.setdefault (v2, []) rev_renames[v2].append ((v, t)) vs.add ((v, t)) for (v2, vlist) in rev_renames.iteritems (): if len (vlist) > 1: dont_rename_vs.update (vlist) renames = dict ([(v, recommended_rename (v)) for (v, t) in vs if (v, t) not in dont_rename_vs]) f = function f.inputs = [(renames.get (v, v), t) for (v, t) in f.inputs] f.outputs = [(renames.get (v, v), t) for (v, t) in f.outputs] for n in f.nodes: f.nodes[n] = syntax.copy_rename (f.nodes[n], (renames, {}))
def rename_vars(function): preds = logic.compute_preds(function.nodes) var_deps = logic.compute_var_deps(function.nodes, lambda x: function.outputs, preds) vs = set() dont_rename_vs = set() for n in var_deps: rev_renames = {} for (v, t) in var_deps[n]: v2 = recommended_rename(v) rev_renames.setdefault(v2, []) rev_renames[v2].append((v, t)) vs.add((v, t)) for (v2, vlist) in rev_renames.iteritems(): if len(vlist) > 1: dont_rename_vs.update(vlist) renames = dict([(v, recommended_rename(v)) for (v, t) in vs if (v, t) not in dont_rename_vs]) f = function f.inputs = [(renames.get(v, v), t) for (v, t) in f.inputs] f.outputs = [(renames.get(v, v), t) for (v, t) in f.outputs] for n in f.nodes: f.nodes[n] = syntax.copy_rename(f.nodes[n], (renames, {}))
def force_single_loop_return(self, head, loop_set): rets = [n for n in self.preds[head] if n in loop_set] if len(rets) == 1 and rets[0] != head and self.nodes[rets[0]].is_noop(): return None r = self.alloc_node(self.node_tags[head][0], "LoopReturn", loop_id=head) self.nodes[r] = Node("Basic", head, []) for r2 in rets: self.nodes[r2] = syntax.copy_rename(self.nodes[r2], ({}, {head: r})) return r
def force_single_loop_return(self, head, loop_set): rets = [n for n in self.preds[head] if n in loop_set] if (len(rets) == 1 and rets[0] != head and self.nodes[rets[0]].is_noop()): return None r = self.alloc_node(self.node_tags[head][0], 'LoopReturn', loop_id=head) self.nodes[r] = Node('Basic', head, []) for r2 in rets: self.nodes[r2] = syntax.copy_rename(self.nodes[r2], ({}, { head: r })) return r
def pad_merge_points(self): self.compute_preds() arcs = [(pred, n) for n in self.preds if len(self.preds[n]) > 1 if n in self.nodes for pred in self.preds[n] if (self.nodes[pred].kind != 'Basic' or self.nodes[pred].upds != [])] for (pred, n) in arcs: (tag, _) = self.node_tags[pred] name = self.alloc_node(tag, 'MergePadding') self.nodes[name] = Node('Basic', n, []) self.nodes[pred] = syntax.copy_rename(self.nodes[pred], ({}, { n: name }))
def pad_merge_points (self): self.compute_preds () arcs = [(pred, n) for n in self.preds if len (self.preds[n]) > 1 if n in self.nodes for pred in self.preds[n] if (self.nodes[pred].kind != 'Basic' or self.nodes[pred].upds != [])] for (pred, n) in arcs: (tag, _) = self.node_tags[pred] name = self.alloc_node (tag, 'MergePadding') self.nodes[name] = Node ('Basic', n, []) self.nodes[pred] = syntax.copy_rename (self.nodes[pred], ({}, {n: name}))
def add_function(self, fun, tag, node_renames, loop_id=None): if not fun.entry: printout("Aborting %s: underspecified %s" % (self.name, fun.name)) raise Abort() node_renames.setdefault("Ret", "Ret") node_renames.setdefault("Err", "Err") new_node_renames = {} vs = syntax.get_vars(fun) vs = dict([(v, fresh_name(v, self.vs, vs[v])) for v in vs]) ns = fun.reachable_nodes() for n in ns: assert n not in node_renames node_renames[n] = self.alloc_node(tag, (fun.name, n), loop_id=loop_id, hint=n) new_node_renames[n] = node_renames[n] for n in ns: self.nodes[node_renames[n]] = syntax.copy_rename(fun.nodes[n], (vs, node_renames)) return (new_node_renames, vs)
def add_function(self, fun, tag, node_renames, loop_id=None): if not fun.entry: printout('Aborting %s: underspecified %s' % (self.name, fun.name)) raise Abort() node_renames.setdefault('Ret', 'Ret') node_renames.setdefault('Err', 'Err') new_node_renames = {} vs = syntax.get_vars(fun) vs = dict([(v, fresh_name(v, self.vs, vs[v])) for v in vs]) ns = fun.reachable_nodes() check_no_symbols([fun.nodes[n] for n in ns]) for n in ns: assert n not in node_renames node_renames[n] = self.alloc_node(tag, (fun.name, n), loop_id=loop_id, hint=n) new_node_renames[n] = node_renames[n] for n in ns: self.nodes[node_renames[n]] = syntax.copy_rename( fun.nodes[n], (vs, node_renames)) return (new_node_renames, vs)
def contextual_cond_simps (nodes, preds): """a common pattern in architectures with conditional operations is a sequence of instructions with the same condition. we can usually then reduce to a single contional block. b e => b-e / \ / \ => / \ a-c-d-f-g => a-c-f-g this is sometimes important if b calculates a register that e uses since variable dependency analysis will see this register escape via the impossible path a-c-d-e """ (arc_conds, pre_conds) = contextual_conds (nodes, preds) nodes = dict (nodes) for n in nodes: if nodes[n].kind == 'Cond': continue cont = nodes[n].cont conds = arc_conds[(n, cont)] cont2 = cont_with_conds (nodes, cont, conds) if cont2 != cont: nodes[n] = syntax.copy_rename (nodes[n], ({}, {cont: cont2})) return nodes