예제 #1
0
    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_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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
파일: backend.py 프로젝트: jfinkels/pythran
    def can_use_c_for(self, node):
        """
        Check if a for loop can use classic C syntax.

        To use C syntax:
            - target should not be assign in the loop
            - xrange should be use as iterator
            - order have to be known at compile time or OpenMP should not be
              use

        """
        assert isinstance(node.target, ast.Name)
        pattern = ast.Call(func=ast.Attribute(value=ast.Name(id='__builtin__',
                                                             ctx=ast.Load()),
                                              attr='xrange', ctx=ast.Load()),
                           args=AST_any(), keywords=[], starargs=None,
                           kwargs=None)
        is_assigned = {node.target.id: False}
        [is_assigned.update(self.passmanager.gather(IsAssigned, stmt))
         for stmt in node.body]

        if (node.iter not in ASTMatcher(pattern).search(node.iter) or
                is_assigned[node.target.id]):
            return False

        args = node.iter.args
        if (len(args) > 2 and (not isinstance(args[2], ast.Num) and
                               not (isinstance(args[1], ast.Num) and
                                    isinstance(args[0], ast.Num))) and
                metadata.get(node, OMPDirective)):
            return False
        return True
예제 #6
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)
        # do not unroll too much to prevent code growth
        node_count = self.passmanager.gather(NodeCount, node, self.ctx)

        if type(node.iter) is ast.List:
            isvalid = not(has_omp or has_break or has_cont)
            total_count = node_count * len(node.iter.elts)
            issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT
            if isvalid and issmall:
                def unroll(elt):
                    return ([ast.Assign([deepcopy(node.target)], elt)] +
                            deepcopy(node.body))
                self.update = True
                return reduce(list.__add__, map(unroll, node.iter.elts))
        return node
예제 #7
0
파일: openmp.py 프로젝트: xmar/pythran
    def attach_data(self, node):
        '''Generic method called for visit_XXXX() with XXXX in
        GatherOMPData.statements list

        '''
        if self.current:
            for curr in self.current:
                md = OMPDirective(curr)
                metadata.add(node, md)
            self.current = list()
        # add a Pass to hold some directives
        for field_name, field in ast.iter_fields(node):
            if field_name in GatherOMPData.statement_lists:
                if(field and
                   isinstance(field[-1], ast.Expr) and
                   self.isompdirective(field[-1].value)):
                    field.append(ast.Pass())
        self.generic_visit(node)

        # add an If to hold scoping OpenMP directives
        directives = metadata.get(node, OMPDirective)
        field_names = {n for n, _ in ast.iter_fields(node)}
        has_no_scope = field_names.isdisjoint(GatherOMPData.statement_lists)
        if directives and has_no_scope:
            # some directives create a scope, but the holding stmt may not
            # artificially create one here if needed
            sdirective = ''.join(d.s for d in directives)
            scoping = ('parallel', 'task', 'section')
            if any(s in sdirective for s in scoping):
                node = ast.If(ast.Num(1), [node], [])
        return node
예제 #8
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
예제 #9
0
    def visit_FunctionDef(self, node):
        if metadata.get(node, metadata.Local):
            if not self.def_use_chains.chains[node].users():
                self.update = True
                return None

        return node
예제 #10
0
    def attach_data(self, node):
        '''Generic method called for visit_XXXX() with XXXX in
        GatherOMPData.statements list

        '''
        if self.current:
            for curr in self.current:
                md = OMPDirective(curr)
                metadata.add(node, md)
            self.current = list()
        # add a Pass to hold some directives
        for field_name, field in ast.iter_fields(node):
            if field_name in GatherOMPData.statement_lists:
                if(field and
                   isinstance(field[-1], ast.Expr) and
                   self.isompdirective(field[-1].value)):
                    field.append(ast.Pass())
        self.generic_visit(node)

        # add an If to hold scoping OpenMP directives
        directives = metadata.get(node, OMPDirective)
        field_names = {n for n, _ in ast.iter_fields(node)}
        has_no_scope = field_names.isdisjoint(GatherOMPData.statement_lists)
        if directives and has_no_scope:
            # some directives create a scope, but the holding stmt may not
            # artificially create one here if needed
            sdirective = ''.join(d.s for d in directives)
            scoping = ('parallel', 'task', 'section')
            if any(s in sdirective for s in scoping):
                metadata.clear(node, OMPDirective)
                node = ast.If(ast.Num(1), [node], [])
                for directive in directives:
                    metadata.add(node, directive)

        return node
