def visit_For(self, node): # if the user added some OpenMP directive, trust him and no unroll if metadata.get(node, OMPDirective): return node # don't visit children because of collapse # first unroll children if needed or possible self.generic_visit(node) # a break or continue in the loop prevents unrolling too has_break = any(self.gather(HasBreak, n) for n in node.body) has_cont = any(self.gather(HasContinue, n) for n in node.body) if has_break or has_cont: return node # do not unroll too much to prevent code growth node_count = self.gather(NodeCount, node) def unroll(elt, body): return [ast.Assign([deepcopy(node.target)], elt)] + body def dc(body, i, n): if i == n - 1: return body else: return deepcopy(body) def getrange(n): return getattr(getattr(n, 'func', None), 'attr', None) if isinstance(node.iter, (ast.Tuple, ast.List)): elts_count = len(node.iter.elts) total_count = node_count * elts_count issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: self.update = True return sum([unroll(elt, dc(node.body, i, elts_count)) for i, elt in enumerate(node.iter.elts)], []) code = compile(ast.gast_to_ast(ast.Expression(node.iter)), '<loop unrolling>', 'eval') try: values = list(eval(code, {'builtins': __import__('builtins')})) except Exception: return node values_count = len(values) total_count = node_count * values_count issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: try: new_node = sum([unroll(to_ast(elt), dc(node.body, i, values_count)) for i, elt in enumerate(values)], []) self.update = True return new_node except Exception: return node return node
def generic_visit(self, node): if isinstance(node, ast.expr) and node in self.constant_expressions: fake_node = ast.Expression(node) code = compile(ast.gast_to_ast(fake_node), '<constant folding>', 'eval') try: value = eval(code, self.env) new_node = to_ast(value) if not ASTMatcher(node).match(new_node): self.update = True return new_node except DamnTooLongPattern as e: print("W: ", e, " Assume no update happened.") except ConversionError as e: print('error in constant folding: ', e) raise except ToNotEval: pass except AttributeError as e: # this may miss a few optimization logger.info('During constant folding, bailing out due to: ' + e.args[0]) except NameError as e: # FIXME dispatched function are not processed by constant # folding if "__dispatch__" in e.args[0]: return Transformation.generic_visit(self, node) # this may miss a few optimization logger.info('During constant folding, bailing out due to: ' + e.args[0]) except Exception as e: raise PythranSyntaxError(str(e), node) return Transformation.generic_visit(self, node)
def visit_For(self, node): # if the user added some OpenMP directive, trust him and no unroll if metadata.get(node, OMPDirective): return node # don't visit children because of collapse # first unroll children if needed or possible self.generic_visit(node) # a break or continue in the loop prevents unrolling too has_break = any(self.gather(HasBreak, n) for n in node.body) has_cont = any(self.gather(HasContinue, n) for n in node.body) if has_break or has_cont: return node # do not unroll too much to prevent code growth node_count = self.gather(NodeCount, node) def unroll(elt): return ([ast.Assign([deepcopy(node.target)], elt)] + deepcopy(node.body)) def getrange(n): return getattr(getattr(n, 'func', None), 'attr', None) if isinstance(node.iter, (ast.Tuple, ast.List)): total_count = node_count * len(node.iter.elts) issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: self.update = True return sum([unroll(elt) for elt in node.iter.elts], []) code = compile(ast.gast_to_ast(ast.Expression(node.iter)), '<loop unrolling>', 'eval') try: values = list(eval(code, {'__builtin__': __import__('__builtin__')})) except Exception: return node total_count = node_count * len(values) issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: try: new_node = sum([unroll(to_ast(elt)) for elt in values], []) self.update = True return new_node except Exception: return node return node
def __init__(self, **kwargs): self.argument_effects = kwargs.get('argument_effects', (UpdateEffect(), ) * 11) self.global_effects = kwargs.get('global_effects', False) self.return_alias = kwargs.get('return_alias', lambda x: {UnboundValue}) self.args = ast.arguments( [ast.Name(n, ast.Param(), None) for n in kwargs.get('args', [])], None, [], [], None, [to_ast(d) for d in kwargs.get('defaults', [])]) self.return_range = kwargs.get("return_range", lambda call: UNKNOWN_RANGE) self.return_range_content = kwargs.get("return_range_content", lambda c: UNKNOWN_RANGE)
def visit_For(self, node): # first unroll children if needed or possible self.generic_visit(node) # if the user added some OpenMP directive, trust him and no unroll has_omp = metadata.get(node, OMPDirective) # a break or continue in the loop prevents unrolling too has_break = any( self.passmanager.gather(HasBreak, n, self.ctx) for n in node.body) has_cont = any( self.passmanager.gather(HasContinue, n, self.ctx) for n in node.body) if has_omp or has_break or has_cont: return node # do not unroll too much to prevent code growth node_count = self.passmanager.gather(NodeCount, node, self.ctx) def unroll(elt): return ([ast.Assign([deepcopy(node.target)], elt)] + deepcopy(node.body)) def getrange(n): return getattr(getattr(n, 'func', None), 'attr', None) if isinstance(node.iter, (ast.Tuple, ast.List)): total_count = node_count * len(node.iter.elts) issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: self.update = True return sum([unroll(elt) for elt in node.iter.elts], []) code = compile(ast.gast_to_ast(ast.Expression(node.iter)), '<loop unrolling>', 'eval') try: values = list( eval(code, {'__builtin__': __import__('__builtin__')})) except Exception as e: return node total_count = node_count * len(values) issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT if issmall: try: new_node = sum([unroll(to_ast(elt)) for elt in values], []) self.update = True return new_node except Exception as e: return node return node
def __init__(self, **kwargs): self.argument_effects = kwargs.get('argument_effects', (UpdateEffect(),) * 11) self.global_effects = kwargs.get('global_effects', False) self.return_alias = kwargs.get('return_alias', lambda x: {UnboundValue}) self.args = ast.arguments( [ast.Name(n, ast.Param(), None) for n in kwargs.get('args', [])], None, [], [], None, [to_ast(d) for d in kwargs.get('defaults', [])]) self.return_range = kwargs.get("return_range", lambda call: UNKNOWN_RANGE) self.return_range_content = kwargs.get("return_range_content", lambda c: UNKNOWN_RANGE)
def save_arguments(module_name, elements): """ Recursively save arguments name and default value. """ for elem, signature in elements.items(): if isinstance(signature, dict): # Submodule case save_arguments(module_name + (elem,), signature) else: # use introspection to get the Python obj try: themodule = __import__(".".join(module_name)) obj = getattr(themodule, elem) spec = inspect.getargspec(obj) assert not signature.args.args signature.args.args = [ast.Name(arg, ast.Param(), None) for arg in spec.args] if spec.defaults: signature.args.defaults = [to_ast(default) for default in spec.defaults] except (AttributeError, ImportError, TypeError, ToNotEval): pass
def generic_visit(self, node): if node in self.constant_expressions: try: fake_node = ast.Expression( node.value if isinstance(node, ast.Index) else node) code = compile(ast.gast_to_ast(fake_node), '<constant folding>', 'eval') value = eval(code, self.env) new_node = to_ast(value) if(isinstance(node, ast.Index) and not isinstance(new_node, ast.Index)): new_node = ast.Index(new_node) try: if not ASTMatcher(node).search(new_node): self.update = True return new_node except DamnTooLongPattern as e: print("W: ", e, " Assume no update happened.") return Transformation.generic_visit(self, node) except ConversionError as e: print('error in constant folding: ', e) raise except ToNotEval: return Transformation.generic_visit(self, node) except AttributeError as e: # FIXME union_ function is not handle by constant folding if "union_" in e.args[0]: return Transformation.generic_visit(self, node) elif "pythran" in e.args[0]: # FIXME: Can be fix giving a Python implementation for # these functions. return Transformation.generic_visit(self, node) raise except NameError as e: # FIXME dispatched function are not processed by constant # folding if "__dispatch__" in e.args[0]: return Transformation.generic_visit(self, node) raise except Exception as e: raise PythranSyntaxError(str(e), node) else: return Transformation.generic_visit(self, node)
def save_arguments(module_name, elements): """ Recursively save arguments name and default value. """ for elem, signature in elements.items(): if isinstance(signature, dict): # Submodule case save_arguments(module_name + (elem, ), signature) else: # use introspection to get the Python obj try: themodule = __import__(".".join(module_name)) obj = getattr(themodule, elem) spec = inspect.getargspec(obj) assert not signature.args.args signature.args.args = [ ast.Name(arg, ast.Param(), None) for arg in spec.args ] if spec.defaults: signature.args.defaults = [ to_ast(default) for default in spec.defaults ] except (AttributeError, ImportError, TypeError, ToNotEval): pass