[pypy-commit] pypy conditional_call_value_4: copy and adapt from the conditional_call_value_2 branch: goal
arigo
pypy.commits at gmail.com
Tue Nov 22 05:52:54 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: conditional_call_value_4
Changeset: r88540:c73bebe15c32
Date: 2016-11-22 11:52 +0100
http://bitbucket.org/pypy/pypy/changeset/c73bebe15c32/
Log: copy and adapt from the conditional_call_value_2 branch: goal
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -1194,10 +1194,19 @@
return hop.gendirectcall(ll_record_exact_class, v_inst, v_cls)
def _jit_conditional_call(condition, function, *args):
- pass
+ pass # special-cased below
@specialize.call_location()
def conditional_call(condition, function, *args):
+ """Does the same as:
+
+ if condition:
+ function(*args)
+
+ but is better for the JIT, in case the condition is often false
+ but could be true occasionally. It allows the JIT to always produce
+ bridge-free code. The function is never looked inside.
+ """
if we_are_jitted():
_jit_conditional_call(condition, function, *args)
else:
@@ -1205,21 +1214,58 @@
function(*args)
conditional_call._always_inline_ = True
+def _jit_conditional_call_value(value, function, *args):
+ return value # special-cased below
+
+ at specialize.call_location()
+def conditional_call_value(value, function, *args):
+ """Does the same as:
+
+ if not value:
+ value = function(*args)
+ return value
+
+ For the JIT. Allows one branch which doesn't create a bridge,
+ typically used for caching. The function must be @elidable.
+ The value and the function's return type must match and cannot
+ be a float.
+ """
+ if we_are_jitted():
+ return _jit_conditional_call_value(value, function, *args)
+ else:
+ if not value:
+ value = function(*args)
+ return value
+conditional_call_value._always_inline_ = True
+
class ConditionalCallEntry(ExtRegistryEntry):
- _about_ = _jit_conditional_call
+ _about_ = _jit_conditional_call, _jit_conditional_call_value
def compute_result_annotation(self, *args_s):
- self.bookkeeper.emulate_pbc_call(self.bookkeeper.position_key,
- args_s[1], args_s[2:])
+ s_res = self.bookkeeper.emulate_pbc_call(self.bookkeeper.position_key,
+ args_s[1], args_s[2:])
+ if self.instance == _jit_conditional_call_value:
+ from rpython.annotator import model as annmodel
+ return annmodel.unionof(s_res, args_s[0])
def specialize_call(self, hop):
from rpython.rtyper.lltypesystem import lltype
- args_v = hop.inputargs(lltype.Bool, lltype.Void, *hop.args_r[2:])
+ if self.instance == _jit_conditional_call:
+ opname = 'jit_conditional_call'
+ COND = lltype.Bool
+ resulttype = None
+ elif self.instance == _jit_conditional_call_value:
+ opname = 'jit_conditional_call_value'
+ COND = hop.r_result
+ resulttype = hop.r_result.lowleveltype
+ else:
+ assert False
+ args_v = hop.inputargs(COND, lltype.Void, *hop.args_r[2:])
args_v[1] = hop.args_r[1].get_concrete_llfn(hop.args_s[1],
hop.args_s[2:], hop.spaceop)
hop.exception_is_here()
- return hop.genop('jit_conditional_call', args_v)
+ return hop.genop(opname, args_v, resulttype=resulttype)
def enter_portal_frame(unique_id):
"""call this when starting to interpret a function. calling this is not
diff --git a/rpython/rlib/test/test_jit.py b/rpython/rlib/test/test_jit.py
--- a/rpython/rlib/test/test_jit.py
+++ b/rpython/rlib/test/test_jit.py
@@ -3,7 +3,7 @@
from rpython.conftest import option
from rpython.annotator.model import UnionError
from rpython.rlib.jit import (hint, we_are_jitted, JitDriver, elidable_promote,
- JitHintError, oopspec, isconstant, conditional_call,
+ JitHintError, oopspec, isconstant, conditional_call, conditional_call_value,
elidable, unroll_safe, dont_look_inside,
enter_portal_frame, leave_portal_frame)
from rpython.rlib.rarithmetic import r_uint
@@ -302,6 +302,18 @@
mix.getgraph(later, [annmodel.s_Bool], annmodel.s_None)
mix.finish()
+ def test_conditional_call_value(self):
+ def g(x, y):
+ return x - y + 5
+ def f(n, x, y):
+ return conditional_call_value(n, g, x, y)
+ assert f(0, 1000, 100) == 905
+ res = self.interpret(f, [0, 1000, 100])
+ assert res == 905
+ assert f(-42, 1000, 100) == -42
+ res = self.interpret(f, [-42, 1000, 100])
+ assert res == -42
+
def test_enter_leave_portal_frame(self):
from rpython.translator.interactive import Translation
def g():
More information about the pypy-commit
mailing list