[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