Example #1
0
    def build_dependencies(self):
        """ This is basically building the definition-use chain and saving this
            information in a graph structure. This is the same as calculating
            the reaching definitions and the 'looking back' whenever it is used.

            Write After Read, Write After Write dependencies are not possible,
            the operations are in SSA form
        """
        tracker = DefTracker(self)
        #
        label_pos = 0
        jump_pos = len(self.nodes)-1
        intformod = IntegralForwardModification(self.memory_refs, self.index_vars,
                                                self.comparison_vars, self.invariant_vars)
        # pass 1
        for i,node in enumerate(self.nodes):
            op = node.op
            if rop.is_always_pure(op.opnum):
                node.setpriority(1)
            if rop.is_guard(op.opnum):
                node.setpriority(2)
            # the label operation defines all operations at the
            # beginning of the loop

            intformod.inspect_operation(op,node)
            # definition of a new variable
            if op.type != 'v':
                # In SSA form. Modifications get a new variable
                tracker.define(op, node)
            # usage of defined variables
            if rop.is_always_pure(op.opnum) or rop.is_final(op.opnum):
                # normal case every arguments definition is set
                for arg in op.getarglist():
                    tracker.depends_on_arg(arg, node)
            elif rop.is_guard(op.opnum):
                if node.exits_early():
                    pass
                else:
                    # consider cross iterations?
                    if len(self.guards) > 0:
                        last_guard = self.guards[-1]
                        last_guard.edge_to(node, failarg=True, label="guardorder")
                    for nonpure in tracker.non_pure:
                        nonpure.edge_to(node, failarg=True, label="nonpure")
                    tracker.non_pure = []
                self.guards.append(node)
                self.build_guard_dependencies(node, tracker)
            else:
                self.build_non_pure_dependencies(node, tracker)
Example #2
0
    def build_dependencies(self):
        """ This is basically building the definition-use chain and saving this
            information in a graph structure. This is the same as calculating
            the reaching definitions and the 'looking back' whenever it is used.

            Write After Read, Write After Write dependencies are not possible,
            the operations are in SSA form
        """
        tracker = DefTracker(self)
        #
        label_pos = 0
        jump_pos = len(self.nodes)-1
        intformod = IntegralForwardModification(self.memory_refs, self.index_vars,
                                                self.comparison_vars, self.invariant_vars)
        # pass 1
        for i,node in enumerate(self.nodes):
            op = node.op
            if rop.is_always_pure(op.opnum):
                node.setpriority(1)
            if rop.is_guard(op.opnum):
                node.setpriority(2)
            # the label operation defines all operations at the
            # beginning of the loop

            intformod.inspect_operation(op,node)
            # definition of a new variable
            if op.type != 'v':
                # In SSA form. Modifications get a new variable
                tracker.define(op, node)
            # usage of defined variables
            if rop.is_always_pure(op.opnum) or rop.is_final(op.opnum):
                # normal case every arguments definition is set
                for arg in op.getarglist():
                    tracker.depends_on_arg(arg, node)
            elif rop.is_guard(op.opnum):
                if node.exits_early():
                    pass
                else:
                    # consider cross iterations?
                    if len(self.guards) > 0:
                        last_guard = self.guards[-1]
                        last_guard.edge_to(node, failarg=True, label="guardorder")
                    for nonpure in tracker.non_pure:
                        nonpure.edge_to(node, failarg=True, label="nonpure")
                    tracker.non_pure = []
                self.guards.append(node)
                self.build_guard_dependencies(node, tracker)
            else:
                self.build_non_pure_dependencies(node, tracker)
Example #3
0
 def is_always_pure(self, exclude_first=False, exclude_last=False):
     last = len(self.path)-1
     count = len(self.path)
     i = 0
     if exclude_first:
         i += 1
     if exclude_last:
         count -= 1
     while i < count: 
         node = self.path[i]
         if node.is_imaginary():
             i += 1
             continue
         op = node.getoperation()
         if rop.is_guard(op.opnum):
             descr = op.getdescr()
             if not descr:
                 return False
             assert isinstance(descr, AbstractFailDescr)
             if not descr.exits_early():
                 return False
         elif not rop.is_always_pure(op.opnum):
             return False
         i += 1
     return True
