[pypy-svn] r64597 - pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test

arigo at codespeak.net arigo at codespeak.net
Thu Apr 23 16:50:20 CEST 2009


Author: arigo
Date: Thu Apr 23 16:50:19 2009
New Revision: 64597

Added:
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/conftest.py
      - copied, changed from r63006, pypy/branch/oo-jit/pypy/jit/codegen/demo/conftest.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py
      - copied, changed from r63006, pypy/branch/oo-jit/pypy/jit/codegen/demo/test_random.py
Log:
Random test.  Running it with --backend=x86 quickly shows crashes
and/or real bugs.


Copied: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/conftest.py (from r63006, pypy/branch/oo-jit/pypy/jit/codegen/demo/conftest.py)
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/demo/conftest.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/conftest.py	Thu Apr 23 16:50:19 2009
@@ -1,38 +1,27 @@
 import py, random
 
-from pypy.jit.codegen.ppc import conftest
+option = py.test.config.option
 
-Option = py.test.config.Option
+class RandomRunnerPlugin:
+    def pytest_addoption(self, parser):
+        group = parser.addgroup('random test options')
+        group.addoption('--seed', action="store", type="int",
+                        default=random.randrange(0, 10000),
+                        dest="randomseed",
+                        help="choose a fixed random seed")
+        group.addoption('--backend', action="store",
+                        default='llgraph',
+                        choices=['llgraph', 'minimal', 'x86'],
+                        dest="backend",
+                        help="select the backend to run the functions with")
+        group.addoption('--block-length', action="store", type="int",
+                        default=30,
+                        dest="block_length",
+                        help="insert up to this many operations in each test")
+        group.addoption('--n-vars', action="store", type="int",
+                        default=10,
+                        dest="n_vars",
+                        help="supply this many randomly-valued arguments to "
+                             "the function")
 
-option = py.test.config.addoptions("demo options",
-        Option('--seed', action="store", type="int",
-               default=random.randrange(0, 10000),
-               dest="randomseed",
-               help="choose a fixed random seed"),
-        Option('--backend', action="store",
-               default='llgraph',
-               choices=['llgraph', 'dump', 'ppc', 'i386', 'ia32', 'llvm',
-                        'ppcfew'],
-               dest="backend",
-               help="select the backend to run the functions with"),
-        Option('--nb-blocks', action="store", type="int",
-               default=15,
-               dest="nb_blocks",
-               help="how many blocks to include in the random function"),
-        Option('--max-block-length', action="store", type="int",
-               default=20,
-               dest="max_block_length",
-               help="insert up to this many operations in each block"),
-        Option('--n-vars', action="store", type="int",
-               default=26,
-               dest="n_vars",
-               help="supply this many randomly-valued arguments to the function"),
-        Option('--iterations', action="store", type="int",
-               default=0,
-               dest="iterations",
-               help="run the loop of the generated function this many times - "
-                    "the default is backend dependent"),
-        )
-
-very_slow_backends = {'llgraph': True,
-                      'dump': True}
+ConftestPlugin = RandomRunnerPlugin

