[pypy-svn] r23218 - in pypy/dist/pypy: jit jit/test rpython rpython/test

pedronis at codespeak.net pedronis at codespeak.net
Fri Feb 10 22:48:45 CET 2006


Author: pedronis
Date: Fri Feb 10 22:48:43 2006
New Revision: 23218

Modified:
   pypy/dist/pypy/jit/hintrtyper.py
   pypy/dist/pypy/jit/rtimeshift.py
   pypy/dist/pypy/jit/test/test_hint_timeshift.py
   pypy/dist/pypy/rpython/objectmodel.py
   pypy/dist/pypy/rpython/rgenop.py
   pypy/dist/pypy/rpython/test/test_objectmodel.py
   pypy/dist/pypy/rpython/test/test_rbuiltin.py
Log:
implemented simple mechanics for optimistic constant propagation

now we need proper join merge logic to not unroll too much

default op emitting and const propagation ow works for 1,2 arguments, this is the case for most normal
llops. The others likely need special casing anyway.

rgenop.genop is quite awkward at this point.



Modified: pypy/dist/pypy/jit/hintrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/hintrtyper.py	(original)
+++ pypy/dist/pypy/jit/hintrtyper.py	Fri Feb 10 22:48:43 2006
@@ -18,6 +18,13 @@
 
 # ___________________________________________________________
 
+
+def originalconcretetype(hs):
+    if isinstance(hs, annmodel.SomeImpossibleValue):
+        return lltype.Void
+    else:
+        return hs.concretetype
+
 class HintRTyper(RPythonTyper):
     
     def __init__(self, hannotator, timeshifter):
@@ -27,6 +34,8 @@
         self.red_reprs = {}
         self.timeshifter = timeshifter
 
+    originalconcretetype = staticmethod(originalconcretetype)
+
     def make_new_lloplist(self, block):
         return HintLowLevelOpList(self.timeshifter, block)
 
@@ -64,21 +73,31 @@
         # genop variables, and emits a call to a helper that will generate
         # the same operation at run-time
         # XXX constant propagate if possible
