[pypy-svn] r62904 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test
fijal at codespeak.net
fijal at codespeak.net
Thu Mar 12 20:32:03 CET 2009
Author: fijal
Date: Thu Mar 12 20:32:01 2009
New Revision: 62904
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py
Log:
implement an optimization that lets guard ops store the result of comparison
in processor flags, if possible
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu Mar 12 20:32:01 2009
@@ -262,6 +262,24 @@
getattr(self.mc, 'SET' + cond)(lower_byte(result_loc))
return genop_cmp
+ def _cmpop_guard(cond, rev_cond, false_cond, false_rev_cond):
+ def genop_cmp_guard(self, op, guard_op, arglocs, result_loc):
+ if isinstance(op.args[0], Const):
+ self.mc.CMP(arglocs[1], arglocs[0])
+ if guard_op.opnum == rop.GUARD_FALSE:
+ name = 'J' + rev_cond
+ else:
+ name = 'J' + false_rev_cond
+ else:
+ self.mc.CMP(arglocs[0], arglocs[1])
+ if guard_op.opnum == rop.GUARD_FALSE:
+ name = 'J' + cond
+ else:
+ name = 'J' + false_cond
+ self.implement_guard(guard_op, getattr(self.mc, name), arglocs[2:])
+ return genop_cmp_guard
+
+
def call(self, addr, args, res):
for i in range(len(args)):
arg = args[i]
@@ -283,10 +301,10 @@
genop_uint_mul = genop_int_mul
xxx_genop_uint_and = genop_int_and
- genop_int_mul_ovf = _binaryop_ovf("IMUL", True)
- genop_int_sub_ovf = _binaryop_ovf("SUB")
- genop_int_add_ovf = _binaryop_ovf("ADD", True)
- genop_int_mod_ovf = _binaryop_ovf("IDIV", is_mod=True)
+ genop_guard_int_mul_ovf = _binaryop_ovf("IMUL", True)
+ genop_guard_int_sub_ovf = _binaryop_ovf("SUB")
+ genop_guard_int_add_ovf = _binaryop_ovf("ADD", True)
+ genop_guard_int_mod_ovf = _binaryop_ovf("IDIV", is_mod=True)
genop_int_lt = _cmpop("L", "G")
genop_int_le = _cmpop("LE", "GE")
@@ -300,6 +318,18 @@
genop_uint_le = _cmpop("BE", "AE")
genop_uint_ge = _cmpop("AE", "BE")
+ genop_guard_int_lt = _cmpop_guard("L", "G", "GE", "LE")
+ genop_guard_int_le = _cmpop_guard("LE", "GE", "G", "L")
+ genop_guard_int_eq = _cmpop_guard("E", "NE", "NE", "E")
+ genop_guard_int_ne = _cmpop_guard("NE", "E", "E", "NE")
+ genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE")
+ genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G")
+
+ genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE")
+ genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE")
+ genop_guard_uint_le = _cmpop_guard("BE", "AE", "A", "B")
+ genop_guard_uint_ge = _cmpop_guard("AE", "BE", "B", "A")
+
# for now all chars are being considered ints, although we should make
# a difference at some point
xxx_genop_char_eq = genop_int_eq
@@ -391,7 +421,7 @@
genop_getfield_raw = genop_getfield_gc
genop_getarrayitem_gc_pure = genop_getarrayitem_gc
- def genop_setfield_gc(self, op, arglocs):
+ def genop_discard_setfield_gc(self, op, arglocs):
base_loc, ofs_loc, size_loc, value_loc = arglocs
assert isinstance(size_loc, IMM32)
size = size_loc.value
@@ -405,7 +435,7 @@
else:
raise NotImplementedError("Addr size %d" % size)
- def genop_setarrayitem_gc(self, op, arglocs):
+ def genop_discard_setarrayitem_gc(self, op, arglocs):
base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs
assert isinstance(baseofs, IMM32)
assert isinstance(scale_loc, IMM32)
@@ -418,14 +448,14 @@
else:
raise NotImplementedError("scale = %d" % scale_loc.value)
- def genop_strsetitem(self, op, arglocs):
+ def genop_discard_strsetitem(self, op, arglocs):
base_loc, ofs_loc, val_loc = arglocs
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
self.cpu.translate_support_code)
self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize),
lower_byte(val_loc))
- genop_setfield_raw = genop_setfield_gc
+ genop_discard_setfield_raw = genop_discard_setfield_gc
def genop_strlen(self, op, arglocs, resloc):
base_loc = arglocs[0]
@@ -443,13 +473,13 @@
self.cpu.translate_support_code)
self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize))
- def genop_merge_point(self, op, locs):
+ def genop_discard_merge_point(self, op, locs):
op.position = self.mc.tell()
op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op)
- genop_catch = genop_merge_point
+ genop_discard_catch = genop_discard_merge_point
- def genop_return(self, op, locs):
+ def genop_discard_return(self, op, locs):
if op.args:
loc = locs[0]
if loc is not eax:
@@ -467,16 +497,16 @@
self.mc.MOV(heap(self._exception_addr), imm(0))
self.mc.RET()
- def genop_jump(self, op, locs):
+ def genop_discard_jump(self, op, locs):
targetmp = op.jump_target
self.mc.JMP(rel32(targetmp.position))
- def genop_guard_true(self, op, locs):
+ def genop_discard_guard_true(self, op, locs):
loc = locs[0]
self.mc.TEST(loc, loc)
self.implement_guard(op, self.mc.JZ, locs[1:])
- def genop_guard_no_exception(self, op, locs):
+ def genop_discard_guard_no_exception(self, op, locs):
loc = locs[0]
self.mc.MOV(loc, heap(self._exception_addr))
self.mc.TEST(loc, loc)
@@ -492,23 +522,23 @@
self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD)))
self.mc.MOV(heap(self._exception_addr), imm(0))
- def genop_guard_false(self, op, locs):
+ def genop_discard_guard_false(self, op, locs):
loc = locs[0]
self.mc.TEST(loc, loc)
self.implement_guard(op, self.mc.JNZ, locs[1:])
- def genop_guard_value(self, op, locs):
+ def genop_discard_guard_value(self, op, locs):
arg0 = locs[0]
arg1 = locs[1]
self.mc.CMP(arg0, arg1)
self.implement_guard(op, self.mc.JNE, locs[2:])
- def genop_guard_class(self, op, locs):
+ def genop_discard_guard_class(self, op, locs):
offset = 0 # XXX for now, the vtable ptr is at the start of the obj
self.mc.CMP(mem(locs[0], offset), locs[1])
self.implement_guard(op, self.mc.JNE, locs[2:])
- #def genop_guard_nonvirtualized(self, op):
+ #def genop_discard_guard_nonvirtualized(self, op):
# STRUCT = op.args[0].concretetype.TO
# offset, size = symbolic.get_field_token(STRUCT, 'vable_rti')
# assert size == WORD
@@ -605,18 +635,21 @@
genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
for name, value in Assembler386.__dict__.iteritems():
- if name.startswith('genop_'):
- opname = name[len('genop_'):]
+ if name.startswith('genop_discard_'):
+ opname = name[len('genop_discard_'):]
if opname == 'return':
num = RETURN
else:
num = getattr(rop, opname.upper())
- if value.func_code.co_argcount == 3:
- genop_discard_list[num] = value
- elif value.func_code.co_argcount == 5:
- genop_guard_list[num] = value
- else:
- genop_list[num] = value
+ genop_discard_list[num] = value
+ elif name.startswith('genop_guard_') and name != 'genop_guard_exception':
+ opname = name[len('genop_guard_'):]
+ num = getattr(rop, opname.upper())
+ genop_guard_list[num] = value
+ elif name.startswith('genop_'):
+ opname = name[len('genop_'):]
+ num = getattr(rop, opname.upper())
+ genop_list[num] = value
def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0):
if isinstance(reg_or_imm1, IMM32):
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu Mar 12 20:32:01 2009
@@ -206,6 +206,16 @@
self.longevity[v][0] <= self.position):
assert not v in self.dirty_stack
+ def can_optimize_cmp_op(self, op, i, operations):
+ if not op.is_comparison():
+ return False
+ if (operations[i + 1].opnum != rop.GUARD_TRUE and
+ operations[i + 1].opnum != rop.GUARD_FALSE):
+ return False
+ if self.longevity[op.result][1] > i + 1:
+ return False
+ return True
+
def walk_operations(self, operations, loop_consts):
# first pass - walk along the operations in order to find
# load/store places
@@ -225,10 +235,15 @@
assert operations[i + 1].opnum == rop.GUARD_NO_EXCEPTION
new_ops += oplist[op.opnum](self, op, operations[i + 1])
i += 1
+ elif self.can_optimize_cmp_op(op, i, operations):
+ new_ops += oplist[op.opnum](self, op, operations[i + 1])
+ i += 1
else:
new_ops += oplist[op.opnum](self, op, None)
self.eventually_free_var(op.result)
self._check_invariants()
+ else:
+ self.eventually_free_vars(op.args)
i += 1
return new_ops
@@ -621,6 +636,7 @@
def _consider_binop_ovf(self, op, guard_op):
loc, argloc, ops = self._consider_binop_part(op, None)
locs = self._locs_from_liveboxes(guard_op)
+ self.position += 1
self.eventually_free_vars(guard_op.liveboxes)
return ops + [PerformWithGuard(op, guard_op, [loc, argloc] + locs, loc)]
@@ -663,8 +679,9 @@
_, ops3 = self.force_allocate_reg(tmpvar, [], eax)
assert (l0, l1, l2) == (eax, ecx, edx)
locs = self._locs_from_liveboxes(guard_op)
- self.eventually_free_vars(guard_op.liveboxes)
self.eventually_free_vars(op.args + [tmpvar])
+ self.position += 1
+ self.eventually_free_vars(guard_op.liveboxes)
return (ops0 + ops1 + ops2 + ops3 +
[PerformWithGuard(op, guard_op, [eax, ecx] + locs, edx)])
@@ -678,7 +695,7 @@
self.eventually_free_vars(op.args + [tmpvar])
return ops0 + ops1 + ops2 + [Perform(op, [eax, ecx], eax)]
- def _consider_compop(self, op, ignored):
+ def _consider_compop(self, op, guard_op):
vx = op.args[0]
vy = op.args[1]
arglocs = [self.loc(vx), self.loc(vy)]
@@ -689,8 +706,15 @@
arglocs[0], ops0 = self.force_allocate_reg(vx, [])
self.eventually_free_var(vx)
self.eventually_free_var(vy)
- loc, ops = self.force_allocate_reg(op.result, op.args)
- return ops0 + ops + [Perform(op, arglocs, loc)]
+ if guard_op is None:
+ loc, ops = self.force_allocate_reg(op.result, op.args)
+ return ops0 + ops + [Perform(op, arglocs, loc)]
+ else:
+ locs = self._locs_from_liveboxes(guard_op)
+ self.position += 1
+ self.eventually_free_var(op.result)
+ self.eventually_free_vars(guard_op.liveboxes)
+ return ops0 + [PerformWithGuard(op, guard_op, arglocs + locs, None)]
consider_int_lt = _consider_compop
consider_int_gt = _consider_compop
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Thu Mar 12 20:32:01 2009
@@ -8,6 +8,7 @@
from pypy.rpython.lltypesystem import lltype
from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats
from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.backend.x86.regalloc import RETURN
def test_simple_loop():
meta_interp = FakeMetaInterp()
@@ -127,7 +128,6 @@
assert meta_interp.recordedvalues == [0, 1, 3, 2, 0]
def test_bool_optimizations():
- py.test.skip("Not yet")
meta_interp = FakeMetaInterp()
cpu = CPU(rtyper=None, stats=FakeStats())
cpu.set_meta_interp(meta_interp)
@@ -143,9 +143,35 @@
ops[2].liveboxes = [res]
cpu.compile_operations(ops)
- res = cpu.execute_operations_in_new_frame('foo', ops[0],
- [arg0, arg1], 'int')
+ res = cpu.execute_operations_in_new_frame('foo', ops,
+ [arg0, arg1])
assert len(cpu.assembler._regalloc.computed_ops) == 2
assert meta_interp.gf
# er, what to check here, assembler???
+
+def test_bool_cannot_optimize():
+ meta_interp = FakeMetaInterp()
+ cpu = CPU(rtyper=None, stats=FakeStats())
+ cpu.set_meta_interp(meta_interp)
+ arg0 = BoxInt(3)
+ arg1 = BoxInt(4)
+ res = BoxInt(0)
+ r = BoxInt(1)
+ ops = [
+ ResOperation(rop.MERGE_POINT, [arg0, arg1], None),
+ ResOperation(rop.INT_GT, [arg0, arg1], res),
+ ResOperation(rop.GUARD_TRUE, [res], None),
+ # we should never get here
+ ResOperation(rop.INT_ADD, [res, ConstInt(0)], r),
+ ResOperation(RETURN, [r], None),
+ ]
+ ops[2].liveboxes = [res]
+
+ cpu.compile_operations(ops)
+ res = cpu.execute_operations_in_new_frame('foo', ops,
+ [arg0, arg1])
+
+ assert len(cpu.assembler._regalloc.computed_ops) == 5
+ assert meta_interp.gf
+ # er, what to check here, assembler???
More information about the Pypy-commit
mailing list