Copied: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py (from r63006, pypy/branch/oo-jit/pypy/jit/codegen/demo/test_random.py)
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/demo/test_random.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py	Thu Apr 23 16:50:19 2009
@@ -1,100 +1,182 @@
-import py
-from pypy.rlib.rarithmetic import intmask
-from pypy.jit.codegen.demo.support import rundemo, Random, udir
-from pypy.jit.codegen.demo import conftest as demo_conftest
+import py, sys, math
+from pypy.rlib.rarithmetic import intmask, LONG_BIT
+from pypy.jit.backend.test import conftest as demo_conftest
+from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt
+from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.executor import execute
+
+
+class OperationBuilder:
+    def __init__(self, cpu, loop, vars):
+        self.cpu = cpu
+        self.loop = loop
+        self.vars = vars
+        self.boolvars = []   # subset of self.vars
+
+    def do(self, opnum, argboxes):
+        v_result = execute(self.cpu, opnum, argboxes)
+        v_result = BoxInt(v_result.value)
+        self.loop.operations.append(ResOperation(opnum, argboxes, v_result))
+        return v_result
+
+class AbstractOperation:
+    def __init__(self, opnum, boolres=False):
+        self.opnum = opnum
+        self.boolres = boolres
+    def put(self, builder, args):
+        v_result = builder.do(self.opnum, args)
+        builder.vars.append(v_result)
+        if self.boolres:
+            builder.boolvars.append(v_result)
+
+class UnaryOperation(AbstractOperation):
+    def produce_into(self, builder, r):
+        self.put(builder, [r.choice(builder.vars)])
+
+class BooleanUnaryOperation(UnaryOperation):
+    def produce_into(self, builder, r):
+        if builder.boolvars:
+            v = r.choice(builder.boolvars)
+        else:
+            v = r.choice(builder.vars)
+            v = builder.do(rop.INT_IS_TRUE, [v])
+        self.put(builder, [v])
+
+class BinaryOperation(AbstractOperation):
+    def __init__(self, opnum, and_mask=-1, or_mask=0, boolres=False):
+        AbstractOperation.__init__(self, opnum, boolres=boolres)
+        self.and_mask = and_mask
+        self.or_mask = or_mask
+    def produce_into(self, builder, r):
+        k = r.random()
+        if k < 0.2:
+            v_first = ConstInt(r.random_integer())
+        else:
+            v_first = r.choice(builder.vars)
+        if k > 0.75:
+            value = r.random_integer()
+            v_second = ConstInt((value & self.and_mask) | self.or_mask)
+        else:
+            v = r.choice(builder.vars)
+            if self.and_mask != 1:
+                v = builder.do(rop.INT_AND, [v, ConstInt(self.and_mask)])
+            if self.or_mask != 0:
+                v = builder.do(rop.INT_OR, [v, ConstInt(self.or_mask)])
+            v_second = v
+        self.put(builder, [v_first, v_second])
+
+OPERATIONS = []
+
+for _op in [rop.INT_ADD,
+            rop.INT_SUB,
+            rop.INT_MUL,
+            rop.INT_AND,
+            rop.INT_OR,
+            rop.INT_XOR,
+            rop.UINT_MUL,
+            ]:
+    OPERATIONS.append(BinaryOperation(_op))
+
+for _op in [rop.INT_LT,
+            rop.INT_LE,
+            rop.INT_EQ,
+            rop.INT_NE,
+            rop.INT_GT,
+            rop.INT_GE,
+            rop.UINT_LT,
+            rop.UINT_LE,
+            #rop.UINT_EQ,
+            #rop.UINT_NE,
+            rop.UINT_GT,
+            rop.UINT_GE,
+            ]:
+    OPERATIONS.append(BinaryOperation(_op, boolres=True))
+
+OPERATIONS.append(BinaryOperation(rop.INT_FLOORDIV, ~3, 1))
+OPERATIONS.append(BinaryOperation(rop.INT_MOD, ~3, 1))
+OPERATIONS.append(BinaryOperation(rop.INT_RSHIFT, LONG_BIT-1))
+OPERATIONS.append(BinaryOperation(rop.INT_LSHIFT, LONG_BIT-1))
+OPERATIONS.append(BinaryOperation(rop.UINT_RSHIFT, LONG_BIT-1))
+
+for _op in [rop.INT_NEG,
+            rop.INT_INVERT,
+            rop.INT_ABS,
+            ]:
+    OPERATIONS.append(UnaryOperation(_op))
+
+OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True))
+OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True))
+
+# ____________________________________________________________
+
+def Random():
+    import random
+    seed = demo_conftest.option.randomseed
+    print
+    print 'Random seed value is %d.' % (seed,)
+    print
+    r = random.Random(seed)
+    def get_random_integer():
+        while True:
+            result = int(random.expovariate(0.05))
+            if result <= sys.maxint:
+                break
+        if random.randrange(0, 5) <= 1:
+            result = -result
+        return result
+    r.random_integer = get_random_integer
+    return r
+
+def get_cpu():
+    if demo_conftest.option.backend == 'llgraph':
+        from pypy.jit.backend.llgraph.runner import LLtypeCPU
+        return LLtypeCPU(None)
+    elif demo_conftest.option.backend == 'minimal':
+        from pypy.jit.backend.minimal.runner import CPU
+        return CPU(None)
+    elif demo_conftest.option.backend == 'x86':
+        from pypy.jit.backend.x86.runner import CPU386
+        return CPU386(None, None)
+    else:
+        assert 0, "unknown backend %r" % demo_conftest.option.backend
 
+# ____________________________________________________________
 
-def test_random_function(nb_blocks=demo_conftest.option.nb_blocks,
-                         max_block_length=demo_conftest.option.max_block_length):
-    #py.test.skip("in-progress")
-    blocklabels = range(nb_blocks)
+def test_random_function():
     r = Random()
