[pypy-svn] r69102 - in pypy/trunk/pypy: jit/backend/llgraph jit/backend/test jit/backend/x86 jit/backend/x86/test jit/metainterp jit/metainterp/test module/pypyjit/test

arigo at codespeak.net arigo at codespeak.net
Mon Nov 9 18:20:05 CET 2009


Author: arigo
Date: Mon Nov  9 18:20:03 2009
New Revision: 69102

Modified:
   pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
   pypy/trunk/pypy/jit/backend/test/runner_test.py
   pypy/trunk/pypy/jit/backend/test/test_random.py
   pypy/trunk/pypy/jit/backend/x86/assembler.py
   pypy/trunk/pypy/jit/backend/x86/regalloc.py
   pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py
   pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/trunk/pypy/jit/backend/x86/test/test_runner.py
   pypy/trunk/pypy/jit/metainterp/codewriter.py
   pypy/trunk/pypy/jit/metainterp/executor.py
   pypy/trunk/pypy/jit/metainterp/history.py
   pypy/trunk/pypy/jit/metainterp/optimizefindnode.py
   pypy/trunk/pypy/jit/metainterp/optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/resoperation.py
   pypy/trunk/pypy/jit/metainterp/test/test_basic.py
   pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
Log:
Merge the branch 'guard-nonnull':

Remove oononnull and ooisnull operations, replace with guard_nonnull/isnull.
Kills a bit of stuff here and there.



Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py	Mon Nov  9 18:20:03 2009
@@ -104,8 +104,6 @@
     'new_with_vtable' : (('ref',), 'ref'),
     'new'             : ((), 'ref'),
     'new_array'       : (('int',), 'ref'),
-    'oononnull'       : (('ref',), 'bool'),
-    'ooisnull'        : (('ref',), 'bool'),
     'oois'            : (('ref', 'ref'), 'bool'),
     'ooisnot'         : (('ref', 'ref'), 'bool'),
     'instanceof'      : (('ref',), 'bool'),
@@ -134,6 +132,8 @@
     'guard_exception'      : (('ref',), 'ref'),
     'guard_no_overflow'    : ((), None),
     'guard_overflow'       : ((), None),
+    'guard_nonnull'        : (('ref',), None),
+    'guard_isnull'        : (('ref',), None),
     'newstr'          : (('int',), 'ref'),
     'strlen'          : (('ref',), 'int'),
     'strgetitem'      : (('ref', 'int'), 'int'),
@@ -551,6 +551,9 @@
         if value:
             raise GuardFailed
 
+    op_guard_nonnull = op_guard_true
+    op_guard_isnull  = op_guard_false
+
     def op_guard_class(self, _, value, expected_class):
         value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value)
         expected_class = llmemory.cast_adr_to_ptr(

Modified: pypy/trunk/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/trunk/pypy/jit/backend/test/runner_test.py	Mon Nov  9 18:20:03 2009
@@ -441,9 +441,13 @@
 
 
     def test_passing_guards(self):
+        t_box, T_box = self.alloc_instance(self.T)
+        nullbox = self.null_instance()
         all = [(rop.GUARD_TRUE, [BoxInt(1)]),
                (rop.GUARD_FALSE, [BoxInt(0)]),
-               (rop.GUARD_VALUE, [BoxInt(42), BoxInt(42)])]
+               (rop.GUARD_VALUE, [BoxInt(42), BoxInt(42)]),
+               (rop.GUARD_NONNULL, [t_box]),
+               (rop.GUARD_ISNULL, [nullbox])]
         if self.cpu.supports_floats:
             all.append((rop.GUARD_VALUE, [BoxFloat(3.5), BoxFloat(3.5)]))
         for (opname, args) in all:
@@ -460,9 +464,13 @@
         #                       'void')
 
     def test_failing_guards(self):
+        t_box, T_box = self.alloc_instance(self.T)
+        nullbox = self.null_instance()
         all = [(rop.GUARD_TRUE, [BoxInt(0)]),
                (rop.GUARD_FALSE, [BoxInt(1)]),
-               (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)])]
+               (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)]),
+               (rop.GUARD_NONNULL, [nullbox]),
+               (rop.GUARD_ISNULL, [t_box])]
         if self.cpu.supports_floats:
             all.append((rop.GUARD_VALUE, [BoxFloat(-1.0), BoxFloat(1.0)]))
         for opname, args in all:
@@ -493,10 +501,6 @@
         assert r.value == 0
         r = self.execute_operation(rop.OOISNOT, [u2_box, u1_box], 'int')
         assert r.value == 1
