Example #1
0
    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
Example #2
0
    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
Example #4
0
 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)
Example #5
0
    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
Example #6
0
 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)
Example #7
0
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
Example #8
0
 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)
Example #9
0
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