[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