예제 #11
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)
        # do not unroll too much to prevent code growth
        node_count = self.passmanager.gather(NodeCount, node, self.ctx)

        if type(node.iter) is ast.List:
            isvalid = not (has_omp or has_break or has_cont)
            total_count = node_count * len(node.iter.elts)
            issmall = total_count < LoopFullUnrolling.MAX_NODE_COUNT
            if isvalid and issmall:

                def unroll(elt):
                    return ([ast.Assign([deepcopy(node.target)], elt)] +
                            deepcopy(node.body))

                return reduce(list.__add__, map(unroll, node.iter.elts))
        return node
예제 #12
0
파일: backend.py 프로젝트: jfinkels/pythran
    def handle_omp_for(self, node, local_iter):
        """
        Fix OpenMP directives on For loops.

        Add the target as private variable as a new variable may have been
        introduce to handle cxx iterator.

        Also, add the iterator as shared variable as all 'parallel for chunck'
        have to use the same iterator.
        """
        for directive in metadata.get(node, OMPDirective):
            if any(key in directive.s for key in (' parallel ', ' task ')):
                # Eventually add local_iter in a shared clause as iterable is
                # shared in the for loop (for every clause with datasharing)
                directive.s += ' shared({})'
                directive.deps.append(ast.Name(local_iter, ast.Load()))

            target = node.target
            assert isinstance(target, ast.Name)
            hasfor = 'for' in directive.s
            nodefault = 'default' not in directive.s
            noindexref = all(isinstance(x, ast.Name) and
                             x.id != target.id for x in directive.deps)
            if (hasfor and nodefault and noindexref and
                    target.id not in self.scope[node]):
                # Target is private by default in omp but iterator use may
                # introduce an extra variable
                directive.s += ' private({})'
                directive.deps.append(ast.Name(target.id, ast.Load()))
예제 #13
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def handle_omp_for(self, node, local_iter):
        """
        Fix OpenMP directives on For loops.

        Add the target as private variable as a new variable may have been
        introduce to handle cxx iterator.

        Also, add the iterator as shared variable as all 'parallel for chunck'
        have to use the same iterator.
        """
        for directive in metadata.get(node, OMPDirective):
            if any(key in directive.s for key in (' parallel ', ' task ')):
                # Eventually add local_iter in a shared clause as iterable is
                # shared in the for loop (for every clause with datasharing)
                directive.s += ' shared({})'
                directive.deps.append(ast.Name(local_iter, ast.Load(), None))

            target = node.target
            assert isinstance(target, ast.Name)
            hasfor = 'for' in directive.s
            nodefault = 'default' not in directive.s
            noindexref = all(
                isinstance(x, ast.Name) and x.id != target.id
                for x in directive.deps)
            if (hasfor and nodefault and noindexref
                    and target.id not in self.scope[node]):
                # Target is private by default in omp but iterator use may
                # introduce an extra variable
                directive.s += ' private({})'
                directive.deps.append(ast.Name(target.id, ast.Load(), None))
예제 #14
0
    def can_use_c_for(self, node):
        """
        Check if a for loop can use classic C syntax.

        To use C syntax:
            - target should not be assign in the loop
            - xrange should be use as iterator
            - order have to be known at compile time or OpenMP should not be
              use

        """
        assert isinstance(node.target, ast.Name)
        pattern = ast.Call(func=ast.Attribute(value=ast.Name(id='__builtin__',
                                                             ctx=ast.Load()),
                                              attr='xrange', ctx=ast.Load()),
                           args=AST_any(), keywords=[], starargs=None,
                           kwargs=None)
        is_assigned = {node.target.id: False}
        [is_assigned.update(self.passmanager.gather(IsAssigned, stmt))
         for stmt in node.body]

        if (node.iter not in ASTMatcher(pattern).search(node.iter) or
                is_assigned[node.target.id]):
            return False

        args = node.iter.args
        if (len(args) > 2 and (not isinstance(args[2], ast.Num) and
                               not (isinstance(args[1], ast.Num) and
                                    isinstance(args[0], ast.Num))) and
                metadata.get(node, OMPDirective)):
            return False
        return True