-        r = self.execute_operation(rop.OOISNULL, [u1_box], 'int')
-        assert r.value == 0
-        r = self.execute_operation(rop.OONONNULL, [u2_box], 'int')
-        assert r.value == 1
         #
         null_box = self.null_instance()
         r = self.execute_operation(rop.OOIS, [null_box,
@@ -513,10 +517,6 @@
         assert r.value == 1
         r = self.execute_operation(rop.OOISNOT, [null_box, u1_box], 'int')
         assert r.value == 1
-        r = self.execute_operation(rop.OOISNULL, [null_box], 'int')
-        assert r.value == 1
-        r = self.execute_operation(rop.OONONNULL, [null_box], 'int')
-        assert r.value == 0
 
     def test_array_basic(self):
         a_box, A = self.alloc_array_of(lltype.Signed, 342)
@@ -962,10 +962,6 @@
         assert r.value == 1
         r = self.execute_operation(rop.OOISNOT, [BoxInt(v), BoxInt(v)], 'int')
         assert r.value == 0
-        r = self.execute_operation(rop.OOISNULL, [BoxInt(v)], 'int')
-        assert r.value == 0
-        r = self.execute_operation(rop.OONONNULL, [BoxInt(v)], 'int')
-        assert r.value == 1
         lltype.free(x, flavor='raw')
 
     def test_new_plain_struct(self):
@@ -1335,6 +1331,22 @@
                 [value, chr1, chr2])
         assert len(dict.fromkeys([value, chr1, chr2]).keys()) == 3
 
+    def test_guards_nongc(self):
+        x = lltype.malloc(lltype.Struct('x'), flavor='raw')
+        v = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x))
+        vbox = BoxInt(v)
+        ops = [
+            (rop.GUARD_NONNULL, vbox, False),
+            (rop.GUARD_ISNULL, vbox, True),
+            (rop.GUARD_NONNULL, BoxInt(0), True),
+            (rop.GUARD_ISNULL, BoxInt(0), False),
+            ]
+        for opname, arg, res in ops:
+            self.execute_operation(opname, [arg], 'void')
+            assert self.guard_failed == res
+        
+        lltype.free(x, flavor='raw')
+
 class OOtypeBackendTest(BaseBackendTest):
 
     type_system = 'ootype'

Modified: pypy/trunk/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/test/test_random.py	(original)
+++ pypy/trunk/pypy/jit/backend/test/test_random.py	Mon Nov  9 18:20:03 2009
@@ -57,27 +57,18 @@
 
     def get_bool_var(self, r):
         if self.boolvars and r.random() < 0.8:
-            v = r.choice(self.boolvars)
+            return r.choice(self.boolvars)
         elif self.ptrvars and r.random() < 0.4:
             v, S = r.choice(self.ptrvars + self.prebuilt_ptr_consts)[:2]
             v2, S2 = r.choice(self.ptrvars + self.prebuilt_ptr_consts)[:2]
             if S == S2 and not (isinstance(v, ConstPtr) and
                                 isinstance(v2, ConstPtr)):
                 if r.random() < 0.5:
-                    v = self.do(rop.OOIS, [v, v2])
+                    return self.do(rop.OOIS, [v, v2])
                 else:
-                    v = self.do(rop.OOISNOT, [v, v2])
-            else:
-                if isinstance(v, ConstPtr):
-                    v, S = r.choice(self.ptrvars)
-                if r.random() < 0.5:
-                    v = self.do(rop.OONONNULL, [v])
-                else:
-                    v = self.do(rop.OOISNULL, [v])
-        else:
-            v = r.choice(self.intvars)
-            v = self.do(rop.INT_IS_TRUE, [v])
-        return v
+                    return self.do(rop.OOISNOT, [v, v2])
+        v = r.choice(self.intvars)
+        return self.do(rop.INT_IS_TRUE, [v])
 
     def subset_of_intvars(self, r):
         subset = []
@@ -358,6 +349,16 @@
             builder.should_fail_by = op
             builder.guard_op = op
 
+class GuardPtrOperation(GuardOperation):
+    def gen_guard(self, builder, r):
+        if not builder.ptrvars:
+            raise CannotProduceOperation
+        box = r.choice(builder.ptrvars)[0]
+        op = ResOperation(self.opnum, [box], None)
+        passing = ((self.opnum == rop.GUARD_NONNULL and box.value) or
+                   (self.opnum == rop.GUARD_ISNULL and not box.value))
+        return op, passing
+
 class GuardValueOperation(GuardOperation):
     def gen_guard(self, builder, r):
         v = r.choice(builder.intvars)
@@ -410,6 +411,8 @@
 OPERATIONS.append(GuardOperation(rop.GUARD_TRUE))
 OPERATIONS.append(GuardOperation(rop.GUARD_FALSE))
 OPERATIONS.append(GuardOperation(rop.GUARD_FALSE))
