[pypy-commit] pypy conditional_call_value_4: Revert the @jit.call_shortcut support (6305cfb3bad2)
arigo
pypy.commits at gmail.com
Thu Nov 24 06:06:28 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: conditional_call_value_4
Changeset: r88630:6d3400d6ed8f
Date: 2016-11-24 11:16 +0000
http://bitbucket.org/pypy/pypy/changeset/6d3400d6ed8f/
Log: Revert the @jit.call_shortcut support (6305cfb3bad2)
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -11,7 +11,7 @@
from rpython.jit.backend.llsupport.symbolic import (WORD,
get_field_token, get_array_token)
from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr,\
- FLAG_POINTER, CallDescr
+ FLAG_POINTER
from rpython.jit.metainterp.history import JitCellToken
from rpython.jit.backend.llsupport.descr import (unpack_arraydescr,
unpack_fielddescr, unpack_interiorfielddescr)
@@ -359,9 +359,7 @@
self.consider_setfield_gc(op)
elif op.getopnum() == rop.SETARRAYITEM_GC:
self.consider_setarrayitem_gc(op)
- # ---------- calls -----------
- if OpHelpers.is_plain_call(op.getopnum()):
- self.expand_call_shortcut(op)
+ # ---------- call assembler -----------
if OpHelpers.is_call_assembler(op.getopnum()):
self.handle_call_assembler(op)
continue
@@ -607,31 +605,6 @@
self.emit_gc_store_or_indexed(None, ptr, ConstInt(0), value,
size, 1, ofs)
- def expand_call_shortcut(self, op):
- descr = op.getdescr()
- if descr is None:
- return
- assert isinstance(descr, CallDescr)
- effectinfo = descr.get_extra_info()
- if effectinfo is None or effectinfo.call_shortcut is None:
- return
- if op.type == 'r':
- cond_call_opnum = rop.COND_CALL_VALUE_R
- elif op.type == 'i':
- cond_call_opnum = rop.COND_CALL_VALUE_I
- else:
- return
- cs = effectinfo.call_shortcut
- ptr_box = op.getarg(1 + cs.argnum)
- if cs.fielddescr is not None:
- value_box = self.emit_getfield(ptr_box, descr=cs.fielddescr,
- raw=(ptr_box.type == 'i'))
- else:
- value_box = ptr_box
- self.replace_op_with(op, ResOperation(cond_call_opnum,
- [value_box] + op.getarglist(),
- descr=descr))
-
def handle_call_assembler(self, op):
descrs = self.gc_ll_descr.getframedescrs(self.cpu)
loop_token = op.getdescr()
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -1,8 +1,7 @@
import py
from rpython.jit.backend.llsupport.descr import get_size_descr,\
get_field_descr, get_array_descr, ArrayDescr, FieldDescr,\
- SizeDescr, get_interiorfield_descr, get_call_descr
-from rpython.jit.codewriter.effectinfo import EffectInfo, CallShortcut
+ SizeDescr, get_interiorfield_descr
from rpython.jit.backend.llsupport.gc import GcLLDescr_boehm,\
GcLLDescr_framework
from rpython.jit.backend.llsupport import jitframe
@@ -81,21 +80,6 @@
lltype.malloc(T, zero=True))
self.myT = myT
#
- call_shortcut = CallShortcut(0, tzdescr)
- effectinfo = EffectInfo(None, None, None, None, None, None,
- EffectInfo.EF_RANDOM_EFFECTS,
- call_shortcut=call_shortcut)
- call_shortcut_descr = get_call_descr(self.gc_ll_descr,
- [lltype.Ptr(T)], lltype.Signed,
- effectinfo)
- call_shortcut_2 = CallShortcut(0, None)
- effectinfo_2 = EffectInfo(None, None, None, None, None, None,
- EffectInfo.EF_RANDOM_EFFECTS,
- call_shortcut=call_shortcut_2)
- call_shortcut_descr_2 = get_call_descr(self.gc_ll_descr,
- [lltype.Signed], lltype.Signed,
- effectinfo_2)
- #
A = lltype.GcArray(lltype.Signed)
adescr = get_array_descr(self.gc_ll_descr, A)
adescr.tid = 4321
@@ -1452,26 +1436,3 @@
jump()
""")
assert len(self.gcrefs) == 2
-
- def test_handle_call_shortcut(self):
- self.check_rewrite("""
- [p0]
- i1 = call_i(123, p0, descr=call_shortcut_descr)
- jump(i1)
- """, """
- [p0]
- i2 = gc_load_i(p0, %(tzdescr.offset)s, %(tzdescr.field_size)s)
- i1 = cond_call_value_i(i2, 123, p0, descr=call_shortcut_descr)
- jump(i1)
- """)
-
- def test_handle_call_shortcut_2(self):
- self.check_rewrite("""
- [i0]
- i1 = call_i(123, i0, descr=call_shortcut_descr_2)
- jump(i1)
- """, """
- [i0]
- i1 = cond_call_value_i(i0, 123, i0, descr=call_shortcut_descr_2)
- jump(i1)
- """)
diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py
--- a/rpython/jit/codewriter/call.py
+++ b/rpython/jit/codewriter/call.py
@@ -7,10 +7,9 @@
from rpython.jit.codewriter.jitcode import JitCode
from rpython.jit.codewriter.effectinfo import (VirtualizableAnalyzer,
QuasiImmutAnalyzer, RandomEffectsAnalyzer, effectinfo_from_writeanalyze,
- EffectInfo, CallInfoCollection, CallShortcut)
+ EffectInfo, CallInfoCollection)
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.rtyper.lltypesystem.lltype import getfunctionptr
-from rpython.flowspace.model import Constant, Variable
from rpython.rlib import rposix
from rpython.translator.backendopt.canraise import RaiseAnalyzer
from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer
@@ -215,7 +214,6 @@
elidable = False
loopinvariant = False
call_release_gil_target = EffectInfo._NO_CALL_RELEASE_GIL_TARGET
- call_shortcut = None
if op.opname == "direct_call":
funcobj = op.args[0].value._obj
assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
@@ -230,12 +228,6 @@
tgt_func, tgt_saveerr = func._call_aroundstate_target_
tgt_func = llmemory.cast_ptr_to_adr(tgt_func)
call_release_gil_target = (tgt_func, tgt_saveerr)
- if hasattr(funcobj, 'graph'):
- call_shortcut = self.find_call_shortcut(funcobj.graph)
- if getattr(func, "_call_shortcut_", False):
- assert call_shortcut is not None, (
- "%r: marked as @jit.call_shortcut but shortcut not found"
- % (func,))
elif op.opname == 'indirect_call':
# check that we're not trying to call indirectly some
# function with the special flags
@@ -250,8 +242,6 @@
error = '@jit.loop_invariant'
if hasattr(graph.func, '_call_aroundstate_target_'):
error = '_call_aroundstate_target_'
- if hasattr(graph.func, '_call_shortcut_'):
- error = '@jit.call_shortcut'
if not error:
continue
raise Exception(
@@ -308,7 +298,6 @@
self.readwrite_analyzer.analyze(op, self.seen_rw), self.cpu,
extraeffect, oopspecindex, can_invalidate, call_release_gil_target,
extradescr, self.collect_analyzer.analyze(op, self.seen_gc),
- call_shortcut,
)
#
assert effectinfo is not None
@@ -379,76 +368,3 @@
if GTYPE_fieldname in jd.greenfield_info.green_fields:
return True
return False
-
- def find_call_shortcut(self, graph):
- """Identifies graphs that start like this:
-
- def graph(x, y, z): def graph(x, y, z):
- if y.field: r = y.field
- return y.field if r: return r
- """
- block = graph.startblock
- operations = block.operations
- c_fieldname = None
- if not operations:
- v_inst = v_result = block.exitswitch
- else:
- op = operations[0]
- if len(op.args) == 0:
- return
- if op.opname != 'getfield': # check for this form:
- v_inst = op.args[0] # if y is not None;
- v_result = v_inst # return y
- else:
- operations = operations[1:]
- [v_inst, c_fieldname] = op.args
- v_result = op.result
- if not isinstance(v_inst, Variable):
- return
- if v_result.concretetype != graph.getreturnvar().concretetype:
- return
- if v_result.concretetype == lltype.Void:
- return
- argnum = i = 0
- while block.inputargs[i] is not v_inst:
- if block.inputargs[i].concretetype != lltype.Void:
- argnum += 1
- i += 1
- PSTRUCT = v_inst.concretetype
- v_check = v_result
- fastcase = True
- for op in operations:
- if (op.opname in ('int_is_true', 'ptr_nonzero', 'same_as')
- and v_check is op.args[0]):
- v_check = op.result
- elif op.opname == 'ptr_iszero' and v_check is op.args[0]:
- v_check = op.result
- fastcase = not fastcase
- elif (op.opname in ('int_eq', 'int_ne')
- and v_check is op.args[0]
- and isinstance(op.args[1], Constant)
- and op.args[1].value == 0):
- v_check = op.result
- if op.opname == 'int_eq':
- fastcase = not fastcase
- else:
- return
- if v_check.concretetype is not lltype.Bool:
- return
- if block.exitswitch is not v_check:
- return
-
- links = [link for link in block.exits if link.exitcase == fastcase]
- if len(links) != 1:
- return
- [link] = links
- if link.args != [v_result]:
- return
- if not link.target.is_final_block():
- return
-
- if c_fieldname is not None:
- fielddescr = self.cpu.fielddescrof(PSTRUCT.TO, c_fieldname.value)
- else:
- fielddescr = None
- return CallShortcut(argnum, fielddescr)
diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -117,8 +117,7 @@
can_invalidate=False,
call_release_gil_target=_NO_CALL_RELEASE_GIL_TARGET,
extradescrs=None,
- can_collect=True,
- call_shortcut=None):
+ can_collect=True):
readonly_descrs_fields = frozenset_or_none(readonly_descrs_fields)
readonly_descrs_arrays = frozenset_or_none(readonly_descrs_arrays)
readonly_descrs_interiorfields = frozenset_or_none(
@@ -136,8 +135,7 @@
extraeffect,
oopspecindex,
can_invalidate,
- can_collect,
- call_shortcut)
+ can_collect)
tgt_func, tgt_saveerr = call_release_gil_target
if tgt_func:
key += (object(),) # don't care about caching in this case
@@ -192,7 +190,6 @@
result.oopspecindex = oopspecindex
result.extradescrs = extradescrs
result.call_release_gil_target = call_release_gil_target
- result.call_shortcut = call_shortcut
if result.check_can_raise(ignore_memoryerror=True):
assert oopspecindex in cls._OS_CANRAISE
@@ -278,8 +275,7 @@
call_release_gil_target=
EffectInfo._NO_CALL_RELEASE_GIL_TARGET,
extradescr=None,
- can_collect=True,
- call_shortcut=None):
+ can_collect=True):
from rpython.translator.backendopt.writeanalyze import top_set
if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
readonly_descrs_fields = None
@@ -368,8 +364,7 @@
can_invalidate,
call_release_gil_target,
extradescr,
- can_collect,
- call_shortcut)
+ can_collect)
def consider_struct(TYPE, fieldname):
if fieldType(TYPE, fieldname) is lltype.Void:
@@ -392,24 +387,6 @@
# ____________________________________________________________
-
-class CallShortcut(object):
- def __init__(self, argnum, fielddescr):
- self.argnum = argnum
- self.fielddescr = fielddescr
-
- def __eq__(self, other):
- return (isinstance(other, CallShortcut) and
- self.argnum == other.argnum and
- self.fielddescr == other.fielddescr)
- def __ne__(self, other):
- return not (self == other)
- def __hash__(self):
- return hash((self.argnum, self.fielddescr))
-
-# ____________________________________________________________
-
-
class VirtualizableAnalyzer(BoolGraphAnalyzer):
def analyze_simple_operation(self, op, graphinfo):
return op.opname in ('jit_force_virtualizable',
diff --git a/rpython/jit/codewriter/test/test_call.py b/rpython/jit/codewriter/test/test_call.py
--- a/rpython/jit/codewriter/test/test_call.py
+++ b/rpython/jit/codewriter/test/test_call.py
@@ -6,7 +6,7 @@
from rpython.rlib import jit
from rpython.jit.codewriter import support, call
from rpython.jit.codewriter.call import CallControl
-from rpython.jit.codewriter.effectinfo import EffectInfo, CallShortcut
+from rpython.jit.codewriter.effectinfo import EffectInfo
class FakePolicy:
@@ -368,121 +368,3 @@
assert call_op.opname == 'direct_call'
call_descr = cc.getcalldescr(call_op)
assert call_descr.extrainfo.check_can_collect() == expected
-
-def test_find_call_shortcut():
- class FakeCPU:
- def fielddescrof(self, TYPE, fieldname):
- if isinstance(TYPE, lltype.GcStruct):
- if fieldname == 'inst_foobar':
- return 'foobardescr'
- if fieldname == 'inst_fooref':
- return 'foorefdescr'
- if TYPE == RAW and fieldname == 'x':
- return 'xdescr'
- assert False, (TYPE, fieldname)
- cc = CallControl(FakeCPU())
-
- class B(object):
- foobar = 0
- fooref = None
-
- def f1(a, b, c):
- if b.foobar:
- return b.foobar
- b.foobar = a + c
- return b.foobar
-
- def f2(x, y, z, b):
- r = b.fooref
- if r is not None:
- return r
- r = b.fooref = B()
- return r
-
- class Space(object):
- def _freeze_(self):
- return True
- space = Space()
-
- def f3(space, b):
- r = b.foobar
- if not r:
- r = b.foobar = 123
- return r
-
- def f4(raw):
- r = raw.x
- if r != 0:
- return r
- raw.x = 123
- return 123
- RAW = lltype.Struct('RAW', ('x', lltype.Signed))
-
- def f5(b):
- r = b.foobar
- if r == 0:
- r = b.foobar = 123
- return r
-
- def f6(b):
- if b is not None:
- return b
- return B()
-
- def f7(c, a):
- if a:
- return a
- return 123
-
- def b_or_none(c):
- if c > 15:
- return B()
- return None
-
- def f(a, c):
- b = B()
- f1(a, b, c)
- f2(a, c, a, b)
- f3(space, b)
- r = lltype.malloc(RAW, flavor='raw')
- f4(r)
- f5(b)
- f6(b_or_none(c))
- f7(c, a)
-
- rtyper = support.annotate(f, [10, 20])
- f1_graph = rtyper.annotator.translator._graphof(f1)
- assert cc.find_call_shortcut(f1_graph) == CallShortcut(1, "foobardescr")
- f2_graph = rtyper.annotator.translator._graphof(f2)
- assert cc.find_call_shortcut(f2_graph) == CallShortcut(3, "foorefdescr")
- f3_graph = rtyper.annotator.translator._graphof(f3)
- assert cc.find_call_shortcut(f3_graph) == CallShortcut(0, "foobardescr")
- f4_graph = rtyper.annotator.translator._graphof(f4)
- assert cc.find_call_shortcut(f4_graph) == CallShortcut(0, "xdescr")
- f5_graph = rtyper.annotator.translator._graphof(f5)
- assert cc.find_call_shortcut(f5_graph) == CallShortcut(0, "foobardescr")
- f6_graph = rtyper.annotator.translator._graphof(f6)
- assert cc.find_call_shortcut(f6_graph) == CallShortcut(0, None)
- f7_graph = rtyper.annotator.translator._graphof(f7)
- assert cc.find_call_shortcut(f7_graph) == CallShortcut(1, None)
-
-def test_cant_find_call_shortcut():
- from rpython.jit.backend.llgraph.runner import LLGraphCPU
-
- @jit.dont_look_inside
- @jit.call_shortcut
- def f1(n):
- return n + 17 # no call shortcut found
-
- def f(n):
- return f1(n)
-
- rtyper = support.annotate(f, [1])
- jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
- cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
- res = cc.find_all_graphs(FakePolicy())
- [f_graph] = [x for x in res if x.func is f]
- call_op = f_graph.startblock.operations[0]
- assert call_op.opname == 'direct_call'
- e = py.test.raises(AssertionError, cc.getcalldescr, call_op)
- assert "shortcut not found" in str(e.value)
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -257,27 +257,6 @@
func.oopspec = "jit.not_in_trace()" # note that 'func' may take arguments
return func
-def call_shortcut(func):
- """A decorator to ensure that a function has a fast-path.
- DOES NOT RELIABLY WORK ON METHODS, USE ONLY ON FUNCTIONS!
-
- Only useful on functions that the JIT doesn't normally look inside.
- It still replaces residual calls to that function with inline code
- that checks for a fast path, and only does the call if not. For
- now, graphs made by the following kinds of functions are detected:
-
- def func(x, y, z): def func(x, y, z):
- if y.field: r = y.field
- return y.field if r is None:
- ... ...
- return r
-
- Fast-path detection is always on, but this decorator makes the
- codewriter complain if it cannot find the promized fast-path.
- """
- func._call_shortcut_ = True
- return func
-
@oopspec("jit.isconstant(value)")
@specialize.call_location()
More information about the pypy-commit
mailing list