예제 #15
0
def is_global_constant(node):
    if isinstance(node, ConstantIntr):
        return True

    if not isinstance(node, ast.FunctionDef):
        return False

    return metadata.get(node.body[0], metadata.StaticReturn)
예제 #16
0
 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
예제 #17
0
 def visit(self, node):
     old_omp = self.in_omp
     omp_nodes = md.get(node, openmp.OMPDirective)
     if omp_nodes:
         self.in_omp = set(self.name_count.keys())
     super(LazynessAnalysis, self).visit(node)
     if omp_nodes:
         new_nodes = set(self.name_count).difference(self.in_omp)
         self.dead.update(new_nodes)
     self.in_omp = old_omp
예제 #18
0
 def visit(self, node):
     old_omp = self.in_omp
     omp_nodes = md.get(node, openmp.OMPDirective)
     if omp_nodes:
         self.in_omp = set(self.name_count.keys())
     super(LazynessAnalysis, self).visit(node)
     if omp_nodes:
         new_nodes = set(self.name_count).difference(self.in_omp)
         self.dead.update(new_nodes)
     self.in_omp = old_omp
예제 #19
0
 def is_in_collapse(self, loop, node):
     for ancestor in reversed(self.ancestors[loop]):
         if not isinstance(ancestor, ast.For):
             return False
         for directive in metadata.get(ancestor, OMPDirective):
             if 'collapse' in directive.s:
                 # FIXME: check loop depth and range canonicalization
                 if node not in self.pure_expressions:
                     raise PythranSyntaxError(
                         "not pure expression used as loop target inside a "
                         "collapse clause", loop)
                 return True
     assert False, "unreachable state"
    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
예제 #21
0
 def visit(self, node):
     old_omp = self.in_omp
     omp_nodes = md.get(node, openmp.OMPDirective)
     if omp_nodes:
         self.in_omp = set(self.name_count.keys())
     super(LazynessAnalysis, self).visit(node)
     if omp_nodes:
         new_nodes = set(self.name_count).difference(self.in_omp)
         for omp_node in omp_nodes:
             for n in omp_node.deps:
                 if isinstance(n, ast.Name):
                     self.result[n.id] = LazynessAnalysis.INF
         self.dead.update(new_nodes)
     self.in_omp = old_omp
예제 #22
0
파일: backend.py 프로젝트: sthagen/pythran
 def visit_Return(self, node):
     value = self.visit(node.value)
     if metadata.get(node, metadata.StaticReturn):
         # don't rely on auto because we want to make sure there's no
         # conversion each time we return
         # this happens for variant because the variant param
         # order may differ from the init order (because of the way we
         # do type inference
         rtype = "typename {}::type::result_type".format(self.fname)
         stmt = Block([Assign("static %s tmp_global" % rtype, value),
                       ReturnStatement("tmp_global")])
     else:
         stmt = ReturnStatement(value)
     return self.process_omp_attachements(node, stmt)
예제 #23
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
예제 #24
0
 def visit(self, node):
     old_omp = self.in_omp
     omp_nodes = md.get(node, openmp.OMPDirective)
     if omp_nodes:
         self.in_omp = set(self.name_count.keys())
     super(LazynessAnalysis, self).visit(node)
     if omp_nodes:
         new_nodes = set(self.name_count).difference(self.in_omp)
         for omp_node in omp_nodes:
             for n in omp_node.deps:
                 if isinstance(n, ast.Name):
                     self.result[n.id] = LazynessAnalysis.INF
         self.dead.update(new_nodes)
     self.in_omp = old_omp
예제 #25
0
 def visit_Return(self, node):
     value = self.visit(node.value)
     if metadata.get(node, metadata.StaticReturn):
         # don't rely on auto because we want to make sure there's no
         # conversion each time we return
         # this happens for variant because the variant param
         # order may differ from the init order (because of the way we
         # do type inference
         rtype = "typename {}::type::result_type".format(self.fname)
         stmt = Block([Assign("static %s tmp_global" % rtype, value),
                       ReturnStatement("tmp_global")])
     else:
         stmt = ReturnStatement(value)
     return self.process_omp_attachements(node, stmt)
예제 #26
0
파일: backend.py 프로젝트: LuisBL/pythran
 def visit_Return(self, node):
     if self.yields:
         return Block(
             [
                 Statement("{0} = -1".format(Cxx.generator_state_holder)),
                 Statement("goto {0}".format(Cxx.final_statement)),
             ]
         )
     else:
         value = self.visit(node.value)
         if metadata.get(node, metadata.StaticReturn):
             stmt = Block([Assign("static auto tmp_global", value), ReturnStatement("tmp_global")])
         else:
             stmt = ReturnStatement(value)
         return self.process_omp_attachements(node, stmt)