Example #4
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(
                    op.opnum) and ops[i +
                                      1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            # Also, don't move cond_call_value in the short preamble.
            # The issue there is that it's usually pointless to try to
            # because the 'value' argument is typically not a loop
            # invariant, and would really need to be in order to end up
            # in the short preamble.  Maybe the code works anyway in the
            # other rare case, but better safe than sorry and don't try.
            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                if not OpHelpers.is_cond_call_value(op.opnum):
                    sb.add_pure_op(op)
Example #5
0
 def is_always_pure(self, exclude_first=False, exclude_last=False):
     last = len(self.path)-1
     count = len(self.path)
     i = 0
     if exclude_first:
         i += 1
     if exclude_last:
         count -= 1
     while i < count: 
         node = self.path[i]
         if node.is_imaginary():
             i += 1
             continue
         op = node.getoperation()
         if rop.is_guard(op.opnum):
             descr = op.getdescr()
             if not descr:
                 return False
             assert isinstance(descr, AbstractFailDescr)
             if not descr.exits_early():
                 return False
         elif not rop.is_always_pure(op.opnum):
             return False
         i += 1
     return True
Example #6
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(
                    op.opnum) and ops[i +
                                      1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                sb.add_pure_op(op)
Example #7
0
    def optimize_default(self, op):
        canfold = rop.is_always_pure(op.opnum)
        if rop.is_ovf(op.opnum):
            self.postponed_op = op
            return
        if self.postponed_op:
            nextop = op
            op = self.postponed_op
            self.postponed_op = None
            canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
        else:
            nextop = None

        save = False
        if canfold:
            for i in range(op.numargs()):
                if self.get_constant_box(op.getarg(i)) is None:
                    break
            else:
                # all constant arguments: constant-fold away
                resbox = self.optimizer.constant_fold(op)
                # note that INT_xxx_OVF is not done from here, and the
                # overflows in the INT_xxx operations are ignored
                self.optimizer.make_constant(op, resbox)
                return

            # did we do the exact same operation already?
            recentops = self.getrecentops(op.getopnum())
            save = True
            oldop = recentops.lookup(self.optimizer, op)
            if oldop is not None:
                self.optimizer.make_equal_to(op, oldop)
                return

        # otherwise, the operation remains
        self.emit_operation(op)
        if rop.returns_bool_result(op.opnum):
            self.getintbound(op).make_bool()
        if save:
            recentops = self.getrecentops(op.getopnum())
            recentops.add(op)
        if nextop:
            self.emit_operation(nextop)
Example #8
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(op.opnum) and ops[i + 1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            # Also, don't move cond_call_value in the short preamble.
            # The issue there is that it's usually pointless to try to
            # because the 'value' argument is typically not a loop
            # invariant, and would really need to be in order to end up
            # in the short preamble.  Maybe the code works anyway in the
            # other rare case, but better safe than sorry and don't try.
            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                if not OpHelpers.is_cond_call_value(op.opnum):
                    sb.add_pure_op(op)
Example #9
0
    def optimize_default(self, op):
        canfold = rop.is_always_pure(op.opnum)
        if rop.is_ovf(op.opnum):
            self.postponed_op = op
            return
        if self.postponed_op:
            nextop = op
            op = self.postponed_op
            self.postponed_op = None
            canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
        else:
            nextop = None

        save = False
        if canfold:
            for i in range(op.numargs()):
                if self.get_constant_box(op.getarg(i)) is None:
                    break
            else:
                # all constant arguments: constant-fold away
                resbox = self.optimizer.constant_fold(op)
                # note that INT_xxx_OVF is not done from here, and the
                # overflows in the INT_xxx operations are ignored
                self.optimizer.make_constant(op, resbox)
                return

            # did we do the exact same operation already?
            recentops = self.getrecentops(op.getopnum())
            save = True
            oldop = recentops.lookup(self.optimizer, op)
            if oldop is not None:
                self.optimizer.make_equal_to(op, oldop)
                return

        # otherwise, the operation remains
        return self.emit_result(DefaultOptimizationResult(self, op, save, nextop))
Example #10
0
 def is_pure(self):
     return rop.is_always_pure(self.op.getopnum())
Example #11
0
 def is_pure(self):
     return rop.is_always_pure(self.op.getopnum())