-        v_args = hop.genop('malloc_varsize',
-                           [hop.inputconst(lltype.Void, VARLIST.TO),
-                            hop.inputconst(lltype.Signed, len(hop.args_v))],
-                           resulttype = VARLIST)
-        for i in range(len(hop.args_v)):
-            v_gvar = hop.args_r[i].get_genop_var(hop.args_v[i], hop.llops)
-            hop.genop('setarrayitem', [v_args,
-                                       hop.inputconst(lltype.Signed, i),
-                                       v_gvar])
-        RESTYPE = originalconcretetype(hop.s_result)
-        c_restype = hop.inputconst(lltype.Void, RESTYPE)
-        return hop.gendirectcall(rtimeshift.ll_generate_operation,
+        opdesc = rtimeshift.make_opdesc(hop)
+        if opdesc.nb_args == 1:
+            ll_generate = rtimeshift.ll_generate_operation1
+        elif opdesc.nb_args == 2:
+            ll_generate = rtimeshift.ll_generate_operation2
+        c_opdesc = inputconst(lltype.Void, opdesc)
+        return hop.gendirectcall(ll_generate,
+                                 c_opdesc,
                                  hop.llops.getjitstate(),
-                                 opname2vstr(hop.spaceop.opname),
-                                 v_args, c_restype)
+                                 *hop.args_v)
+        #v_args = hop.genop('malloc_varsize',
+        #                   [hop.inputconst(lltype.Void, VARLIST.TO),
+        #                    hop.inputconst(lltype.Signed, len(hop.args_v))],
+        #                   resulttype = VARLIST)
+        #for i in range(len(hop.args_v)):
+        #    v_gvar = hop.args_r[i].get_genop_var(hop.args_v[i], hop.llops)
+        #    hop.genop('setarrayitem', [v_args,
+        #                               hop.inputconst(lltype.Signed, i),
+        #                               v_gvar])
+        #RESTYPE = originalconcretetype(hop.s_result)
+        #c_restype = hop.inputconst(lltype.Void, RESTYPE)
+        #return hop.gendirectcall(rtimeshift.ll_generate_operation,
+        #                         hop.llops.getjitstate(),
+        #                         opname2vstr(hop.spaceop.opname),
+        #                         v_args, c_restype)
 
 class HintLowLevelOpList(LowLevelOpList):
     """Warning: the HintLowLevelOpList's rtyper is the *original*
@@ -160,14 +179,6 @@
     if isinstance(_r, GreenRepr):
         PRECOMPUTED_GREEN_REPRS[_r.lowleveltype] = _r
 
-def ll_fixed_items(l):
-    return l
-
-VARLIST = lltype.Ptr(lltype.GcArray(rgenop.CONSTORVAR,
-                                    adtmeths = {
-                                        "ll_items": ll_fixed_items,
-                                    }))
-
 # ____________________________________________________________
 
 class SomeJITState(annmodel.SomeObject):
@@ -193,9 +204,3 @@
 def opname2vstr(name):
     lls = string_repr.convert_const(name)
     return inputconst(string_repr.lowleveltype, lls)
-
-def originalconcretetype(hs):
-    if isinstance(hs, annmodel.SomeImpossibleValue):
-        return lltype.Void
-    else:
-        return hs.concretetype

Modified: pypy/dist/pypy/jit/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/rtimeshift.py	Fri Feb 10 22:48:43 2006
@@ -1,6 +1,17 @@
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython import objectmodel
 from pypy.rpython import rgenop
 
+# ____________________________________________________________
+# types and adts
+
+def ll_fixed_items(l):
+    return l
+
+VARLIST = lltype.Ptr(lltype.GcArray(rgenop.CONSTORVAR,
+                                    adtmeths = {
+                                        "ll_items": ll_fixed_items,
+                                    }))
 
 STATE = lltype.GcStruct("jitstate", ("curblock", rgenop.BLOCK))
 STATE_PTR = lltype.Ptr(STATE)
@@ -38,6 +49,8 @@
                                     ("value", lltype.Signed))
 REDBOX_FOR_SIGNED_PTR = lltype.Ptr(REDBOX_FOR_SIGNED)
 
+# ____________________________________________________________
+# ll helpers on boxes
 
 
 def ll_gvar_from_redbox(jitstate, box, TYPE):
@@ -49,10 +62,88 @@
 def ll_gvar_from_const(jitstate, value):
     return rgenop.genconst(value)
 
-def ll_generate_operation(jitstate, opname, args, RESULTTYPE):
-    gvar = rgenop.genop(jitstate.curblock, opname, args, RESULTTYPE)
+# ____________________________________________________________
+# emit ops
+
+
+
+class OpDesc(object):
+    """
+    Descrption of a low-level operation
+    that can be passed around to low level helper
+    to inform op generation
+    """
+    
+    def _freeze_(self):
+        return True
+
+    def __init__(self, opname, ARGS, RESULT):
+        self.opname = opname
+        self.llop = getattr(objectmodel.llop, opname)
+        self.nb_args = len(ARGS)
+        self.ARGS = ARGS
+        self.RESULT = RESULT
+
+    def __getattr__(self, name): # .ARGx -> .ARGS[x]
+        if name.startswith('ARG'):
+            index = int(name[3:])
+            return self.ARGS[index]
+        else:
+            raise AttributeError("don't know about %r in OpDesc" % name)
+
+    def compact_repr(self): # goes in ll helper names
+        return self.opname.upper()
+
+_opdesc_cache = {}
+
+def make_opdesc(hop):
+    hrtyper = hop.rtyper
+    op_key = (hop.spaceop.opname,
+              tuple([hrtyper.originalconcretetype(s_arg) for s_arg in hop.args_s]),
+              hrtyper.originalconcretetype(hop.s_result))
+    try:
+        return _opdesc_cache[op_key]
+    except KeyError:
+        opdesc = OpDesc(*op_key)
+        _opdesc_cache[op_key] = opdesc
+        return opdesc
+
+def ll_generate_operation1(opdesc, jitstate, argbox):
+    ARG0 = opdesc.ARG0
+    RESULT = opdesc.RESULT
+    opname = opdesc.name
+    if not argbox.isvar: # const propagate
+        arg = argbox.getvalue(ARG0)
+        res = opdesc.llop(RESULT, arg)
+        return REDBOX.make_from_const(res)
+    op_args = lltype.malloc(VARLIST.TO, 1)
+    op_args[0] = ll_gvar_from_redbox(jitstate, argbox, ARG0)
+    gvar = rgenop.genop(jitstate.curblock, opdesc.opname, op_args, RESULT)
     return REDBOX.make_for_gvar(gvar)
 
+def ll_generate_operation2(opdesc, jitstate, argbox0, argbox1):
+    ARG0 = opdesc.ARG0
+    ARG1 = opdesc.ARG1
+    RESULT = opdesc.RESULT
+    opname = opdesc.name
+    if not argbox0.isvar and not argbox1.isvar: # const propagate
+        arg0 = argbox0.getvalue(ARG0)
+        arg1 = argbox1.getvalue(ARG1)
+        res = opdesc.llop(RESULT, arg0, arg1)
+        return REDBOX.make_from_const(res)
+    op_args = lltype.malloc(VARLIST.TO, 2)
+    op_args[0] = ll_gvar_from_redbox(jitstate, argbox0, ARG0)
+    op_args[1] = ll_gvar_from_redbox(jitstate, argbox1, ARG1)
+    gvar = rgenop.genop(jitstate.curblock, opdesc.opname, op_args, RESULT)
+    return REDBOX.make_for_gvar(gvar)
+
+#def ll_generate_operation(jitstate, opname, args, RESULTTYPE):
+#    gvar = rgenop.genop(jitstate.curblock, opname, args, RESULTTYPE)
+#    return REDBOX.make_for_gvar(gvar)
+
+# ____________________________________________________________
+# other jitstate/graph level operations
+
 def ll_setup_jitstate():
     jitstate = lltype.malloc(STATE)
     jitstate.curblock = rgenop.newblock()

Modified: pypy/dist/pypy/jit/test/test_hint_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_hint_timeshift.py	(original)
+++ pypy/dist/pypy/jit/test/test_hint_timeshift.py	Fri Feb 10 22:48:43 2006
@@ -34,7 +34,7 @@
         hannotator.translator.view()
     return hs, hannotator, rtyper
 
-def timeshift(ll_function, values):
+def timeshift(ll_function, values, opt_consts=[]):
     hs, ha, rtyper = hannotate(ll_function, values)
     htshift = HintTimeshift(ha, rtyper)
     htshift.timeshift()
@@ -50,7 +50,7 @@
     graph1args = [jitstate]
     residual_graph_args = []
     assert len(graph1.getargs()) == 1 + len(values)
-    for v, llvalue in zip(graph1.getargs()[1:], values):
+    for i, (v, llvalue) in enumerate(zip(graph1.getargs()[1:], values)):
         r = htshift.hrtyper.bindingrepr(v)
         residual_v = r.residual_values(llvalue)
         if len(residual_v) == 0:
@@ -61,6 +61,8 @@
             assert residual_v == [llvalue], "XXX for now"
             TYPE = htshift.originalconcretetype(v)
             box = rtimeshift.ll_input_redbox(jitstate, TYPE)
+            if i in opt_consts: # XXX what should happen here interface wise is unclear
+                box = rtimeshift.REDBOX.make_from_const(llvalue)
             graph1args.append(box)
             residual_graph_args.append(llvalue)
     llinterp = LLInterpreter(rtyper)
@@ -70,7 +72,7 @@
     if isinstance(r, hintrtyper.GreenRepr):
         result_gvar = rgenop.genconst(result1)
     elif isinstance(r, hintrtyper.RedRepr):
-        result_gvar = result1.genvar
+        result_gvar = rtimeshift.ll_gvar_from_redbox(jitstate, result1, r.original_concretetype)
     else:
         raise NotImplementedError(r)
     jitblock = rtimeshift.ll_close_jitstate(jitstate, result_gvar)
@@ -105,3 +107,17 @@
     insns, res = timeshift(ll_function, [7, 2])
     assert res == 14
     assert insns == {'int_add': 7}
+
+def test_simple_opt_const_propagation2():
+    def ll_function(x, y):
+        return x + y
+    insns, res = timeshift(ll_function, [5, 7], [0, 1])
+    assert res == 12
+    assert insns == {}
+
+def test_simple_opt_const_propagation1():
+    def ll_function(x):
+        return -x
+    insns, res = timeshift(ll_function, [5], [0])
+    assert res == -5
+    assert insns == {}

Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Fri Feb 10 22:48:43 2006
@@ -44,6 +44,7 @@
     obj.__dict__ = {}
     obj.__class__ = FREED_OBJECT
 
+# XXX these things don't clearly belong here XXX
 
 # the obtained address will not keep the object alive. e.g. if the object is
 # only reachable through an address, it might get collected
@@ -61,6 +62,48 @@
 def hlinvoke(repr, llcallable, *args):
     raise TypeError, "hlinvoke is meant to be rtyped and not called direclty"
 
+# generically insert ll ops
+
+# xxx Another approach would combine a llop function with a factory of names
+
+class LLOp(object):
+
+    def __init__(self, opname):
+        self.opname = opname
+
+    __name__ = property(lambda self: 'llop_'+self.opname)
+
+    def __call__(self, RESULTTYPE, *args):
+        raise TypeError, "llop is meant to be rtyped and not called direclty"
+
+    def compute_result_annotation(self, RESULTTYPE, *args):
+        from pypy.annotation.model import lltype_to_annotation
+        assert RESULTTYPE.is_constant()
+        return lltype_to_annotation(RESULTTYPE.const)
+
+    def specialize(self, hop):
+        args_v = [hop.inputarg(r, i+1) for i, r in enumerate(hop.args_r[1:])]
+        return hop.genop(self.opname, args_v, resulttype=hop.r_result.lowleveltype)
+
+class LLOpFactory(object):
+    def __init__(self):
+        self._cache = {}
+        
+    def _freeze_(self):
+        return True
+
+    def __getattr__(self, opname):
+        if opname == 'compute_result_annotation':
+            raise AttributeError
+        try:
+            return self._cache[opname]
+        except KeyError:
+            llop = self._cache[opname] = LLOp(opname)
+            return llop
+        
+llop = LLOpFactory()
+
+
 # ____________________________________________________________
 
 

Modified: pypy/dist/pypy/rpython/rgenop.py
==============================================================================
--- pypy/dist/pypy/rpython/rgenop.py	(original)
+++ pypy/dist/pypy/rpython/rgenop.py	Fri Feb 10 22:48:43 2006
@@ -178,7 +178,7 @@
 def testgengraph(gengraph, args, viewbefore=False):
     from pypy.rpython.llinterp import LLInterpreter
     if viewbefore:
-        graph.show()
+        gengraph.show()
     llinterp = LLInterpreter(PseudoRTyper())
     return llinterp.eval_graph(gengraph, args)
     

Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Fri Feb 10 22:48:43 2006
@@ -196,3 +196,11 @@
         return s1 == s2
     res = interpret(f, [])
     assert res
+
+def test_llop():
+    from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
+    from pypy.rpython import objectmodel
+    from pypy.rpython.lltypesystem import lltype
+    def llf(x, y):
+        return objectmodel.llop.int_add(lltype.Signed, x, y)
+    res = interpret(llf, [5, 7], policy=LowLevelAnnotatorPolicy())

Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rbuiltin.py	Fri Feb 10 22:48:43 2006
@@ -321,6 +321,3 @@
         return lltype.cast_primitive(lltype.UniChar, v)
     res = interpret(llf, [ord('x')], policy=LowLevelAnnotatorPolicy())
     assert res == u'x'
- 
-    
- 



More information about the Pypy-commit mailing list