예제 #27
0
    def check_global(self, node, arg):
        if not isinstance(arg, ast.Call):
            return
        try:
            aliases = self.strict_aliases[arg.func]
        except KeyError:
            return

        for alias in aliases:
            if not isinstance(alias, ast.FunctionDef):
                continue
            if metadata.get(alias.body[0], metadata.StaticReturn):
                raise PythranSyntaxError(
                    ("Cannot modify '{}': global variables are constant "
                     "in pythran.").format(alias.name), node)
예제 #28
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def can_use_autofor(self, node):
        """
        Check if given for Node can use autoFor syntax.

        To use auto_for:
            - iterator should have local scope
            - yield should not be use
            - OpenMP pragma should not be use

        TODO : Yield should block only if it is use in the for loop, not in the
               whole function.
        """
        auto_for = (isinstance(node.target, ast.Name)
                    and node.target.id in self.scope[node])
        auto_for &= not metadata.get(node, OMPDirective)
        return auto_for
예제 #29
0
파일: backend.py 프로젝트: LuisBL/pythran
    def can_use_autofor(self, node):
        """
        Check if given for Node can use autoFor syntax.

        To use auto_for:
            - iterator should have local scope
            - yield should not be use
            - OpenMP pragma should not be use

        TODO : Yield should block only if it is use in the for loop, not in the
               whole function.
        """
        auto_for = isinstance(node.target, ast.Name) and node.target.id in self.scope[node]
        auto_for &= not self.yields
        auto_for &= not metadata.get(node, OMPDirective)
        return auto_for
예제 #30
0
 def visit_Return(self, node):
     if self.yields:
         return Block([
             Statement("{0} = -1".format(Cxx.generator_state_holder)),
             Statement("goto {0}".format(Cxx.final_statement))
         ])
     else:
         value = self.visit(node.value)
         if metadata.get(node, metadata.StaticReturn):
             stmt = Block([
                 Assign("static auto tmp_global", value),
                 ReturnStatement("tmp_global")
             ])
         else:
             stmt = ReturnStatement(value)
         return self.process_omp_attachements(node, stmt)
예제 #31
0
파일: inlinable.py 프로젝트: songkq/pythran
    def visit_FunctionDef(self, node):
        """ Determine this function definition can be inlined. """
        if len(node.body) != 1:
            return

        sbody = node.body[0]
        if not isinstance(sbody, (ast.Call, ast.Return)):
            return

        # only consider static return if they are pure
        if metadata.get(sbody, metadata.StaticReturn):
            if sbody not in self.pure_expressions:
                return

        ids = self.gather(Identifiers, sbody)
        # FIXME : It mark "not inlinable" def foo(foo): return foo
        if node.name not in ids:
            self.result[node.name] = copy.deepcopy(node)
예제 #32
0
파일: backend.py 프로젝트: jfinkels/pythran
    def process_omp_attachements(self, node, stmt, index=None):
        """
        Add OpenMP pragma on the correct stmt in the correct order.

        stmt may be a list. On this case, index have to be specify to add
        OpenMP on the correct statement.
        """
        omp_directives = metadata.get(node, OMPDirective)
        if omp_directives:
            directives = list()
            for directive in reversed(omp_directives):
                directive.deps = map(self.visit, directive.deps)
                directives.append(directive)
            if index is None:
                stmt = AnnotatedStatement(stmt, directives)
            else:
                stmt[index] = AnnotatedStatement(stmt[index], directives)
        return stmt
예제 #33
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def process_omp_attachements(self, node, stmt, index=None):
        """
        Add OpenMP pragma on the correct stmt in the correct order.

        stmt may be a list. On this case, index have to be specify to add
        OpenMP on the correct statement.
        """
        omp_directives = metadata.get(node, OMPDirective)
        if omp_directives:
            directives = list()
            for directive in omp_directives:
                directive.deps = [self.visit(dep) for dep in directive.deps]
                directives.append(directive)
            if index is None:
                stmt = AnnotatedStatement(stmt, directives)
            else:
                stmt[index] = AnnotatedStatement(stmt[index], directives)
        return stmt
