%PDF- %PDF-
Direktori : /lib/python3/dist-packages/pythran/optimizations/ |
Current File : //lib/python3/dist-packages/pythran/optimizations/dead_code_elimination.py |
""" DeadCodeElimination remove useless code. """ from pythran.analyses import PureExpressions, DefUseChains, Ancestors from pythran.openmp import OMPDirective from pythran.passmanager import Transformation import pythran.metadata as metadata import gast as ast class ClumsyOpenMPDependencyHandler(ast.NodeVisitor): def __init__(self): self.blacklist = set() def visit_OMPDirective(self, node): for dep in node.deps: if isinstance(dep, ast.Name): self.blacklist.add(dep.id) return node class DeadCodeElimination(Transformation): """ Remove useless statement like: - assignment to unused variables - remove alone pure statement - remove empty if >>> import gast as ast >>> from pythran import passmanager, backend >>> pm = passmanager.PassManager("test") >>> node = ast.parse("def foo(): a = [2, 3]; return 1") >>> _, node = pm.apply(DeadCodeElimination, node) >>> print(pm.dump(backend.Python, node)) def foo(): pass return 1 >>> node = ast.parse("def foo(): 'a simple string'; return 1") >>> _, node = pm.apply(DeadCodeElimination, node) >>> print(pm.dump(backend.Python, node)) def foo(): pass return 1 >>> node = ast.parse(''' ... def bar(a): ... return a ... def foo(a): ... bar(a) ... return 1''') >>> _, node = pm.apply(DeadCodeElimination, node) >>> print(pm.dump(backend.Python, node)) def bar(a): return a def foo(a): pass return 1 """ def __init__(self): super(DeadCodeElimination, self).__init__(PureExpressions, DefUseChains, Ancestors) self.blacklist = set() def used_target(self, node): if isinstance(node, ast.Name): if node.id in self.blacklist: return True chain = self.def_use_chains.chains[node] return bool(chain.users()) return True def visit_FunctionDef(self, node): codh = ClumsyOpenMPDependencyHandler() codh.visit(node) self.blacklist = codh.blacklist return self.generic_visit(node) def visit_Pass(self, node): ancestor = self.ancestors[node][-1] if getattr(ancestor, 'body', ()) == [node]: return node if getattr(ancestor, 'orelse', ()) == [node]: return node if metadata.get(node, OMPDirective): return node return None def visit_Assign(self, node): targets = [target for target in node.targets if self.used_target(target)] if len(targets) == len(node.targets): return node node.targets = targets self.update = True if targets: return node if node.value in self.pure_expressions: return ast.Pass() else: return ast.Expr(value=node.value) def visit_Expr(self, node): if (node in self.pure_expressions and not isinstance(node.value, ast.Yield)): self.update = True return ast.Pass() self.generic_visit(node) return node def visit_If(self, node): self.generic_visit(node) try: if ast.literal_eval(node.test): if not metadata.get(node, OMPDirective): self.update = True return node.body else: if not metadata.get(node, OMPDirective): self.update = True return node.orelse except ValueError: # not a constant expression pass have_body = any(not isinstance(x, ast.Pass) for x in node.body) have_else = any(not isinstance(x, ast.Pass) for x in node.orelse) # If the "body" is empty but "else content" is useful, switch branches # and remove else content if not have_body and have_else: test = ast.UnaryOp(op=ast.Not(), operand=node.test) self.update = True return ast.If(test=test, body=node.orelse, orelse=list()) # if neither "if" and "else" are useful, keep test if it is not pure elif not have_body: self.update = True if node.test in self.pure_expressions: return ast.Pass() else: node = ast.Expr(value=node.test) self.generic_visit(node) return node def visit(self, node): """ Add OMPDirective from the old node to the new one. """ old_omp = metadata.get(node, OMPDirective) node = super(DeadCodeElimination, self).visit(node) if not metadata.get(node, OMPDirective): for omp_directive in old_omp: metadata.add(node, omp_directive) return node