[pypy-svn] r40547 - in pypy/branch/jit-virtual-world/pypy/jit/codegen: i386 llgraph/test test
arigo at codespeak.net
arigo at codespeak.net
Thu Mar 15 17:18:02 CET 2007
Author: arigo
Date: Thu Mar 15 17:18:00 2007
New Revision: 40547
Modified:
pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/operation.py
pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/regalloc.py
pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/rgenop.py
pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/test/test_rgenop.py
pypy/branch/jit-virtual-world/pypy/jit/codegen/test/operation_tests.py
pypy/branch/jit-virtual-world/pypy/jit/codegen/test/rgenop_tests.py
Log:
(arigo, pedronis, arre) Support for some of the _ovf operations in the 386 backend.
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/operation.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/operation.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/operation.py Thu Mar 15 17:18:00 2007
@@ -50,8 +50,9 @@
self.emit(allocator.mc, dstop)
class OpIntNeg(UnaryOp):
- opname = 'int_neg'
+ opname = 'int_neg', 'int_neg_ovf'
emit = staticmethod(I386CodeBuilder.NEG)
+ ccexcflag = Conditions['O']
class OpIntInvert(UnaryOp):
opname = 'int_invert', 'uint_invert'
@@ -76,6 +77,14 @@
mc.XOR(dstop, tmpop)
allocator.end_clobber(tmpop)
+class OpIntAbsOvf(OpIntAbs):
+ opname = 'int_abs_ovf'
+ ccexcflag = Conditions['E']
+ def generate(self, allocator):
+ OpIntAbs.generate(self, allocator)
+ mc = allocator.mc
+ mc.CMP(allocator.var2loc[self], imm(-sys.maxint-1))
+
class OpSameAs(Op1):
clobbers_cc = False # special handling of the cc
side_effects = False
@@ -134,6 +143,17 @@
suggested_cc = Conditions['E']
inverted = True
+class OpFetchCC(Operation):
+ clobbers_cc = False
+ side_effects = False
+ def __init__(self, cc):
+ self.cc = cc
+ def mark_used_vars(self, allocator):
+ pass
+ def generate(self, allocator):
+ ccop = ccflags[self.cc]
+ allocator.create_in_cc(self, ccop)
+
class Op2(Operation):
def __init__(self, x, y):
self.x = x
@@ -185,13 +205,15 @@
self.emit(allocator.mc, dstop, op2)
class OpIntAdd(BinaryOp):
- opname = 'int_add', 'uint_add'
+ opname = 'int_add', 'uint_add', 'int_add_ovf'
emit = staticmethod(I386CodeBuilder.ADD)
commutative = True
+ ccexcflag = Conditions['O']
class OpIntSub(BinaryOp):
- opname = 'int_sub', 'uint_sub'
+ opname = 'int_sub', 'uint_sub', 'int_sub_ovf'
emit = staticmethod(I386CodeBuilder.SUB)
+ ccexcflag = Conditions['O']
class OpIntAnd(BinaryOp):
opname = 'int_and', 'uint_and'
@@ -206,8 +228,9 @@
emit = staticmethod(I386CodeBuilder.XOR)
class OpIntMul(Op2):
- opname = 'int_mul'
+ opname = 'int_mul', 'int_mul_ovf'
side_effects = False
+ ccexcflag = Conditions['O']
def generate(self, allocator):
op1 = allocator.get_operand(self.x)
@@ -939,6 +962,15 @@
return self.cond
+def load_into_cc_o(mc, srcop):
+ mc.MOV(ecx, srcop)
+ mc.ADD(ecx, imm(sys.maxint))
+
+def load_into_cc_no(self, srcop):
+ mc.MOV(ecx, imm(-sys.maxint-1))
+ mc.ADD(ecx, srcop)
+ mc.DEC(ecx)
+
def load_into_cc_lt(mc, srcop):
mc.XOR(ecx, ecx)
mc.CMP(ecx, srcop)
@@ -956,6 +988,9 @@
load_into_cc_gt = load_into_cc_ne
load_into_cc_ge = load_into_cc_eq
+ccflag_o = CCFLAG('O', load_into_cc_o)
+ccflag_no = CCFLAG('O', load_into_cc_no)
+
ccflag_lt = CCFLAG('L', load_into_cc_lt)
ccflag_le = CCFLAG('LE', load_into_cc_le)
ccflag_eq = CCFLAG('E', load_into_cc_eq)
@@ -969,6 +1004,8 @@
ccflag_uge = CCFLAG('AE', load_into_cc_ge)
ccflags = [None] * 16
+ccflags[Conditions['O']] = ccflag_o
+ccflags[Conditions['NO']] = ccflag_no
ccflags[Conditions['L']] = ccflag_lt
ccflags[Conditions['LE']] = ccflag_le
ccflags[Conditions['E']] = ccflag_eq
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/regalloc.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/regalloc.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/regalloc.py Thu Mar 15 17:18:00 2007
@@ -302,6 +302,7 @@
def _created(self, v, loc):
assert v not in self.var2loc
+ assert loc is not None
self.vars_in_use[v] = ltime = self.lifetime[v]
assert ltime > self.operationindex
self.var2loc[v] = loc
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/rgenop.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/i386/rgenop.py Thu Mar 15 17:18:00 2007
@@ -371,12 +371,30 @@
return op
@specialize.arg(1)
+ def genraisingop1(self, opname, gv_arg):
+ cls = getopclass1(opname)
+ op = cls(gv_arg)
+ self.operations.append(op)
+ op_excflag = OpFetchCC(op.ccexcflag)
+ self.operations.append(op_excflag)
+ return op, op_excflag
+
+ @specialize.arg(1)
def genop2(self, opname, gv_arg1, gv_arg2):
cls = getopclass2(opname)
op = cls(gv_arg1, gv_arg2)
self.operations.append(op)
return op
+ @specialize.arg(1)
+ def genraisingop2(self, opname, gv_arg1, gv_arg2):
+ cls = getopclass2(opname)
+ op = cls(gv_arg1, gv_arg2)
+ self.operations.append(op)
+ op_excflag = OpFetchCC(op.ccexcflag)
+ self.operations.append(op_excflag)
+ return op, op_excflag
+
def genop_ptr_iszero(self, kind, gv_ptr):
cls = getopclass1('ptr_iszero')
op = cls(gv_ptr)
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/test/test_rgenop.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/test/test_rgenop.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/test/test_rgenop.py Thu Mar 15 17:18:00 2007
@@ -9,6 +9,10 @@
class TestLLGraphRGenop(AbstractRGenOpTests):
RGenOp = RGenOp
+ def setup_method(self, meth):
+ if 'ovfcheck' in meth.__name__:
+ py.test.skip("no chance (the llinterpreter has no rtyper)")
+
def getcompiled(self, runner, argtypes, annotatorpolicy):
def quasi_compiled_runner(*args):
return interpret(runner, args, policy=annotatorpolicy)
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/test/operation_tests.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/test/operation_tests.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/test/operation_tests.py Thu Mar 15 17:18:00 2007
@@ -3,7 +3,7 @@
from pypy.jit.codegen import graph2rgenop
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.rarithmetic import r_uint, intmask, ovfcheck
from ctypes import cast, c_void_p, CFUNCTYPE, c_int, c_float
from pypy import conftest
Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/test/rgenop_tests.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/test/rgenop_tests.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/test/rgenop_tests.py Thu Mar 15 17:18:00 2007
@@ -1,5 +1,6 @@
-import random
+import random, sys
from pypy.rpython.annlowlevel import MixLevelAnnotatorPolicy, llhelper
+from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import keepalive_until_here
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.translator.c.test import test_boehm
@@ -757,6 +758,29 @@
return res
return read_frame_place_runner
+def make_ovfcheck_adder(rgenop, n):
+ sigtoken = rgenop.sigToken(FUNC)
+ builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "ovfcheck_adder")
+ builder.start_writing()
+ gv_result, gv_flag = builder.genraisingop2("int_add_ovf", gv_x,
+ rgenop.genconst(n))
+ gv_flag = builder.genop1("cast_bool_to_int", gv_flag)
+ gv_result = builder.genop2("int_lshift", gv_result, rgenop.genconst(1))
+ gv_result = builder.genop2("int_or", gv_result, gv_flag)
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+ return gv_fn
+
+def get_ovfcheck_adder_runner(RGenOp):
+ def runner(x, y):
+ rgenop = RGenOp()
+ gv_add_x = make_ovfcheck_adder(rgenop, x)
+ add_x = gv_add_x.revealconst(lltype.Ptr(FUNC))
+ res = add_x(y)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+ return runner
+
class AbstractRGenOpTests(test_boehm.AbstractGCTestClass):
RGenOp = None
@@ -1765,3 +1789,98 @@
P = lltype.Ptr(lltype.Struct('S'))
gv = RGenOp.genzeroconst(RGenOp.kindToken(P))
assert gv.revealconst(llmemory.Address) == llmemory.NULL
+
+ def test_ovfcheck_adder_direct(self):
+ rgenop = self.RGenOp()
+ gv_add_5 = make_ovfcheck_adder(rgenop, 5)
+ fnptr = self.cast(gv_add_5, 1)
+ res = fnptr(37)
+ assert res == (42 << 1) | 0
+ res = fnptr(sys.maxint-2)
+ assert (res & 1) == 1
+
+ def test_ovfcheck_adder_compile(self):
+ fn = self.compile(get_ovfcheck_adder_runner(self.RGenOp), [int, int])
+ res = fn(9080983, -9080941)
+ assert res == (42 << 1) | 0
+ res = fn(-sys.maxint, -10)
+ assert (res & 1) == 1
+
+ def test_ovfcheck1_direct(self):
+ yield self.ovfcheck1_direct, "int_neg_ovf", [(18, -18),
+ (-18, 18),
+ (sys.maxint, -sys.maxint),
+ (-sys.maxint, sys.maxint),
+ (-sys.maxint-1, None)]
+ yield self.ovfcheck1_direct, "int_abs_ovf", [(18, 18),
+ (-18, 18),
+ (sys.maxint, sys.maxint),
+ (-sys.maxint, sys.maxint),
+ (-sys.maxint-1, None)]
+
+ def ovfcheck1_direct(self, opname, testcases):
+ rgenop = self.RGenOp()
+ sigtoken = rgenop.sigToken(FUNC)
+ builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "ovfcheck1")
+ builder.start_writing()
+ gv_result, gv_flag = builder.genraisingop1(opname, gv_x)
+ gv_flag = builder.genop1("cast_bool_to_int", gv_flag)
+ gv_result = builder.genop2("int_lshift", gv_result, rgenop.genconst(1))
+ gv_result = builder.genop2("int_or", gv_result, gv_flag)
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+
+ fnptr = self.cast(gv_fn, 1)
+ for x, expected in testcases:
+ res = fnptr(x)
+ if expected is None:
+ assert (res & 1) == 1
+ else:
+ assert res == intmask(expected << 1) | 0
+
+ def test_ovfcheck2_direct(self):
+ yield self.ovfcheck2_direct, "int_sub_ovf", [(18, 25, -7),
+ (sys.maxint, -1, None),
+ (-2, sys.maxint, None)]
+ yield self.ovfcheck2_direct, "int_mul_ovf", [(6, 7, 42),
+ (sys.maxint-100, 2, None),
+ (-2, sys.maxint-100, None)]
+ # XXX the rest in-progress
+ # XXX also missing the _zer versions
+## yield self.ovfcheck2_direct, "int_mod_ovf", [
+## (100, 8, 4),
+## (-sys.maxint-1, 1, 0),
+## (-sys.maxint-1, -1, None)]
+## yield self.ovfcheck2_direct, "int_floordiv_ovf", [
+## (100, 2, 50),
+## (-sys.maxint-1, 1, -sys.maxint-1),
+## (-sys.maxint-1, -1, None)]
+## yield self.ovfcheck2_direct, "int_lshift_ovf", [
+## (1, 30, 1<<30),
+## (1, 31, None),
+## (0xf23c, 14, 0xf23c << 14),
+## (0xf23c, 15, None),
+## (-1, 31, (-1) << 31),
+## (-2, 31, None),
+## (-3, 31, None),
+## (-sys.maxint-1, 0, -sys.maxint-1)]
+
+ def ovfcheck2_direct(self, opname, testcases):
+ rgenop = self.RGenOp()
+ sigtoken = rgenop.sigToken(FUNC2)
+ builder, gv_fn, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "ovfcheck2")
+ builder.start_writing()
+ gv_result, gv_flag = builder.genraisingop2(opname, gv_x, gv_y)
+ gv_flag = builder.genop1("cast_bool_to_int", gv_flag)
+ gv_result = builder.genop2("int_lshift", gv_result, rgenop.genconst(1))
+ gv_result = builder.genop2("int_or", gv_result, gv_flag)
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+
+ fnptr = self.cast(gv_fn, 1)
+ for x, y, expected in testcases:
+ res = fnptr(x, y)
+ if expected is None:
+ assert (res & 1) == 1
+ else:
+ assert res == intmask(expected << 1) | 0
More information about the Pypy-commit
mailing list