예제 #34
0
    def dispatch(self, tree):
        """Dispatcher function, dispatching tree type T to method _T."""
        # display omp directive in python dump
        for omp in metadata.get(tree, openmp.OMPDirective):
            deps = list()
            for dep in omp.deps:
                old_file = self.f
                self.f = io.StringIO()
                self.dispatch(dep)
                deps.append(self.f.getvalue())
                self.f = old_file
            directive = omp.s.format(*deps)
            self._Expr(ast.Expr(ast.Str(s=directive)))

        if isinstance(tree, list):
            for t in tree:
                self.dispatch(t)
            return
        meth = getattr(self, "_" + tree.__class__.__name__)
        meth(tree)
예제 #35
0
파일: unparse.py 프로젝트: yssource/pythran
    def dispatch(self, tree):
        """Dispatcher function, dispatching tree type T to method _T."""
        # display omp directive in python dump
        for omp in metadata.get(tree, openmp.OMPDirective):
            deps = list()
            for dep in omp.deps:
                old_file = self.f
                self.f = io.StringIO()
                self.dispatch(dep)
                deps.append(self.f.getvalue())
                self.f = old_file
            directive = omp.s.format(*deps)
            self._Expr(ast.Expr(ast.Constant(directive, None)))

        if isinstance(tree, list):
            for t in tree:
                self.dispatch(t)
            return
        meth = getattr(self, "_" + tree.__class__.__name__)
        meth(tree)
예제 #36
0
파일: backend.py 프로젝트: jfinkels/pythran
    def visit_For(self, node):
        """
        Create For representation for Cxx generation.

        Examples
        --------
        >> for i in xrange(10):
        >>     ... work ...

        Becomes

        >> typename returnable<decltype(__builtin__.xrange(10))>::type __iterX
           = __builtin__.xrange(10);
        >> ... possible container size reservation ...
        >> for (auto&& i: __iterX)
        >>     ... the work ...

        This function also handle assignment for local variables.

        We can notice that three kind of loop are possible:
        - Normal for loop on iterator
        - Autofor loop.
        - Normal for loop using integer variable iteration
        Kind of loop used depend on OpenMP, yield use and variable scope.
        """
        if not isinstance(node.target, ast.Name):
            raise PythranSyntaxError(
                "Using something other than an identifier as loop target",
                node.target)
        target = self.visit(node.target)

        # Handle the body of the for loop
        loop_body = Block(map(self.visit, node.body))

        # Declare local variables at the top of the loop body
        loop_body = self.process_locals(node, loop_body, node.target.id)
        iterable = self.visit(node.iter)

        if self.can_use_c_for(node):
            header, loop = self.gen_c_for(node, target, loop_body)
        else:

            if self.can_use_autofor(node):
                header = []
                self.ldecls = {d for d in self.ldecls
                               if d.id != node.target.id}
                autofor = AutoFor(target, iterable, loop_body)
                loop = [self.process_omp_attachements(node, autofor)]
            else:
                # Iterator declaration
                local_iter = "__iter{0}".format(len(self.break_handlers))
                local_iter_decl = Assignable(DeclType(iterable))

                self.handle_omp_for(node, local_iter)

                # For yield function, iterable is globals.
                if self.yields:
                    self.extra_declarations.append(
                        (local_iter, local_iter_decl,))
                    local_iter_decl = ""

                # Assign iterable
                # For C loop, it avoids issues
                # if the upper bound is assigned in the loop
                header = [Statement("{0} {1} = {2}".format(local_iter_decl,
                                                           local_iter,
                                                           iterable))]
                loop = self.gen_for(node, target, local_iter, loop_body)

        # For xxxComprehension, it is replaced by a for loop. In this case,
        # pre-allocate size of container.
        for comp in metadata.get(node, metadata.Comprehension):
            header.append(Statement("pythonic::utils::reserve({0},{1})".format(
                comp.target,
                iterable)))

        return Block(header + loop)
