[pypy-svn] r37394 - in pypy/dist/pypy: jit/codegen jit/codegen/i386 jit/codegen/i386/demo jit/codegen/i386/test objspace/flow

arigo at codespeak.net arigo at codespeak.net
Fri Jan 26 16:11:40 CET 2007


Author: arigo
Date: Fri Jan 26 16:11:37 2007
New Revision: 37394

Modified:
   pypy/dist/pypy/jit/codegen/graph2rgenop.py
   pypy/dist/pypy/jit/codegen/i386/demo/support.py
   pypy/dist/pypy/jit/codegen/i386/demo/test_factorial.py
   pypy/dist/pypy/jit/codegen/i386/operation.py
   pypy/dist/pypy/jit/codegen/i386/test/test_operation.py
   pypy/dist/pypy/objspace/flow/objspace.py
Log:
Some more bugs found by test_random_function().


Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/graph2rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/graph2rgenop.py	Fri Jan 26 16:11:37 2007
@@ -17,17 +17,16 @@
     t.buildannotator(policy=policy).build_types(entrypoint, argtypes)
     t.buildrtyper().specialize()
 
-    #from pypy.translator.backendopt.all import backend_optimizations
-    #backend_optimizations(t)
+    # note that backend optimizations will constant-fold simple operations,
+    # which is required by some backends that don't accept calls like
+    # genop1("add", constant, constant).
+    from pypy.translator.backendopt.all import backend_optimizations
+    backend_optimizations(t)
 
     if conftest.option.view:
         t.view()
 
-    from pypy.translator.c.genc import CStandaloneBuilder
-    cbuild = CStandaloneBuilder(t, entrypoint, config=t.config)
-    db = cbuild.generate_graphs_for_llinterp()
-    entrypointptr = cbuild.getentrypointptr()
-    entrygraph = entrypointptr._obj.graph
+    entrygraph = t._graphof(entrypoint)
     return compile_graph(rgenop, entrygraph, random_seed=random_seed)
 
 

Modified: pypy/dist/pypy/jit/codegen/i386/demo/support.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/demo/support.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/demo/support.py	Fri Jan 26 16:11:37 2007
@@ -26,8 +26,6 @@
     seed = demo_conftest.option.randomseed
     benchmark = bench_conftest.option.benchmark
 
-    expected = entrypoint(*args)
-
     logfile = str(udir.join('%s.log' % (entrypoint.__name__,)))
     try:
         os.unlink(logfile)
@@ -58,20 +56,22 @@
                              random_seed=seed)
     machine_code_dumper._freeze_()    # clean up state
 
-    fp = cast(c_void_p(gv_entrypoint.value),
-              CFUNCTYPE(c_int, *[c_int] * nb_args))
-
     print
-    print 'Random seed value was %d.' % (seed,)
+    print 'Random seed value: %d' % (seed,)
     print
+    expected = entrypoint(*args)
+
     print 'Running %s(%s)...' % (entrypoint.__name__,
                                  ', '.join(map(repr, args)))
+    fp = cast(c_void_p(gv_entrypoint.value),
+              CFUNCTYPE(c_int, *[c_int] * nb_args))
     res = fp(*args)
     print '===>', res
     print
     if res != expected:
-        raise AssertionError("expected return value is %s, got %s" % (
-            expected, res))
+        raise AssertionError(
+            "expected return value is %s, got %s\nseed = %s" % (
+                expected, res, seed))
 
     if view:
         from pypy.jit.codegen.i386.viewcode import World

Modified: pypy/dist/pypy/jit/codegen/i386/demo/test_factorial.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/demo/test_factorial.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/demo/test_factorial.py	Fri Jan 26 16:11:37 2007
@@ -48,14 +48,13 @@
     #rundemo(f1, 2117)
     rundemo(f1, 217)
 
-def test_random_function():
-    py.test.skip("in-progress (e.g. --seed=225 shows a backend crash)")
-    from pypy.rlib.unroll import SpecTag
-    blocklabels = range(15)
+def test_random_function(nb_blocks=15, max_block_length=20):
+    py.test.skip("in-progress")
+    blocklabels = range(nb_blocks)
     r = Random()
     vars = list("abcdefghijklmnopqrstuvwxyz")
     varlist = ', '.join(vars)
-    magicsum = '+'.join(['%s^%d' % (v, hash(v)) for v in vars])
+    magicsum = '+'.join(['%s*%d' % (v, hash(v)) for v in vars])
     operations = ['%s + %s',
                   '%s + %s',
                   '%s - %s',
@@ -64,8 +63,8 @@
                   '%s & %s',
                   '%s | %s',
                   '%s ^ %s',
-                  '%s << abs(%s)',
-                  '%s >> abs(%s)',
+                  '%s << (%s & 0x1234567f)',
+                  '%s >> (%s & 0x1234567f)',
                   'abs(%s)',
                   '-%s',
                   '~%s',
@@ -84,14 +83,13 @@
                   '!%s >  %s',
                   '!%s >= %s',
                   ]
-    lines = ["def dummyfn(%(varlist)s):" % locals(),
-             "  goto = blocktag0",
-             "  counter = 10000",
-             "  while counter > 0:",
-             "    counter -= 1"]
+    lines = ["def dummyfn(counter, %(varlist)s):" % locals(),
+             "  goto = 0",
+             "  while True:",
+             ]
     for i in blocklabels:
