[pypy-commit] pypy arm-backend-2: implement merging of comparison operations with following guards

bivab noreply at buildbot.pypy.org
Tue Oct 25 11:07:56 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r48420:f29ee3944161
Date: 2011-10-24 17:14 +0200
http://bitbucket.org/pypy/pypy/changeset/f29ee3944161/

Log:	implement merging of comparison operations with following guards

diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -8,7 +8,10 @@
 from pypy.jit.backend.arm.arch import WORD, FUNC_ALIGN, PC_OFFSET, N_REGISTERS_SAVED_BY_MALLOC
 from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
 from pypy.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager, ARMv7RegisterMananger,
-                                                    _check_imm_arg, TempInt, TempPtr)
+                                        _check_imm_arg, TempInt,
+                                        TempPtr,
+                                        operations as regalloc_operations,
+                                        operations_with_guard as regalloc_operations_with_guard)
 from pypy.jit.backend.arm.jump import remap_frame_layout
 from pypy.jit.backend.llsupport.regalloc import compute_vars_longevity, TempBox
 from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
@@ -791,34 +794,45 @@
                 regalloc.possibly_free_vars_for_op(op)
             elif self.can_merge_with_next_guard(op, i, operations):
                 regalloc.next_instruction()
-                arglocs = regalloc.operations_with_guard[opnum](regalloc, op,
+                arglocs = regalloc_operations_with_guard[opnum](regalloc, op,
                                         operations[i+1], fcond)
-                fcond = self.operations_with_guard[opnum](self, op,
+                fcond = asm_operations_with_guard[opnum](self, op,
                                         operations[i+1], arglocs, regalloc, fcond)
             elif not we_are_translated() and op.getopnum() == -124:
                 regalloc.prepare_force_spill(op, fcond)
             else:
-                arglocs = regalloc.operations[opnum](regalloc, op, fcond)
+                arglocs = regalloc_operations[opnum](regalloc, op, fcond)
                 if arglocs is not None:
-                    fcond = self.operations[opnum](self, op, arglocs, regalloc, fcond)
+                    fcond = asm_operations[opnum](self, op, arglocs, regalloc, fcond)
             if op.result:
                 regalloc.possibly_free_var(op.result)
             regalloc.possibly_free_vars_for_op(op)
             regalloc._check_invariants()
 
+    # from ../x86/regalloc.py
     def can_merge_with_next_guard(self, op, i, operations):
-        num = op.getopnum()
-        if num == rop.CALL_MAY_FORCE or num == rop.CALL_ASSEMBLER:
+        if (op.getopnum() == rop.CALL_MAY_FORCE or
+            op.getopnum() == rop.CALL_ASSEMBLER or
+            op.getopnum() == rop.CALL_RELEASE_GIL):
             assert operations[i + 1].getopnum() == rop.GUARD_NOT_FORCED
             return True
-        if num == rop.INT_MUL_OVF or num == rop.INT_ADD_OVF or num == rop.INT_SUB_OVF:
-            opnum = operations[i + 1].getopnum()
-            assert opnum  == rop.GUARD_OVERFLOW or opnum == rop.GUARD_NO_OVERFLOW
-            return True
-        if num == rop.CALL_RELEASE_GIL:
-            return True
-        return False
-
+        if not op.is_comparison():
+            if op.is_ovf():
+                if (operations[i + 1].getopnum() != rop.GUARD_NO_OVERFLOW and
+                    operations[i + 1].getopnum() != rop.GUARD_OVERFLOW):
+                    not_implemented("int_xxx_ovf not followed by "
+                                    "guard_(no)_overflow")
+                return True
+            return False
+        if (operations[i + 1].getopnum() != rop.GUARD_TRUE and
+            operations[i + 1].getopnum() != rop.GUARD_FALSE):
+            return False
+        if operations[i + 1].getarg(0) is not op.result:
+            return False
+        if (self._regalloc.longevity[op.result][1] > i + 1 or
+            op.result in operations[i + 1].getfailargs()):
+            return False
+        return True
 
     def _insert_checks(self, mc=None):
         if not we_are_translated():
@@ -1148,36 +1162,29 @@
         else:
             return 0
 
-def make_operation_list():
-    def notimplemented(self, op, arglocs, regalloc, fcond):
-        raise NotImplementedError, op
+def notimplemented(self, op, arglocs, regalloc, fcond):
+    raise NotImplementedError, op
+def notimplemented_with_guard(self, op, guard_op, arglocs, regalloc, fcond):
+    raise NotImplementedError, op
 
-    operations = [None] * (rop._LAST+1)
-    for key, value in rop.__dict__.items():
-        key = key.lower()
-        if key.startswith('_'):
-            continue
-        methname = 'emit_op_%s' % key
-        if hasattr(AssemblerARM, methname):
-            func = getattr(AssemblerARM, methname).im_func
-        else:
-            func = notimplemented
-        operations[value] = func
-    return operations
+asm_operations = [notimplemented] * (rop._LAST + 1)
+asm_operations_with_guard = [notimplemented_with_guard] * (rop._LAST + 1)
 
-def make_guard_operation_list():
-    def notimplemented(self, op, guard_op, arglocs, regalloc, fcond):
-        raise NotImplementedError, op
-    guard_operations = [notimplemented] * rop._LAST
-    for key, value in rop.__dict__.items():
-        key = key.lower()
-        if key.startswith('_'):
-            continue
-        methname = 'emit_guard_%s' % key
-        if hasattr(AssemblerARM, methname):
-            func = getattr(AssemblerARM, methname).im_func
-            guard_operations[value] = func
-    return guard_operations
+for key, value in rop.__dict__.items():
+    key = key.lower()
+    if key.startswith('_'):
+        continue
+    methname = 'emit_op_%s' % key
+    if hasattr(AssemblerARM, methname):
+        func = getattr(AssemblerARM, methname).im_func
+        asm_operations[value] = func
 
-AssemblerARM.operations = make_operation_list()
-AssemblerARM.operations_with_guard = make_guard_operation_list()
+for key, value in rop.__dict__.items():
+    key = key.lower()
+    if key.startswith('_'):
+        continue
+    methname = 'emit_guard_%s' % key
+    if hasattr(AssemblerARM, methname):
+        func = getattr(AssemblerARM, methname).im_func
+        asm_operations_with_guard[value] = func
+
diff --git a/pypy/jit/backend/arm/helper/assembler.py b/pypy/jit/backend/arm/helper/assembler.py
--- a/pypy/jit/backend/arm/helper/assembler.py
+++ b/pypy/jit/backend/arm/helper/assembler.py
@@ -4,6 +4,7 @@
 from pypy.jit.backend.arm.codebuilder import AbstractARMv7Builder
 from pypy.jit.metainterp.history import ConstInt, BoxInt, FLOAT
 from pypy.rlib.rarithmetic import r_uint, r_longlong, intmask
+from pypy.jit.metainterp.resoperation import rop
 
 def gen_emit_op_unary_cmp(true_cond, false_cond):
     def f(self, op, arglocs, regalloc, fcond):
@@ -55,6 +56,24 @@
         return fcond
     return f
 
+def gen_emit_cmp_op_guard(condition):
+    def f(self, op, guard, arglocs, regalloc, fcond):
+        l0 = arglocs[0]
+        l1 = arglocs[1]
+
+        inv = c.get_opposite_of(condition)
+        if l1.is_imm():
+            self.mc.CMP_ri(l0.value, imm=l1.getint(), cond=fcond)
+        else:
+            self.mc.CMP_rr(l0.value, l1.value, cond=fcond)
+        guard_opnum = guard.getopnum()
+        cond = condition
+        if guard_opnum == rop.GUARD_FALSE:
+            cond = inv
+        self._emit_guard(guard, arglocs[2:], cond)
+        return fcond
+    return f
+
 def gen_emit_float_op(opname):
     op_rr = getattr(AbstractARMv7Builder, opname)
     def f(self, op, arglocs, regalloc, fcond):
diff --git a/pypy/jit/backend/arm/helper/regalloc.py b/pypy/jit/backend/arm/helper/regalloc.py
--- a/pypy/jit/backend/arm/helper/regalloc.py
+++ b/pypy/jit/backend/arm/helper/regalloc.py
@@ -95,7 +95,7 @@
     return f
 
 def prepare_cmp_op(name=None, inverse=False):
-    def f(self, op, fcond):
+    def f(self, op, guard_op, fcond):
         assert fcond is not None
         boxes = list(op.getarglist())
         if not inverse:
@@ -114,9 +114,14 @@
             l1, box = self._ensure_value_is_boxed(arg1, forbidden_vars=boxes)
             boxes.append(box)
         self.possibly_free_vars(boxes)
-        res = self.force_allocate_reg(op.result)
-        self.possibly_free_var(op.result)
-        return [l0, l1, res]
+        if guard_op is None:
+            res = self.force_allocate_reg(op.result)
+            self.possibly_free_var(op.result)
+            return [l0, l1, res]
+        else:
+            args = self._prepare_guard(guard_op, [l0, l1])
+            self.possibly_free_vars(guard_op.getfailargs())
+            return args
     if name:
         f.__name__ = name
     return f
diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py
--- a/pypy/jit/backend/arm/opassembler.py
+++ b/pypy/jit/backend/arm/opassembler.py
@@ -11,6 +11,7 @@
                                                     gen_emit_op_unary_cmp,
                                                     gen_emit_op_ri,
                                                     gen_emit_cmp_op,
+                                                    gen_emit_cmp_op_guard,
                                                     gen_emit_float_op,
                                                     gen_emit_float_cmp_op,
                                                     gen_emit_unary_float_op, 
@@ -139,11 +140,28 @@
     emit_op_uint_lt = gen_emit_cmp_op(c.HI)
     emit_op_uint_ge = gen_emit_cmp_op(c.LS)
 
+    emit_op_ptr_eq = emit_op_int_eq
+    emit_op_ptr_ne = emit_op_int_ne
+
+    emit_guard_int_lt = gen_emit_cmp_op_guard(c.LT)
+    emit_guard_int_le = gen_emit_cmp_op_guard(c.LE)
+    emit_guard_int_eq = gen_emit_cmp_op_guard(c.EQ)
+    emit_guard_int_ne = gen_emit_cmp_op_guard(c.NE)
+    emit_guard_int_gt = gen_emit_cmp_op_guard(c.GT)
+    emit_guard_int_ge = gen_emit_cmp_op_guard(c.GE)
+
+    emit_guard_uint_le = gen_emit_cmp_op_guard(c.LS)
+    emit_guard_uint_gt = gen_emit_cmp_op_guard(c.HI)
+
+    emit_guard_uint_lt = gen_emit_cmp_op_guard(c.HI)
+    emit_guard_uint_ge = gen_emit_cmp_op_guard(c.LS)
+
+    emit_guard_ptr_eq = emit_guard_int_eq
+    emit_guard_ptr_ne = emit_guard_int_ne
+
     emit_op_int_add_ovf = emit_op_int_add
     emit_op_int_sub_ovf = emit_op_int_sub
 
-    emit_op_ptr_eq = emit_op_int_eq
-    emit_op_ptr_ne = emit_op_int_ne
 
 
 class UnaryIntOpAssembler(object):
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -425,11 +425,28 @@
     prepare_op_uint_lt = prepare_cmp_op('uint_lt', inverse=True)
     prepare_op_uint_ge = prepare_cmp_op('uint_ge', inverse=True)
 
+    prepare_op_ptr_eq = prepare_op_int_eq
+    prepare_op_ptr_ne = prepare_op_int_ne
+
+    prepare_guard_int_lt = prepare_cmp_op('guard_int_lt')
+    prepare_guard_int_le = prepare_cmp_op('guard_int_le')
+    prepare_guard_int_eq = prepare_cmp_op('guard_int_eq')
+    prepare_guard_int_ne = prepare_cmp_op('guard_int_ne')
+    prepare_guard_int_gt = prepare_cmp_op('guard_int_gt')
+    prepare_guard_int_ge = prepare_cmp_op('guard_int_ge')
+
+    prepare_guard_uint_le = prepare_cmp_op('guard_uint_le')
+    prepare_guard_uint_gt = prepare_cmp_op('guard_uint_gt')
+
+    prepare_guard_uint_lt = prepare_cmp_op('guard_uint_lt', inverse=True)
+    prepare_guard_uint_ge = prepare_cmp_op('guard_uint_ge', inverse=True)
+
+    prepare_guard_ptr_eq = prepare_guard_int_eq
+    prepare_guard_ptr_ne = prepare_guard_int_ne
+
     prepare_op_int_add_ovf = prepare_op_int_add
     prepare_op_int_sub_ovf = prepare_op_int_sub
 
-    prepare_op_ptr_eq = prepare_op_int_eq
-    prepare_op_ptr_ne = prepare_op_int_ne
 
     prepare_op_int_is_true = prepare_op_unary_cmp('int_is_true')
     prepare_op_int_is_zero = prepare_op_unary_cmp('int_is_zero')
@@ -1186,36 +1203,32 @@
         self.force_spill_var(op.getarg(0))
         return []
 
-def make_operation_list():
-    def notimplemented(self, op, fcond):
-        raise NotImplementedError, op
+def add_none_argument(fn):
+    return lambda self, op, fcond: fn(self, op, None, fcond)
 
-    operations = [None] * (rop._LAST+1)
-    for key, value in rop.__dict__.items():
-        key = key.lower()
-        if key.startswith('_'):
-            continue
-        methname = 'prepare_op_%s' % key
-        if hasattr(Regalloc, methname):
-            func = getattr(Regalloc, methname).im_func
-        else:
-            func = notimplemented
+def notimplemented(self, op, fcond):
+    raise NotImplementedError, op
+def notimplemented_with_guard(self, op, guard_op, fcond):
+    raise NotImplementedError, op
+
+operations = [notimplemented] * (rop._LAST + 1)
+operations_with_guard = [notimplemented_with_guard] * (rop._LAST + 1)
+
+for key, value in rop.__dict__.items():
+    key = key.lower()
+    if key.startswith('_'):
+        continue
+    methname = 'prepare_op_%s' % key
+    if hasattr(Regalloc, methname):
+        func = getattr(Regalloc, methname).im_func
         operations[value] = func
-    return operations
 
-def make_guard_operation_list():
-    def notimplemented(self, op, guard_op, fcond):
-        raise NotImplementedError, op
-    guard_operations = [notimplemented] * rop._LAST
-    for key, value in rop.__dict__.items():
-        key = key.lower()
-        if key.startswith('_'):
-            continue
-        methname = 'prepare_guard_%s' % key
-        if hasattr(Regalloc, methname):
-            func = getattr(Regalloc, methname).im_func
-            guard_operations[value] = func
-    return guard_operations
-
-Regalloc.operations = make_operation_list()
-Regalloc.operations_with_guard = make_guard_operation_list()
+for key, value in rop.__dict__.items():
+    key = key.lower()
+    if key.startswith('_'):
+        continue
+    methname = 'prepare_guard_%s' % key
+    if hasattr(Regalloc, methname):
+        func = getattr(Regalloc, methname).im_func
+        operations_with_guard[value] = func
+        operations[value] = add_none_argument(func)


More information about the pypy-commit mailing list