예제 #37
0
파일: backend.py 프로젝트: gouarin/pythran
    def visit_For(self, node):
        """
        Create For representation for Cxx generation.

        Examples
        --------
        >> for i in xrange(10):
        >>     ... work ...

        Becomes

        >> typename returnable<decltype(__builtin__.xrange(10))>::type __iterX
           = __builtin__.xrange(10);
        >> ... possible container size reservation ...
        >> for (typename decltype(__iterX)::iterator::reference i: __iterX)
        >>     ... the work ...

        This function also handle assignment for local variables.

        We can notice that three kind of loop are possible:
        - Normal for loop on iterator
        - Autofor loop.
        - Normal for loop using integer variable iteration
        Kind of loop used depend on OpenMP, yield use and variable scope.
        """
        if not isinstance(node.target, ast.Name):
            raise PythranSyntaxError(
                "Using something other than an identifier as loop target",
                node.target)
        target = self.visit(node.target)

        # Handle the body of the for loop
        loop_body = Block(map(self.visit, node.body))

        # Declare local variables at the top of the loop body
        loop_body = self.process_locals(node, loop_body, node.target.id)
        iterable = self.visit(node.iter)

        if self.can_use_c_for(node):
            header, loop = self.gen_c_for(node, target, loop_body)
        else:

            # Iterator declaration
            local_iter = "__iter{0}".format(len(self.break_handlers))
            local_iter_decl = Assignable(DeclType(iterable))

            self.handle_omp_for(node, local_iter)

            # For yield function, iterable is globals.
            if self.yields:
                self.extra_declarations.append((
                    local_iter,
                    local_iter_decl,
                ))
                local_iter_decl = ""

            # Assign iterable
            # For C loop, it avoid issue if upper bound is reassign in the loop
            header = [
                Statement("{0} {1} = {2}".format(local_iter_decl, local_iter,
                                                 iterable))
            ]
            if self.can_use_autofor(node):
                self.ldecls = {
                    d
                    for d in self.ldecls if d.id != node.target.id
                }
                autofor = AutoFor(target, local_iter, loop_body)
                loop = [self.process_omp_attachements(node, autofor)]
            else:
                loop = self.gen_for(node, target, local_iter, local_iter_decl,
                                    loop_body)

        # For xxxComprehension, it is replaced by a for loop. In this case,
        # pre-allocate size of container.
        for comp in metadata.get(node, metadata.Comprehension):
            header.append(
                Statement("pythonic::utils::reserve({0},{1})".format(
                    comp.target, iterable)))

        return Block(header + loop)
예제 #38
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def visit_For(self, node):
        """
        Create For representation for Cxx generation.

        Examples
        --------
        >> for i in xrange(10):
        >>     ... work ...

        Becomes

        >> typename returnable<decltype(__builtin__.xrange(10))>::type __iterX
           = __builtin__.xrange(10);
        >> ... possible container size reservation ...
        >> for (auto&& i: __iterX)
        >>     ... the work ...

        This function also handle assignment for local variables.

        We can notice that three kind of loop are possible:
        - Normal for loop on iterator
        - Autofor loop.
        - Normal for loop using integer variable iteration
        Kind of loop used depend on OpenMP, yield use and variable scope.
        """
        if not isinstance(node.target, ast.Name):
            raise PythranSyntaxError(
                "Using something other than an identifier as loop target",
                node.target)
        target = self.visit(node.target)

        # Handle the body of the for loop
        loop_body = Block([self.visit(stmt) for stmt in node.body])

        # Declare local variables at the top of the loop body
        loop_body = self.process_locals(node, loop_body, node.target.id)
        iterable = self.visit(node.iter)

        if self.can_use_c_for(node):
            header, loop = self.gen_c_for(node, target, loop_body)
        else:

            if self.can_use_autofor(node):
                header = []
                self.ldecls.remove(node.target.id)
                autofor = AutoFor(target, iterable, loop_body)
                loop = [self.process_omp_attachements(node, autofor)]
            else:
                # Iterator declaration
                local_iter = "__iter{0}".format(id(node))
                local_iter_decl = self.types.builder.Assignable(
                    self.types[node.iter])

                self.handle_omp_for(node, local_iter)

                # Assign iterable
                # For C loop, it avoids issues
                # if the upper bound is assigned in the loop
                asgnt = self.make_assign(local_iter_decl, local_iter, iterable)
                header = [Statement(asgnt)]
                loop = self.gen_for(node, target, local_iter, local_iter_decl,
                                    loop_body)

        # For xxxComprehension, it is replaced by a for loop. In this case,
        # pre-allocate size of container.
        for comp in metadata.get(node, metadata.Comprehension):
            header.append(
                Statement("pythonic::utils::reserve({0},{1})".format(
                    comp.target, iterable)))

        return Block(header + loop)