+OPERATIONS.append(GuardPtrOperation(rop.GUARD_NONNULL))
+OPERATIONS.append(GuardPtrOperation(rop.GUARD_ISNULL))
 OPERATIONS.append(GuardValueOperation(rop.GUARD_VALUE))
 
 for _op in [rop.INT_NEG,

Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/assembler.py	Mon Nov  9 18:20:03 2009
@@ -466,7 +466,7 @@
             loc2 = cl
         self.mc.SHR(loc, loc2)
 
-    def genop_guard_oononnull(self, op, guard_op, addr, arglocs, resloc):
+    def genop_guard_int_is_true(self, op, guard_op, addr, arglocs, resloc):
         guard_opnum = guard_op.opnum
         loc = arglocs[0]
         self.mc.TEST(loc, loc)
@@ -475,29 +475,11 @@
         else:
             return self.implement_guard(addr, self.mc.JNZ)
 
-    def genop_guard_ooisnull(self, op, guard_op, addr, arglocs, resloc):
-        guard_opnum = guard_op.opnum
-        loc = arglocs[0]
-        self.mc.TEST(loc, loc)
-        if guard_opnum == rop.GUARD_TRUE:
-            return self.implement_guard(addr, self.mc.JNZ)
-        else:
-            return self.implement_guard(addr, self.mc.JZ)
-
-    genop_guard_int_is_true = genop_guard_oononnull
-
-    def genop_oononnull(self, op, arglocs, resloc):
+    def genop_int_is_true(self, op, arglocs, resloc):
         self.mc.CMP(arglocs[0], imm8(0))
         self.mc.MOV(resloc, imm8(0))
         self.mc.SETNE(lower_byte(resloc))
 
-    genop_int_is_true = genop_oononnull
-
-    def genop_ooisnull(self, op, arglocs, resloc):
-        self.mc.CMP(arglocs[0], imm8(0))
-        self.mc.MOV(resloc, imm8(0))
-        self.mc.SETE(lower_byte(resloc))
-
     def genop_same_as(self, op, arglocs, resloc):
         self.mov(arglocs[0], resloc)
     genop_cast_ptr_to_int = genop_same_as
@@ -672,6 +654,7 @@
         loc = locs[0]
         self.mc.TEST(loc, loc)
         return self.implement_guard(addr, self.mc.JZ)
+    genop_guard_guard_nonnull = genop_guard_guard_true
 
     def genop_guard_guard_no_exception(self, ign_1, guard_op, addr,
                                        locs, ign_2):
@@ -703,6 +686,7 @@
         loc = locs[0]
         self.mc.TEST(loc, loc)
         return self.implement_guard(addr, self.mc.JNZ)
+    genop_guard_guard_isnull = genop_guard_guard_false
 
     def genop_guard_guard_value(self, ign_1, guard_op, addr, locs, ign_2):
         if guard_op.args[0].type == FLOAT:

Modified: pypy/trunk/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/regalloc.py	Mon Nov  9 18:20:03 2009
@@ -305,8 +305,7 @@
         self.assembler.regalloc_perform_discard(op, arglocs)
 
     def can_optimize_cmp_op(self, op, i, operations):
-        if not (op.is_comparison() or op.opnum == rop.OOISNULL or
-                op.opnum == rop.OONONNULL):
+        if not op.is_comparison():
             return False
         if (operations[i + 1].opnum != rop.GUARD_TRUE and
             operations[i + 1].opnum != rop.GUARD_FALSE):
@@ -385,6 +384,8 @@
 
     consider_guard_true = _consider_guard
     consider_guard_false = _consider_guard
+    consider_guard_nonnull = _consider_guard
+    consider_guard_isnull = _consider_guard
 
     def consider_finish(self, op, ignored):
         locs = [self.loc(v) for v in op.args]
@@ -831,8 +832,6 @@
             self.Perform(op, [argloc], resloc)
 
     consider_int_is_true = _consider_nullity
-    consider_ooisnull = _consider_nullity
-    consider_oononnull = _consider_nullity
 
     def consider_same_as(self, op, ignored):
         argloc = self.loc(op.args[0])

Modified: pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py	Mon Nov  9 18:20:03 2009
@@ -132,11 +132,9 @@
         guard_value(i2, 1) [i2, i3, i4, i5, i6, i7, i0, i1, i8]
         guard_class(i4, 138998336) [i4, i5, i6, i7, i0, i1, i8]
         i11 = getfield_gc(i4, descr=descr0)
-        i12 = ooisnull(i11)
-        guard_false(i12) [i4, i5, i6, i7, i0, i1, i11, i8]
+        guard_nonnull(i11) [i4, i5, i6, i7, i0, i1, i11, i8]
         i13 = getfield_gc(i11, descr=descr0)
-        i14 = ooisnull(i13)
-        guard_true(i14) [i4, i5, i6, i7, i0, i1, i11, i8]
+        guard_isnull(i13) [i4, i5, i6, i7, i0, i1, i11, i8]
         i15 = getfield_gc(i4, descr=descr0)
         i17 = int_lt(i15, 0)
         guard_false(i17) [i4, i5, i6, i7, i0, i1, i11, i15, i8]

Modified: pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_regalloc.py	Mon Nov  9 18:20:03 2009
@@ -437,20 +437,6 @@
         self.interpret(ops, [0, 1, 2, 3, 4, 5, 6])
         assert self.getints(6) == [1, 1, 0, 0, 1, 1]
 
-    def test_nullity(self):
-        ops = '''
-        [i0, i1, i2, i3, i4, i5, i6]
-        i10 = oononnull(i0)
-        i11 = ooisnull(i1)
-        i12 = oononnull(i2)
-        i13 = oononnull(i3)
-        i14 = ooisnull(i6)
-        i15 = ooisnull(i5)
-        finish(i10, i11, i12, i13, i14, i15)
-        '''
-        self.interpret(ops, [0, 1, 2, 3, 4, 5, 6])
-        assert self.getints(6) == [0, 0, 1, 1, 0, 0]
-
     def test_strsetitem(self):
         ops = '''
         [p0, i]

Modified: pypy/trunk/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_runner.py	Mon Nov  9 18:20:03 2009
@@ -229,7 +229,7 @@
         assert c.value == 3
 
     def test_nullity_with_guard(self):
-        allops = [rop.OONONNULL, rop.OOISNULL, rop.INT_IS_TRUE]
+        allops = [rop.INT_IS_TRUE]
         guards = [rop.GUARD_TRUE, rop.GUARD_FALSE]
         p = lltype.cast_opaque_ptr(llmemory.GCREF,
                                    lltype.malloc(lltype.GcStruct('x')))

Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/codewriter.py	Mon Nov  9 18:20:03 2009
@@ -808,6 +808,31 @@
 
     serialize_op_uint_is_true = serialize_op_int_is_true
 
+    def _serialize_op_ptr_eq(self, op, opname):
+        arg0, arg1 = op.args
+        if isinstance(arg0, Constant) and not arg0.value:
+            self.emit(opname, self.var_position(arg1))
+            self.register_var(op.result)
+        elif isinstance(arg1, Constant) and not arg1.value:
+            self.emit(opname, self.var_position(arg0))
+            self.register_var(op.result)
+        else:
+            self.default_serialize_op(op)
+
+    def serialize_op_ptr_eq(self, op):
+        self._serialize_op_ptr_eq(op, 'ooisnull')
+    serialize_op_oois = serialize_op_ptr_eq
+
+    def serialize_op_ptr_ne(self, op):
+        self._serialize_op_ptr_eq(op, 'oononnull')
+    serialize_op_ooisnot = serialize_op_ptr_ne
+
+    def serialize_op_ptr_iszero(self, op):
+        self.default_serialize_op(op, 'ooisnull')
+
+    def serialize_op_ptr_nonzero(self, op):
+        self.default_serialize_op(op, 'oononnull')
+
     def serialize_op_malloc(self, op):
         assert op.args[1].value == {'flavor': 'gc'}
         STRUCT = op.args[0].value

Modified: pypy/trunk/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/executor.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/executor.py	Mon Nov  9 18:20:03 2009
@@ -103,26 +103,6 @@
 def do_same_as(cpu, box1):
     return box1
 
-def do_oononnull(cpu, box1):
-    tp = box1.type
-    if tp == INT:
-        x = bool(box1.getint())
-    elif tp == REF:
-        x = bool(box1.getref_base())
-    else:
-        assert False
-    return ConstInt(x)
-
-def do_ooisnull(cpu, box1):
-    tp = box1.type
-    if tp == INT:
-        x = bool(box1.getint())
-    elif tp == REF:
-        x = bool(box1.getref_base())
-    else:
-        assert False
-    return ConstInt(not x)
-
 def do_oois(cpu, box1, box2):
     tp = box1.type
     assert tp == box2.type

Modified: pypy/trunk/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/history.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/history.py	Mon Nov  9 18:20:03 2009
@@ -106,6 +106,9 @@
     def set_future_value(self, cpu, j):
         raise NotImplementedError
 
+    def nonnull(self):
+        raise NotImplementedError
+
     def repr_rpython(self):
         return '%s' % self
 
@@ -177,9 +180,6 @@
     def same_constant(self, other):
         raise NotImplementedError
 
-    def nonnull_constant(self):
-        raise NotImplementedError
-
     def __repr__(self):
         return 'Const(%s)' % self._getrepr_()
 
@@ -239,7 +239,7 @@
         assert isinstance(other, Const)
         return self.value == other.getint()
 
-    def nonnull_constant(self):
+    def nonnull(self):
         return self.value != 0
 
     def _getrepr_(self):
@@ -286,7 +286,7 @@
         assert isinstance(other, Const)
         return self.value == other.getaddr(self.cpu)
 
-    def nonnull_constant(self):
+    def nonnull(self):
         return bool(self.value)
 
     def _getrepr_(self):
@@ -322,7 +322,7 @@
         assert isinstance(other, ConstFloat)
         return self.value == other.value
 
-    def nonnull_constant(self):
+    def nonnull(self):
         return self.value != 0.0
 
     def _getrepr_(self):
@@ -368,7 +368,7 @@
         assert isinstance(other, ConstPtr)
         return self.value == other.value
 
-    def nonnull_constant(self):
+    def nonnull(self):
         return bool(self.value)
 
     _getrepr_ = repr_pointer
@@ -421,7 +421,7 @@
         assert isinstance(other, ConstObj)
         return self.value == other.value
 
-    def nonnull_constant(self):
+    def nonnull(self):
         return bool(self.value)
 
     _getrepr_ = repr_object
@@ -512,6 +512,9 @@
     def set_future_value(self, cpu, j):
         cpu.set_future_value_int(j, self.value)
 
+    def nonnull(self):
+        return self.value != 0
+
     def _getrepr_(self):
         return self.value
 
@@ -541,6 +544,9 @@
     def set_future_value(self, cpu, j):
         cpu.set_future_value_float(j, self.value)
 
+    def nonnull(self):
+        return self.value != 0.0
+
     def _getrepr_(self):
         return self.value
 
@@ -580,6 +586,9 @@
     def set_future_value(self, cpu, j):
         cpu.set_future_value_ref(j, self.value)
 
+    def nonnull(self):
+        return bool(self.value)
+
     def repr_rpython(self):
         return repr_rpython(self, 'bp')
 
@@ -615,6 +624,9 @@
         else:
             return 0
 
+    def nonnull(self):
+        return bool(self.value)
+
     def set_future_value(self, cpu, j):
         cpu.set_future_value_ref(j, self.value)
 

Modified: pypy/trunk/pypy/jit/metainterp/optimizefindnode.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizefindnode.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizefindnode.py	Mon Nov  9 18:20:03 2009
@@ -168,11 +168,11 @@
     def find_nodes_no_escape(self, op):
         pass    # for operations that don't escape their arguments
 
-    find_nodes_OONONNULL   = find_nodes_no_escape
-    find_nodes_OOISNULL    = find_nodes_no_escape
-    find_nodes_OOIS        = find_nodes_no_escape
-    find_nodes_OOISNOT     = find_nodes_no_escape
-    find_nodes_INSTANCEOF  = find_nodes_no_escape
+    find_nodes_OOIS          = find_nodes_no_escape
+    find_nodes_OOISNOT       = find_nodes_no_escape
+    find_nodes_INSTANCEOF    = find_nodes_no_escape
+    find_nodes_GUARD_NONNULL = find_nodes_no_escape
+    find_nodes_GUARD_ISNULL  = find_nodes_no_escape
 
     def find_nodes_NEW_WITH_VTABLE(self, op):
         instnode = InstanceNode()

Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py	Mon Nov  9 18:20:03 2009
@@ -69,7 +69,7 @@
         if self.is_constant():
             box = self.box
             assert isinstance(box, Const)
-            return not box.nonnull_constant()
+            return not box.nonnull()
         return False
 
     def make_constant(self, constbox):
@@ -100,7 +100,7 @@
         elif level == LEVEL_CONSTANT:
             box = self.box
             assert isinstance(box, Const)
-            return box.nonnull_constant()
+            return box.nonnull()
         else:
             return False
 
@@ -114,25 +114,6 @@
         # meaning it has been forced.
         return self.box is None
 
-class BoolValue(OptValue):
-
-    def __init__(self, box, fromvalue, reversed, nullconstbox):
-        OptValue.__init__(self, box)
-        # If later 'box' is turned into a constant False
-        # (resp. True), then 'fromvalue' will be known to
-        # be null (resp. non-null).  If 'reversed', then
-        # this logic is reversed.
-        self.fromvalue = fromvalue
-        self.reversed = reversed
-        self.nullconstbox = nullconstbox   # of the correct type
-
-    def make_constant(self, constbox):
-        OptValue.make_constant(self, constbox)
-        if constbox.nonnull_constant() ^ self.reversed:
-            self.fromvalue.make_nonnull()
-        else:
-            self.fromvalue.make_constant(self.nullconstbox)
-
 class ConstantValue(OptValue):
     level = LEVEL_CONSTANT
 
@@ -434,11 +415,6 @@
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_bool(self, box, fromvalue, reversed, nullconstbox):
-        value = BoolValue(box, fromvalue, reversed, nullconstbox)
-        self.make_equal_to(box, value)
-        return value
-
     def new_ptr_box(self):
         return self.cpu.ts.BoxRef()
 
@@ -585,6 +561,24 @@
             self.emit_operation(op)
         value.make_constant(constbox)
 
+    def optimize_GUARD_ISNULL(self, op):
+        value = self.getvalue(op.args[0])
+        if value.is_null():
+            return
+        elif value.is_nonnull():
+            raise InvalidLoop
+        self.emit_operation(op)
+        value.make_constant(self.cpu.ts.CONST_NULL)
+
+    def optimize_GUARD_NONNULL(self, op):
+        value = self.getvalue(op.args[0])
+        if value.is_nonnull():
+            return
+        elif value.is_null():
+            raise InvalidLoop
+        self.emit_operation(op)
+        value.make_nonnull()
+
     def optimize_GUARD_VALUE(self, op):
         value = self.getvalue(op.args[0])
         emit_operation = True
@@ -631,26 +625,19 @@
         self.emit_operation(op)
 
 
-    def _optimize_nullness(self, op, expect_nonnull, nullconstbox):
-        value = self.getvalue(op.args[0])
+    def _optimize_nullness(self, op, box, expect_nonnull):
+        value = self.getvalue(box)
         if value.is_nonnull():
             self.make_constant_int(op.result, expect_nonnull)
         elif value.is_null():
             self.make_constant_int(op.result, not expect_nonnull)
         else:
-            self.make_bool(op.result, value, not expect_nonnull, nullconstbox)
             self.emit_operation(op)
 
-    def optimize_OONONNULL(self, op):
-        self._optimize_nullness(op, True, self.cpu.ts.CONST_NULL)
-
-    def optimize_OOISNULL(self, op):
-        self._optimize_nullness(op, False, self.cpu.ts.CONST_NULL)
-
     def optimize_INT_IS_TRUE(self, op):
-        self._optimize_nullness(op, True, CONST_0)
+        self._optimize_nullness(op, op.args[0], True)
 
-    def _optimize_oois_ooisnot(self, op, expect_isnot, unary_opnum):
+    def _optimize_oois_ooisnot(self, op, expect_isnot):
         value0 = self.getvalue(op.args[0])
         value1 = self.getvalue(op.args[1])
         if value0.is_virtual():
@@ -662,19 +649,17 @@
         elif value1.is_virtual():
             self.make_constant_int(op.result, expect_isnot)
         elif value1.is_null():
-            op = ResOperation(unary_opnum, [op.args[0]], op.result)
-            self._optimize_nullness(op, expect_isnot, self.cpu.ts.CONST_NULL)
+            self._optimize_nullness(op, op.args[0], expect_isnot)
         elif value0.is_null():
-            op = ResOperation(unary_opnum, [op.args[1]], op.result)
-            self._optimize_nullness(op, expect_isnot, self.cpu.ts.CONST_NULL)
+            self._optimize_nullness(op, op.args[1], expect_isnot)
         else:
             self.optimize_default(op)
 
     def optimize_OOISNOT(self, op):
-        self._optimize_oois_ooisnot(op, True, rop.OONONNULL)
+        self._optimize_oois_ooisnot(op, True)
 
     def optimize_OOIS(self, op):
-        self._optimize_oois_ooisnot(op, False, rop.OOISNULL)
+        self._optimize_oois_ooisnot(op, False)
 
     def optimize_GETFIELD_GC(self, op):
         value = self.getvalue(op.args[0])

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Mon Nov  9 18:20:03 2009
@@ -281,6 +281,25 @@
         target = self.load_3byte()  # load the 'target' argument
         self.pc = target      # jump
 
+    def ignore_next_guard_nullness(self, opnum):
+        _op_ooisnull = self.metainterp.staticdata._op_ooisnull
+        _op_oononnull = self.metainterp.staticdata._op_oononnull
+        bc = ord(self.bytecode[self.pc])
+        if bc == _op_ooisnull:
+            if opnum == rop.GUARD_ISNULL:
+                res = ConstInt(0)
+            else:
+                res = ConstInt(1)
+        else:
+            assert bc == _op_oononnull
+            if opnum == rop.GUARD_ISNULL:
+                res = ConstInt(1)
+            else:
+                res = ConstInt(0)
+        self.pc += 1    # past the bytecode for ptr_iszero/ptr_nonzero
+        self.load_int() # past the 'box' argument
+        self.make_result_box(res)
+
     def dont_follow_jump(self):
         _op_goto_if_not = self.metainterp.staticdata._op_goto_if_not
         assert ord(self.bytecode[self.pc]) == _op_goto_if_not
@@ -445,16 +464,29 @@
         else:
             self.execute(rop.INT_NEG, box)
 
-    @arguments("box")
-    def opimpl_ptr_nonzero(self, box):
-        self.execute(rop.OONONNULL, box)
-
-    @arguments("box")
-    def opimpl_ptr_iszero(self, box):
-        self.execute(rop.OOISNULL, box)
+    @arguments("orgpc", "box")
+    def opimpl_oononnull(self, pc, box):
+        value = box.nonnull()
+        if value:
+            opnum = rop.GUARD_NONNULL
+            res = ConstInt(1)
+        else:
+            opnum = rop.GUARD_ISNULL
+            res = ConstInt(0)
+        self.generate_guard(pc, opnum, box, [])
+        self.make_result_box(res)
 
-    opimpl_oononnull = opimpl_ptr_nonzero
-    opimpl_ooisnull = opimpl_ptr_iszero
+    @arguments("orgpc", "box")
+    def opimpl_ooisnull(self, pc, box):
+        value = box.nonnull()
+        if value:
+            opnum = rop.GUARD_NONNULL
+            res = ConstInt(0)
+        else:
+            opnum = rop.GUARD_ISNULL
+            res = ConstInt(1)
+        self.generate_guard(pc, opnum, box, [])
+        self.make_result_box(res)
 
     @arguments("box", "box")
     def opimpl_ptr_eq(self, box1, box2):
@@ -981,6 +1013,8 @@
 
         self.warmrunnerdesc = warmrunnerdesc
         self._op_goto_if_not = self.find_opcode('goto_if_not')
+        self._op_ooisnull    = self.find_opcode('ooisnull')
+        self._op_oononnull   = self.find_opcode('oononnull')
 
         backendmodule = self.cpu.__module__
         backendmodule = backendmodule.split('.')[-2]
@@ -1527,6 +1561,8 @@
             self.handle_exception()
         elif opnum == rop.GUARD_NO_OVERFLOW:   # an overflow now detected
             self.raise_overflow_error()
+        elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL:
+            self.framestack[-1].ignore_next_guard_nullness(opnum)
 
     def compile(self, original_boxes, live_arg_boxes, start):
         num_green_args = self.staticdata.num_green_args

Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/resoperation.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/resoperation.py	Mon Nov  9 18:20:03 2009
@@ -1,7 +1,6 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import make_sure_not_resized
 
-
 class ResOperation(object):
     """The central ResOperation class, representing one operation."""
 
@@ -118,6 +117,8 @@
     'GUARD_FALSE',
     'GUARD_VALUE',
     'GUARD_CLASS',
+    'GUARD_NONNULL',
+    'GUARD_ISNULL',
     '_GUARD_FOLDABLE_LAST',
     'GUARD_NO_EXCEPTION',
     'GUARD_EXCEPTION',
@@ -178,8 +179,6 @@
     #
     'SAME_AS/1',      # gets a Const or a Box, turns it into another Box
     #
-    'OONONNULL/1b',
-    'OOISNULL/1b',
     'OOIS/2b',
     'OOISNOT/2b',
     #

Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py	Mon Nov  9 18:20:03 2009
@@ -1180,8 +1180,24 @@
             history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))).value
         assert res == expected
 
+    def test_collapsing_ptr_eq(self):
+        S = lltype.GcStruct('S')
+        p = lltype.malloc(S)
+        driver = JitDriver(greens = [], reds = ['n', 'x'])
 
+        def f(n, x):
+            while n > 0:
+                driver.can_enter_jit(n=n, x=x)
+                driver.jit_merge_point(n=n, x=x)
+                if x:
+                    n -= 1
+                n -= 1
 
+        def main():
+            f(10, p)
+            f(10, lltype.nullptr(S))
+
+        self.meta_interp(main, [])
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     pass

Modified: pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	Mon Nov  9 18:20:03 2009
@@ -341,6 +341,30 @@
                 assert 0, "missing instantiate_*_%s in:\n%r" % (expected,
                                                                 names)
 
+    def test_oois_constant_null(self):
+        from pypy.rpython.lltypesystem import lltype
+        
+        S = lltype.GcStruct('S')
+        s = lltype.malloc(S)
+        NULL = lltype.nullptr(S)
+        def f(p, i):
+            if i % 2:
+                return p == NULL
+            elif i % 3:
+                return NULL == p
+            elif i % 4:
+                return p != NULL
+            else:
+                return NULL != p
+        graphs = self.make_graphs(f, [s, 5])
+        cw = CodeWriter(self.rtyper)
+        cw.candidate_graphs = graphs
+        cw._start(self.metainterp_sd, None)        
+        jitcode = cw.make_one_bytecode((graphs[0], None), False)
+        assert 'ptr_eq' not in jitcode._source
+        assert 'ptr_ne' not in jitcode._source
+        assert jitcode._source.count('ptr_iszero') == 2
+        assert jitcode._source.count('ptr_nonzero') == 2
 
 class ImmutableFieldsTests:
 

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py	Mon Nov  9 18:20:03 2009
@@ -474,10 +474,7 @@
         [p3, p4, p2]
         p0 = new_with_vtable(ConstClass(node_vtable))
         p1 = new_with_vtable(ConstClass(node_vtable))
-        i1 = oononnull(p0)
-        guard_true(i1) []
-        i2 = ooisnull(p0)
-        guard_false(i2) []
+        guard_nonnull(p0) []
         i3 = ooisnot(p0, NULL)
         guard_true(i3) []
         i4 = oois(p0, NULL)
@@ -827,14 +824,12 @@
     def test_find_nodes_bug_1(self):
         ops = """
         [p12]
-        i16 = ooisnull(p12)
-        guard_false(i16) []
+        guard_nonnull(p12) []
         guard_class(p12, ConstClass(node_vtable)) []
         guard_class(p12, ConstClass(node_vtable)) []
         i22 = getfield_gc_pure(p12, descr=valuedescr)
         escape(i22)
-        i25 = ooisnull(p12)
-        guard_false(i25) []
+        guard_nonnull(p12) []
         guard_class(p12, ConstClass(node_vtable)) []
         guard_class(p12, ConstClass(node_vtable)) []
         i29 = getfield_gc_pure(p12, descr=valuedescr)
@@ -847,10 +842,8 @@
         setarrayitem_gc(p35, 0, p33, descr=arraydescr3)
         p38 = new_with_vtable(ConstClass(u_vtable))         # U
         setfield_gc(p38, p35, descr=onedescr)
-        i39 = ooisnull(p38)
-        guard_false(i39) []
-        i40 = oononnull(p38)
-        guard_true(i40) []
+        guard_nonnull(p38) []
+        guard_nonnull(p38) []
         guard_class(p38, ConstClass(u_vtable)) []
         p42 = getfield_gc(p38, descr=onedescr)              # Array(NODE)
         i43 = arraylen_gc(p42, descr=arraydescr3)
@@ -871,8 +864,7 @@
         guard_false(i55) []
         p56 = getfield_gc(p46, descr=ddescr)                # Array(NODE)
         p58 = getarrayitem_gc(p56, 0, descr=arraydescr3)    # NODE
-        i59 = ooisnull(p38)
-        guard_false(i59) []
+        guard_nonnull(p38) []
         jump(p58)
         """
         self.find_nodes(ops, 'Virtual(node_vtable, valuedescr=Not)')

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	Mon Nov  9 18:20:03 2009
@@ -338,10 +338,7 @@
         ops = """
         [p0]
         guard_class(p0, ConstClass(node_vtable)) []
-        i0 = oononnull(p0)
-        guard_true(i0) []
-        i1 = ooisnull(p0)
-        guard_false(i1) []
+        guard_nonnull(p0) []
         jump(p0)
         """
         expected = """
@@ -352,6 +349,7 @@
         self.optimize_loop(ops, 'Not', expected)
 
     def test_int_is_true_1(self):
+        py.test.skip("too bad")
         ops = """
         [i0]
         i1 = int_is_true(i0)
@@ -371,31 +369,13 @@
     def test_ooisnull_oononnull_2(self):
         ops = """
         [p0]
-        i0 = oononnull(p0)         # p0 != NULL
-        guard_true(i0) []
-        i1 = ooisnull(p0)
-        guard_false(i1) []
-        jump(p0)
-        """
-        expected = """
-        [p0]
-        i0 = oononnull(p0)
-        guard_true(i0) []
-        jump(p0)
-        """
-        self.optimize_loop(ops, 'Not', expected)
-        ops = """
-        [p0]
-        i1 = ooisnull(p0)
-        guard_false(i1) []
-        i0 = oononnull(p0)         # p0 != NULL
-        guard_true(i0) []
+        guard_nonnull(p0) []
+        guard_nonnull(p0) []
         jump(p0)
         """
         expected = """
         [p0]
-        i1 = ooisnull(p0)
-        guard_false(i1) []
+        guard_nonnull(p0) []
         jump(p0)
         """
         self.optimize_loop(ops, 'Not', expected)
@@ -404,34 +384,14 @@
         ops = """
         []
         p0 = escape()
-        i0 = ooisnull(p0)
-        guard_true(i0) []
-        i1 = oononnull(p0)
-        guard_false(i1) []
-        jump()
-        """
-        expected = """
-        []
-        p0 = escape()
-        i0 = ooisnull(p0)
-        guard_true(i0) []
-        jump()
-        """
-        self.optimize_loop(ops, '', expected)
-        ops = """
-        []
-        p0 = escape()
-        i0 = oononnull(p0)
-        guard_false(i0) []
-        i1 = ooisnull(p0)
-        guard_true(i1) []
+        guard_isnull(p0) []
+        guard_isnull(p0) []
         jump()
         """
         expected = """
         []
         p0 = escape()
-        i0 = oononnull(p0)
-        guard_false(i0) []
+        guard_isnull(p0) []
         jump()
         """
         self.optimize_loop(ops, '', expected)
@@ -441,17 +401,14 @@
         [p0]
         pv = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(pv, p0, descr=valuedescr)
-        i0 = oononnull(p0)         # p0 != NULL
-        guard_true(i0) []
+        guard_nonnull(p0) []
         p1 = getfield_gc(pv, descr=valuedescr)
-        i1 = ooisnull(p1)
-        guard_false(i1) []
+        guard_nonnull(p1) []
         jump(p0)
         """
         expected = """
         [p0]
-        i0 = oononnull(p0)
-        guard_true(i0) []
+        guard_nonnull(p0) []
         jump(p0)
         """
         self.optimize_loop(ops, 'Not', expected)
@@ -489,10 +446,7 @@
         guard_true(i0) []
         i3 = oois(NULL, p0)
         guard_false(i1) []
-        i4 = oononnull(p0)
-        guard_true(i4) []
-        i5 = ooisnull(p0)
-        guard_false(i5) []
+        guard_nonnull(p0) []
         jump(p0)
         """
         expected = """
@@ -541,16 +495,16 @@
 
     def test_guard_value_to_guard_false(self):
         ops = """
-        [p]
-        i1 = ooisnull(p)
-        guard_value(i1, 0) [p]
-        jump(p)
+        [i]
+        i1 = int_is_true(i)
+        guard_value(i1, 0) [i]
+        jump(i)
         """
         expected = """
-        [p]
-        i1 = ooisnull(p)
-        guard_false(i1) [p]
-        jump(p)
+        [i]
+        i1 = int_is_true(i)
+        guard_false(i1) [i]
+        jump(i)
         """
         self.optimize_loop(ops, 'Not', expected)
 
@@ -686,10 +640,7 @@
     def test_virtual_oois(self):
         ops = """
         [p0, p1, p2]
-        i1 = oononnull(p0)
-        guard_true(i1) []
-        i2 = ooisnull(p0)
-        guard_false(i2) []
+        guard_nonnull(p0) []
         i3 = ooisnot(p0, NULL)
         guard_true(i3) []
         i4 = oois(p0, NULL)
@@ -727,8 +678,7 @@
         # the details of the algorithm...
         expected2 = """
         [p0, p1, p2]
-        i1 = oononnull(p0)
-        guard_true(i1) []
+        guard_nonnull(p0) []
         i7 = ooisnot(p0, p1)
         guard_true(i7) []
         i8 = oois(p0, p1)
@@ -833,7 +783,7 @@
         p0 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p0, NULL, descr=nextdescr)
         p2 = getfield_gc(p0, descr=nextdescr)
-        i1 = ooisnull(p2)
+        i1 = oois(p2, NULL)
         jump(i1)
         """
         expected = """
@@ -849,7 +799,7 @@
         p0 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p0, ConstPtr(myptr), descr=nextdescr)
         p2 = getfield_gc(p0, descr=nextdescr)
-        i1 = ooisnull(p2)
+        i1 = oois(p2, NULL)
         jump(i1)
         """
         expected = """
@@ -1003,8 +953,7 @@
         ops = """
         [i1, p0]
         setarrayitem_gc(p0, 0, i1, descr=arraydescr)
-        i2 = ooisnull(p0)
-        guard_false(i2) []
+        guard_nonnull(p0) []
         p1 = new_array(i1, descr=arraydescr)
         jump(i1, p1)
         """
@@ -1426,8 +1375,7 @@
         ops = """
         [i0, p1]
         p4 = getfield_gc(p1, descr=nextdescr)
-        i2 = ooisnull(p4)
-        guard_false(i2) []
+        guard_nonnull(p4) []
         escape(p4)
         #
         p2 = new_with_vtable(ConstClass(node_vtable))
@@ -1437,8 +1385,7 @@
         """
         expected = """
         [i0, p4]
-        i2 = ooisnull(p4)
-        guard_false(i2) []
+        guard_nonnull(p4) []
         escape(p4)
         #
         p3 = escape()
@@ -1451,8 +1398,7 @@
         ops = """
         [i0, p1]
         p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
-        i2 = ooisnull(p4)
-        guard_false(i2) []
+        guard_nonnull(p4) []
         escape(p4)
         #
         p2 = new_array(1, descr=arraydescr2)
@@ -1462,8 +1408,7 @@
         """
         expected = """
         [i0, p4]
-        i2 = ooisnull(p4)
-        guard_false(i2) []
+        guard_nonnull(p4) []
         escape(p4)
         #
         p3 = escape()
@@ -1475,8 +1420,7 @@
     def test_invalid_loop_1(self):
         ops = """
         [p1]
-        i1 = ooisnull(p1)
-        guard_true(i1) []
+        guard_isnull(p1) []
         #
         p2 = new_with_vtable(ConstClass(node_vtable))
         jump(p2)
@@ -1501,8 +1445,7 @@
         ops = """
         [p1]
         p2 = getfield_gc(p1, descr=nextdescr)
-        i1 = ooisnull(p2)
-        guard_true(i1) []
+        guard_isnull(p2) []
         #
         p3 = new_with_vtable(ConstClass(node_vtable))
         p4 = new_with_vtable(ConstClass(node_vtable))

Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	Mon Nov  9 18:20:03 2009
@@ -158,8 +158,7 @@
         ops = self.get_by_bytecode("LOAD_GLOBAL")
         assert len(ops) == 2
         assert ops[0].get_opnames() == ["getfield_gc", "getarrayitem_gc",
-                                        "getfield_gc", "ooisnull",
-                                        "guard_false"]
+                                        "getfield_gc", "guard_nonnull"]
         assert not ops[1] # second LOAD_GLOBAL folded away
         ops = self.get_by_bytecode("CALL_FUNCTION")
         assert len(ops) == 2
@@ -203,7 +202,7 @@
         ops = self.get_by_bytecode("LOAD_ATTR")
         assert len(ops) == 2
         assert ops[0].get_opnames() == ["getfield_gc", "getarrayitem_gc",
-                                        "ooisnull", "guard_false"]
+                                        "guard_nonnull"]
         assert not ops[1] # second LOAD_ATTR folded away
 
     def test_default_and_kw(self):



More information about the Pypy-commit mailing list