-    vars = list("abcdefghijklmnopqrstuvwxyz"[:demo_conftest.option.n_vars])
-    varlist = ', '.join(vars)
-    magicsum = '+'.join(['%s*%d' % (v, hash(v)) for v in vars])
-    operations = ['%s + %s',
-                  '%s + %s',
-                  '%s - %s',
-                  '%s - %s',
-                  '%s * %s',
-                  '%s & %s',
-                  '%s | %s',
-                  '%s ^ %s',
-                  '%s << (%s & 0x0000067f)',
-                  '%s >> (%s & 0x1234567f)',
-                  'abs(%s)',
-                  '-%s',
-                  '~%s',
-                  '%s // ((%s & 0xfffff) + 1)',
-                  '%s // (-((%s & 0xfffff) + 2))',
-                  '%s %% ((%s & 0xfffff) + 1)',
-                  '%s %% (-((%s & 0xfffff) + 2))',
-                  '!%s or %s',
-                  '!%s and %s',
-                  '!not %s',
-                  '!bool(%s)',
-                  '!%s <  %s',
-                  '!%s <= %s',
-                  '!%s == %s',
-                  '!%s != %s',
-                  '!%s >  %s',
-                  '!%s >= %s',
-                  ]
-    lines = ["def dummyfn(counter, %(varlist)s):" % locals(),
-             "  goto = 0",
-             "  while True:",
-             ]
-    for blocklabel in blocklabels:
-        lines.append("    if goto == %d:" % blocklabel)
-        for j in range(r.randrange(0, max_block_length)):
-            v1 = r.choice(vars)
-            constbytes = r.randrange(-15, 5)
-            if constbytes <= 0:
-                v2 = r.choice(vars)
-                op = r.choice(operations)
-                if op.count('%s') == 1:
-                    op = op % (v2,)
-                else:
-                    v3 = r.choice(vars)
-                    op = op % (v2, v3)
-                if op.startswith('!'):
-                    op = op[1:]
-                else:
-                    op = 'intmask(%s)' % op
-                lines.append("      %s = %s" % (v1, op))
-            else:
-                constant = r.randrange(-128, 128)
-                for i in range(1, constbytes):
-                    constant = constant << 8 | r.randrange(0, 256)
-                lines.append("      %s = %d" % (v1, constant))
-        v1 = r.choice(vars)
-        for line in ["      if %s:" % v1,
-                     "      else:"]:
-            lines.append(line)
-            j = r.choice(blocklabels)
-            if j <= blocklabel:
-                lines.append("        counter -= 1")
-                lines.append("        if not counter: break")
-            lines.append("        goto = %d" % j)
-    lines.append("  return intmask(%(magicsum)s)" % locals())
-
-    args = [r.randrange(-99, 100) for v1 in vars]
-
-    src = py.code.Source('\n'.join(lines))
-    print src
-    udir.join('generated.py').write(
-        'from pypy.rlib.rarithmetic import intmask\n\n'
-        '%s\n\n'
-        'args=%r\n'
-        'print dummyfn(10000, *args)\n' % (src, args))
-    exec src.compile()
-
-    if demo_conftest.option.iterations != 0:
-        iterations = demo_conftest.option.iterations
-    else:
-        if demo_conftest.option.backend in demo_conftest.very_slow_backends:
-            iterations = 50
+    block_length = demo_conftest.option.block_length
+    vars = [BoxInt(r.random_integer())
+            for i in range(demo_conftest.option.n_vars)]
+    valueboxes = [BoxInt(box.value) for box in vars]
+
+    cpu = get_cpu()
+    loop = TreeLoop('test_random_function')
+    loop.inputargs = vars[:]
+    loop.operations = []
+
+    builder = OperationBuilder(cpu, loop, vars)
+
+    for i in range(block_length):
+        r.choice(OPERATIONS).produce_into(builder, r)
+
+    endvars = []
+    for v in vars:
+        for op in loop.operations:
+            if v in op.args:
+                break
         else:
-            iterations = 10000
+            endvars.append(v)
+    r.shuffle(endvars)
+    loop.operations.append(ResOperation(rop.FAIL, endvars, None))
+
+    cpu.compile_operations(loop)
+
+    expected = {}
+    for v in endvars:
+        expected[v] = v.value
+        v.changevalue_int(-sys.maxint-1)
+
+    cpu.execute_operations(loop, valueboxes)
 
-    rundemo(dummyfn, iterations, *args)
+    for v in endvars:
+        assert v.value == expected[v]



More information about the Pypy-commit mailing list