[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