-        lines.append("    if goto is blocktag%d:" % i)
-        for j in range(r.randrange(0, 20)):
+        lines.append("    if goto == %d:" % i)
+        for j in range(r.randrange(0, max_block_length)):
             v1 = r.choice(vars)
             constbytes = r.randrange(-15, 5)
             if constbytes <= 0:
@@ -113,19 +111,19 @@
                     constant = constant << 8 | r.randrange(0, 256)
                 lines.append("      %s = %d" % (v1, constant))
         v1 = r.choice(vars)
-        lines.append("      if %s: goto = blocktag%d" %
-                     (v1, r.choice(blocklabels)))
-        lines.append("      else: goto = blocktag%d" %
-                     (r.choice(blocklabels),))
-    lines.append("  del goto")
+        for line in ["      if %s:" % v1,
+                     "      else:"]:
+            lines.append(line)
+            j = r.choice(blocklabels)
+            if j <= i:
+                lines.append("        counter -= 1")
+                lines.append("        if not counter: break")
+            lines.append("        goto = %d" % j)
     lines.append("  return intmask(%(magicsum)s)" % locals())
 
-    miniglobals = {'intmask': intmask}
-    for i in blocklabels:
-        miniglobals['blocktag%d' % i] = SpecTag()
     src = py.code.Source('\n'.join(lines))
-    exec src.compile() in miniglobals
-    dummyfn = miniglobals['dummyfn']
+    print src
+    exec src.compile()
 
     args = [r.randrange(-99, 100) for v1 in vars]
-    rundemo(dummyfn, *args)
+    rundemo(dummyfn, 100, *args)

Modified: pypy/dist/pypy/jit/codegen/i386/operation.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/operation.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/operation.py	Fri Jan 26 16:11:37 2007
@@ -53,11 +53,20 @@
 class UnaryOp(Op1):
     def generate(self, allocator):
         try:
-            loc = allocator.var2loc[self]
+            dstop = allocator.get_operand(self)
         except KeyError:
             return    # simple operation whose result is not used anyway
-        op = allocator.load_location_with(loc, self.x)
-        self.emit(allocator.mc, op)
+        srcop = allocator.get_operand(self.x)
+        mc = allocator.mc
+        if srcop != dstop:
+            try:
+                mc.MOV(dstop, srcop)
+            except FailedToImplement:
+                mc.MOV(ecx, srcop)
+                self.emit(mc, ecx)
+                mc.MOV(dstop, ecx)
+                return
+        self.emit(mc, dstop)
 
 class OpIntNeg(UnaryOp):
     opname = 'int_neg'
@@ -214,6 +223,8 @@
             mc.MOV(dstop, tmpop)
 
 class MulOrDivOp(Op2):
+    extra_scratch = mem(esp)
+
     def generate3(self, mc, dstop, op1, op2):
         # not very efficient but not very common operations either
         if dstop != eax:
@@ -223,6 +234,9 @@
         if op1 != eax:
             mc.MOV(eax, op1)
         if self.input_is_64bits:
+            if op2 == edx:
+                mc.PUSH(edx)
+                op2 = MulOrDivOp.extra_scratch
             if self.unsigned:
                 mc.XOR(edx, edx)
             else:
@@ -234,6 +248,8 @@
             self.emit(mc, ecx)
         if dstop != self.reg_containing_result:
             mc.MOV(dstop, self.reg_containing_result)
+        if op2 is MulOrDivOp.extra_scratch:
+            mc.ADD(esp, imm8(WORD))
         if dstop != edx:
             mc.POP(edx)
         if dstop != eax:

Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py	Fri Jan 26 16:11:37 2007
@@ -77,3 +77,15 @@
         [v4] = args_gv
         builder1.finish_and_return(rgenop.sigToken(FUNC0), v4)
         builder0.end()
+
+    def test_idiv_bug(self):
+        def fn(x, y):
+            return (x+1) // (-y) + x + y      # generated a bogus "idiv edx"
+        fp = self.rgen(fn, [int, int])
+        assert fp(5, 7) == fn(5, 7)
+
+    def test_imod_bug(self):
+        def fn(x, y):
+            return (x+1) % (-y) + x + y
+        fp = self.rgen(fn, [int, int])
+        assert fp(5, 7) == fn(5, 7)

Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Fri Jan 26 16:11:37 2007
@@ -623,12 +623,17 @@
                     raise flowcontext.OperationThatShouldNotBePropagatedError(
                         self.wrap(etype), self.wrap(msg))
                 else:
-                    try:
-                        return self.wrap(result)
-                    except WrapException:
-                        # type cannot sanely appear in flow graph,
-                        # store operation with variable result instead
-                        pass
+                    # don't try to constant-fold operations giving a 'long'
+                    # result.  The result is probably meant to be sent to
+                    # an intmask(), but the 'long' constant confuses the
+                    # annotator a lot.
+                    if type(result) is not long:
+                        try:
+                            return self.wrap(result)
+                        except WrapException:
+                            # type cannot sanely appear in flow graph,
+                            # store operation with variable result instead
+                            pass
 
         #print >> sys.stderr, 'Variable operation', name, args_w
         w_result = self.do_operation_with_implicit_exceptions(name, *args_w)



More information about the Pypy-commit mailing list