[pypy-svn] r23461 - in pypy/dist/pypy/jit: . test
ac at codespeak.net
ac at codespeak.net
Fri Feb 17 19:49:51 CET 2006
Author: ac
Date: Fri Feb 17 19:49:50 2006
New Revision: 23461
Modified:
pypy/dist/pypy/jit/hinttimeshift.py
pypy/dist/pypy/jit/rtimeshift.py
pypy/dist/pypy/jit/test/test_hint_timeshift.py
Log:
(pedronis, arre)
Make splitting on a red variable and merging work.
Test test_loop_merging passes now.
The code needs cleanup. For now we don't drop the already unrolled
code blocks, this may need to change later.
It should be possible to extend what we have, after cleanup, to deal
with direct_calls.
Modified: pypy/dist/pypy/jit/hinttimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/hinttimeshift.py (original)
+++ pypy/dist/pypy/jit/hinttimeshift.py Fri Feb 17 19:49:50 2006
@@ -11,62 +11,139 @@
# ___________________________________________________________
+def define_queue_in_state(rtyper, s_item, fieldname):
+ queue_def = listdef.ListDef(None,
+ s_item)
+ queue_def.resize()
+ queue_def.mutate()
+
+ s_queue = annmodel.SomeList(queue_def)
+
+ r_queue = rtyper.getrepr(s_queue)
+ r_queue.setup()
+ QUEUE = r_queue.lowleveltype
+
+ def ll_get_queue(questate):
+ pass
+ def _ll_get_queue(questate):
+ return getattr(questate, fieldname)
+
+ llgetq = ll_get_queue
+
+ def ll_get_queue_annotation(queustate_s):
+ return s_queue
+
+ llgetq.compute_result_annotation = ll_get_queue_annotation
+
+ def ll_get_queue_specialize(hop):
+ return hop.gendirectcall(_ll_get_queue, hop.args_v[0])
+
+ llgetq.specialize = ll_get_queue_specialize
+
+ return s_queue, QUEUE, ll_get_queue
+
+
class HintTimeshift(object):
def __init__(self, hannotator, rtyper):
self.hannotator = hannotator
self.rtyper = rtyper
self.hrtyper = HintRTyper(hannotator, self)
+ self.latestexitindex = -1
+ getrepr = self.rtyper.getrepr
+
+ box_list_def = listdef.ListDef(None, annmodel.SomePtr(REDBOX_PTR))
+ box_list_def.mutate()
+ self.s_box_list = annmodel.SomeList(box_list_def)
+ self.r_box_list = getrepr(self.s_box_list)
+ self.r_box_list.setup()
+
+ box_accum_def = listdef.ListDef(None, annmodel.SomePtr(REDBOX_PTR))
+ box_accum_def.mutate()
+ box_accum_def.resize()
+ self.s_box_accum = annmodel.SomeList(box_accum_def)
+ self.r_box_accum = getrepr(self.s_box_accum)
+ self.r_box_accum.setup()
- # XXX refactor this more nicely
s_return_info = annmodel.SomeTuple([annmodel.SomePtr(rgenop.LINK),
annmodel.SomePtr(REDBOX_PTR)])
- returrn_queue_def = listdef.ListDef(None,
- s_return_info)
- returrn_queue_def.resize()
- returrn_queue_def.mutate()
-
- s_return_queue = annmodel.SomeList(returrn_queue_def)
-
- r_return_queue = rtyper.getrepr(s_return_queue)
- r_return_queue.setup()
- RETURN_QUEUE = r_return_queue.lowleveltype
-
- def ll_get_return_queue(questate):
- pass
- def _ll_get_return_queue(questate):
- return questate.return_queue
-
- llgetq = ll_get_return_queue
+ defs = define_queue_in_state(rtyper, s_return_info, 'return_queue')
+ s_return_queue, RETURN_QUEUE, ll_get_return_queue = defs
- def ll_get_return_queue_annotation(queustate_s):
- return s_return_queue
+ s_split_info = annmodel.SomeTuple([annmodel.SomeInteger(),
+ annmodel.SomePtr(STATE_PTR),
+ self.s_box_list])
- llgetq.compute_result_annotation = ll_get_return_queue_annotation
+ defs = define_queue_in_state(rtyper, s_split_info, 'split_queue')
+ s_split_queue, SPLIT_QUEUE, ll_get_split_queue = defs
- def ll_get_return_queue_specialize(hop):
- return hop.gendirectcall(_ll_get_return_queue, hop.args_v[0])
-
- llgetq.specialize = ll_get_return_queue_specialize
def ll_newstate():
questate = lltype.malloc(QUESTATE)
questate.return_queue = RETURN_QUEUE.TO.ll_newlist(0)
+ questate.split_queue = SPLIT_QUEUE.TO.ll_newlist(0)
return questate
+
+ def ll_copystate(questate):
+ newquestate = lltype.malloc(QUESTATE)
+ newquestate.return_queue = questate.return_queue
+ newquestate.split_queue = questate.split_queue
+ basestate = questate.basestate
+ newbasestate = newquestate.basestate
+ newbasestate.curblock = basestate.curblock
+ newbasestate.curoutgoinglink = basestate.curoutgoinglink
+ newbasestate.curvalue = basestate.curvalue
+ return newquestate
- QUESTATE = lltype.GcStruct("quejistate",
+ QUESTATE = lltype.GcStruct("quejitstate",
('basestate', STATE),
("return_queue", RETURN_QUEUE),
+ ("split_queue", SPLIT_QUEUE),
adtmeths = {
'll_get_return_queue': ll_get_return_queue,
+ 'll_get_split_queue': ll_get_split_queue,
'll_newstate': ll_newstate,
+ 'll_copystate': ll_copystate,
'll_basestate': lambda questate: questate.basestate})
self.s_return_queue = s_return_queue # for the test
self.QUESTATE_PTR = lltype.Ptr(QUESTATE)
-
+
+ def getexitindex(self, link, inputargs, args_r):
+ self.latestexitindex += 1
+ v_jitstate = flowmodel.Variable('jitstate')
+ v_jitstate.concretetype = STATE_PTR
+ v_boxes = flowmodel.Variable('boxes')
+ v_boxes.concretetype = self.r_box_accum.lowleveltype
+
+ reentry_block = flowmodel.Block([v_jitstate, v_boxes])
+
+ llops = HintLowLevelOpList(self, None)
+
+ reenter_vars = [v_jitstate]
+ for var in link.args[1:]:
+ i = inputargs.index(var)
+ r = args_r[i]
+ v_box = self.read_out_box(llops, v_boxes, i)
+ if isinstance(r, RedRepr):
+ reenter_vars.append(v_box)
+ else:
+ c_TYPE = rmodel.inputconst(lltype.Void,
+ r.lowleveltype)
+ v_value = llops.gendirectcall(REDBOX_PTR.TO.ll_getvalue,
+ v_box, c_TYPE)
+ reenter_vars.append(v_value)
+
+ reenter_link = flowmodel.Link(reenter_vars, link.target)
+ reentry_block.operations[:] = llops
+ reentry_block.closeblock(reenter_link)
+
+ from_dispatch =flowmodel.Link([None, None], reentry_block)
+ self.dispatch_to.append((self.latestexitindex, from_dispatch))
+ return self.latestexitindex
+
def timeshift(self):
for graph in self.hannotator.translator.graphs:
self.timeshift_graph(graph)
@@ -75,6 +152,7 @@
def timeshift_graph(self, graph):
self.graph = graph
+ self.dispatch_to = []
entering_links = flowmodel.mkentrymap(graph)
originalblocks = list(graph.iterblocks())
@@ -119,10 +197,7 @@
if link.target.operations != ():
link.args.insert(0, v_jitstate)
elif len(link.args) == 1:
- link.args[0] = v_jitstate
- v_returnjitstate = flowmodel.Variable('jitstate')
- self.hannotator.bindings[v_returnjitstate] = s_JITState
- link.target.inputargs = [v_returnjitstate]
+ assert False, "the return block should not be seen"
def insert_before_block(self, block, entering_links, closeblock=True):
newinputargs = []
@@ -145,17 +220,41 @@
newblock.closeblock(bridge)
return newblock
+ def read_out_box(self, llops, v_boxes, i):
+ c_dum_nocheck = rmodel.inputconst(lltype.Void, rlist.dum_nocheck)
+ c_i = rmodel.inputconst(lltype.Signed, i)
+ v_box = llops.gendirectcall(rlist.ll_getitem_nonneg,
+ c_dum_nocheck,
+ v_boxes,
+ c_i)
+ return v_box
+
+ def insert_read_out_boxes(self, bridge, llops, v_newjitstate, v_boxes, args_r, newinputargs):
+ newinputargs2 = [v_newjitstate]
+ if bridge.target.operations == (): # special case the return block
+ assert False, "the return block should not be seen"
+ else:
+ i = 0
+ for r, newvar in zip(args_r[1:], newinputargs[1:]):
+ if isinstance(r, RedRepr):
+ newinputargs2.append(self.read_out_box(llops, v_boxes, i))
+ i += 1
+ else:
+ newinputargs2.append(newvar)
+
+ # patch bridge
+ bridge.args = newinputargs2 # patch the link
+
+
def insert_bookkeeping_enter(self, block, before_block, nentrylinks):
newinputargs = before_block.inputargs
args_r = []
for var in newinputargs:
- hs = self.hannotator.bindings[var]
- args_r.append(self.hrtyper.getrepr(hs))
+ args_r.append(self.hrtyper.bindingrepr(var))
llops = HintLowLevelOpList(self, None)
- s_box_list = annmodel.SomeList(listdef.ListDef(None,
- annmodel.SomePtr(REDBOX_PTR)))
+
TYPES = []
boxes_v = []
for r, newvar in zip(args_r, newinputargs):
@@ -164,9 +263,8 @@
TYPES.append(r.original_concretetype)
getrepr = self.rtyper.getrepr
- r_box_list = getrepr(s_box_list)
- r_box_list.setup()
- v_boxes = rlist.newlist(llops, r_box_list, boxes_v)
+ # XXX factor this out too!
+ v_boxes = rlist.newlist(llops, self.r_box_list, boxes_v)
c_TYPES = rmodel.inputconst(VARLIST, make_types_const(TYPES))
@@ -177,55 +275,26 @@
# fill the block with logic
- v_newjitstate = enter_block_logic(args_r, newinputargs,
- llops,
- s_box_list, v_boxes,
- c_TYPES)
-
- def read_out_box(i):
- c_dum_nocheck = rmodel.inputconst(lltype.Void, rlist.dum_nocheck)
- c_i = rmodel.inputconst(lltype.Signed, i)
- v_box = llops.gendirectcall(rlist.ll_getitem_nonneg,
- c_dum_nocheck,
- v_boxes,
- c_i)
- return v_box
-
+ enter_block_logic(args_r, newinputargs,
+ before_block,
+ llops,
+ v_boxes,
+ c_TYPES)
+
- bridge = before_block.exits[0]
- newinputargs2 = [v_newjitstate]
- if bridge.target.operations == (): # special case the return block
- # XXX maybe better to return a tuple (state, value)?
- c_curvalue = rmodel.inputconst(lltype.Void, "curvalue")
- if isinstance(args_r[1], GreenRepr):
- v_value = llops.gendirectcall(rtimeshift.REDBOX.ll_make_from_const,
- newinputargs[1])
- else:
- v_value = read_out_box(0)
- llops.genop('setfield', [v_newjitstate, c_curvalue, v_value])
- else:
- i = 0
- for r, newvar in zip(args_r[1:], newinputargs[1:]):
- if isinstance(r, RedRepr):
- newinputargs2.append(read_out_box(i))
- i += 1
- else:
- newinputargs2.append(newvar)
- # patch before block and bridge
- before_block.operations[:] = llops
- bridge.args = newinputargs2 # patch the link
- def bookkeeping_enter_simple(self, args_r, newinputargs, llops, s_box_list, v_boxes,
+ def bookkeeping_enter_simple(self, args_r, newinputargs, before_block, llops, v_boxes,
c_TYPES):
- v_newjiststate = llops.genmixlevelhelpercall(rtimeshift.enter_block,
- [annmodel.SomePtr(STATE_PTR), s_box_list,
+ v_newjitstate = llops.genmixlevelhelpercall(rtimeshift.enter_block,
+ [annmodel.SomePtr(STATE_PTR), self.s_box_list,
annmodel.SomePtr(VARLIST)],
[newinputargs[0], v_boxes, c_TYPES])
- return v_newjiststate
-
-
+ bridge = before_block.exits[0]
+ self.insert_read_out_boxes(bridge, llops, v_newjitstate, v_boxes, args_r, newinputargs)
+ before_block.operations[:] = llops
+
# insert before join blocks a block with:
# key = (<tuple-of-green-values>)
# boxes = [<rest-of-redboxes>]
@@ -236,7 +305,7 @@
# ll_retrieve_jitstate_for_merge is supposed to use the "constant" dict as cache
# mapping green values combinations to frozen states for red boxes values
# and generated blocks
- def bookkeeping_enter_for_join(self, args_r, newinputargs, llops, s_box_list, v_boxes,
+ def bookkeeping_enter_for_join(self, args_r, newinputargs, before_block, llops, v_boxes,
c_TYPES):
getrepr = self.rtyper.getrepr
items_s = []
@@ -253,7 +322,7 @@
s_key_tuple = annmodel.SomeTuple(items_s)
- s_dict_value = annmodel.SomeTuple([s_box_list,
+ s_dict_value = annmodel.SomeTuple([self.s_box_list,
annmodel.SomePtr(rgenop.BLOCK)])
s_state_dic = annmodel.SomeDict(dictdef.DictDef(None,
s_key_tuple,
@@ -271,13 +340,58 @@
v_key = rtuple.newtuple(llops, r_key, key_v)
+ v_oldjitstate = newinputargs[0]
- v_newjiststate = llops.genmixlevelhelpercall(rtimeshift.retrieve_jitstate_for_merge,
- [s_state_dic, annmodel.SomePtr(STATE_PTR), s_key_tuple, s_box_list,
+ v_newjitstate = llops.genmixlevelhelpercall(rtimeshift.retrieve_jitstate_for_merge,
+ [s_state_dic, annmodel.SomePtr(STATE_PTR), s_key_tuple, self.s_box_list,
annmodel.SomePtr(VARLIST)],
- [c_state_dic, newinputargs[0], v_key, v_boxes, c_TYPES])
- return v_newjiststate
+ [c_state_dic, v_oldjitstate, v_key, v_boxes, c_TYPES])
+
+ v_continue = llops.genop('ptr_nonzero', [v_newjitstate], resulttype=lltype.Bool)
+
+ v_newjitstate2 = flowmodel.Variable(v_newjitstate)
+ v_newjitstate2.concretetype = STATE_PTR
+ v_boxes2 = flowmodel.Variable(v_boxes)
+ v_boxes2.concretetype = self.r_box_list.lowleveltype
+
+
+
+ read_boxes_block_vars = [v_newjitstate2, v_boxes2]
+ for greenvar in key_v:
+ greenvar2 = flowmodel.Variable(greenvar)
+ greenvar2.concretetype = greenvar.concretetype
+ read_boxes_block_vars.append(greenvar2)
+
+ read_boxes_block = flowmodel.Block(read_boxes_block_vars)
+ to_read_boxes_block = flowmodel.Link([v_newjitstate, v_boxes] + key_v, read_boxes_block)
+ to_read_boxes_block.exitcase = to_read_boxes_block.llexitcase = True
+ to_dispatch_block = flowmodel.Link([v_oldjitstate], self.dispatchblock)
+ to_dispatch_block.exitcase = to_dispatch_block.llexitcase = False
+ target = before_block.exits[0].target
+ before_block.operations[:] = llops
+ before_block.exitswitch = v_continue
+ before_block.recloseblock(to_dispatch_block, to_read_boxes_block)
+
+ llops = HintLowLevelOpList(self, None)
+
+ newinputargs2 = [v_newjitstate2]
+ i = 0
+ j = 0
+ for r in args_r[1:]:
+ if isinstance(r, RedRepr):
+ newinputargs2.append(self.read_out_box(llops, v_boxes2, i))
+ i += 1
+ else:
+ newinputargs2.append(read_boxes_block_vars[j+2])
+ j += 1
+
+ read_boxes_block.operations[:] = llops
+
+ to_target = flowmodel.Link(newinputargs2, target)
+
+ read_boxes_block.closeblock(to_target)
+
def insert_bookkeeping_leave_block(self, block, entering_links):
# XXX wrong with exceptions as much else
@@ -290,6 +404,7 @@
if isinstance(v, flowmodel.Variable):
if v not in renamemap:
vprime = renamemap[v] = flowmodel.Variable(v)
+ self.hannotator.bindings[vprime] = self.hannotator.bindings[v]
vprime.concretetype = v.concretetype
inargs.append(v)
@@ -299,6 +414,7 @@
newlinks = []
v_newjitstate = flowmodel.Variable('jitstate')
+ self.hannotator.bindings[v_newjitstate] = s_JITState
v_newjitstate.concretetype = STATE_PTR
def rename_on_link(v):
@@ -311,6 +427,7 @@
for v in link.args:
introduce(v)
newlink = link.copy(rename_on_link)
+ newlink.llexitcase = newlink.exitcase # sanitize the link llexitcase
newlinks.append(newlink)
target = link.target
# update entering_links as necessary
@@ -322,24 +439,58 @@
inputargs = [rename(v) for v in inargs]
newblock = flowmodel.Block(inputargs)
- newblock.exitswitch = rename(block.exitswitch)
newblock.closeblock(*newlinks)
inlink = flowmodel.Link(inargs, newblock)
-
+ oldexitswitch = block.exitswitch
block.exitswitch = None
block.recloseblock(inlink)
llops = HintLowLevelOpList(self, None)
+ if len(newblock.exits) == 1 or isinstance(self.hrtyper.bindingrepr(oldexitswitch), GreenRepr):
+ newblock.exitswitch = rename(oldexitswitch)
+ v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block,
+ [annmodel.SomePtr(STATE_PTR)],
+ [rename(orig_v_jitstate)])
+
+ llops.append(flowmodel.SpaceOperation('same_as',
+ [v_res],
+ v_newjitstate))
+ else:
+ args_r = []
+ boxes_v = []
+ for var in inputargs[1:]:
+ r = self.hrtyper.bindingrepr(var)
+ args_r.append(r)
+ if isinstance(r, RedRepr):
+ boxes_v.append(var)
+ elif isinstance(r, GreenRepr):
+ boxes_v.append(llops.gendirectcall(rtimeshift.REDBOX.ll_make_from_const, var))
+ else:
+ raise RuntimeError('Unsupported boxtype')
+
+ getrepr = self.rtyper.getrepr
- v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block,
- [annmodel.SomePtr(STATE_PTR)],
- [rename(orig_v_jitstate)])
-
- llops.append(flowmodel.SpaceOperation('same_as',
- [v_res],
- v_newjitstate))
-
+ v_boxes = rlist.newlist(llops, self.r_box_list, boxes_v)
+ false_exit = [exit for exit in newblock.exits if exit.exitcase is False][0]
+ exitindex = self.getexitindex(false_exit, inputargs[1:], args_r)
+ c_exitindex = rmodel.inputconst(lltype.Signed, exitindex)
+ v_jitstate = rename(orig_v_jitstate)
+ v_quejitstate = llops.genop('cast_pointer', [v_jitstate],
+ resulttype=self.QUESTATE_PTR)
+ v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split,
+ [annmodel.SomePtr(self.QUESTATE_PTR),
+ annmodel.SomePtr(REDBOX_PTR),
+ annmodel.SomeInteger(),
+ self.s_box_list],
+ [v_quejitstate,
+ rename(oldexitswitch),
+ c_exitindex,
+ v_boxes])
+ llops.append(flowmodel.SpaceOperation('same_as',
+ [inputargs[0]],
+ v_newjitstate))
+ newblock.exitswitch = v_res
newblock.operations[:] = llops
def insert_return_bookkeeping(self, before_returnblock):
@@ -366,24 +517,20 @@
dispatchblock = self.dispatchblock
[v_jitstate] = dispatchblock.inputargs
llops = HintLowLevelOpList(self, None)
- s_box_list = annmodel.SomeList(listdef.ListDef(None,
- annmodel.SomePtr(REDBOX_PTR)))
- getrepr = self.rtyper.getrepr
- r_box_list = getrepr(s_box_list)
- r_box_list.setup()
- v_boxes = rlist.newlist(llops, r_box_list, [])
+
+ v_boxes = rlist.newlist(llops, self.r_box_accum, [])
v_quejitstate = llops.genop('cast_pointer', [v_jitstate],
resulttype=self.QUESTATE_PTR)
v_next = llops.genmixlevelhelpercall(rtimeshift.dispatch_next,
- [annmodel.SomePtr(self.QUESTATE_PTR), s_box_list],
+ [annmodel.SomePtr(self.QUESTATE_PTR), self.s_box_accum],
[v_quejitstate, v_boxes])
dispatchblock.operations[:] = llops
- dispatch_to = []
+ dispatch_to = self.dispatch_to
finishedlink = flowmodel.Link([v_jitstate], returnblock)
dispatch_to.append(('default', finishedlink))
@@ -393,7 +540,12 @@
dispatchblock.exitswitch = v_next
exitlinks = []
for case, link in dispatch_to:
- link.exitcase = link.llexitcase = case
+ link.exitcase = case
+ if case != 'default':
+ link.llexitcase = case
+ link.args = [v_jitstate, v_boxes]
+ else:
+ link.llexitcase = None
exitlinks.append(link)
dispatchblock.closeblock(*exitlinks)
Modified: pypy/dist/pypy/jit/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/rtimeshift.py Fri Feb 17 19:49:50 2006
@@ -180,6 +180,7 @@
ll_getvalue(newbox, lltype.Signed)):
continue
# Missmatch. Generalize to a var
+ break
else:
rgenop.closelink(jitstate.curoutgoinglink, incoming, oldblock)
return lltype.nullptr(STATE)
@@ -226,6 +227,22 @@
jitstate.curoutgoinglink = rgenop.closeblock1(jitstate.curblock)
return jitstate
+def leave_block_split(quejitstate, switchredbox, exitindex, redboxes):
+ jitstate = lltype.cast_pointer(STATE_PTR, quejitstate)
+ if not switchredbox.isvar:
+ jitstate.curoutgoinglink = rgenop.closeblock1(jitstate.curblock)
+ return switchredbox.ll_getvalue(lltype.Bool)
+ exitgvar = switchredbox.genvar
+ linkpair = rgenop.closeblock2(jitstate.curblock, exitgvar)
+ false_link, true_link = linkpair.item0, linkpair.item1
+ later_jitstate = quejitstate.ll_copystate()
+ later_jitstate = lltype.cast_pointer(STATE_PTR, later_jitstate)
+ jitstate.curoutgoinglink = true_link
+ later_jitstate.curoutgoinglink = false_link
+ quejitstate.ll_get_split_queue().append((exitindex, later_jitstate, redboxes))
+ return True
+
+
def schedule_return(jitstate, redbox):
return_queue = jitstate.ll_get_return_queue()
curoutgoinglink = jitstate.ll_basestate().curoutgoinglink
@@ -234,6 +251,16 @@
novars = lltype.malloc(VARLIST.TO, 0)
def dispatch_next(jitstate, outredboxes):
+ basestate = jitstate.ll_basestate()
+ split_queue = jitstate.ll_get_split_queue()
+ if split_queue:
+ exitindex, later_jitstate, redboxes = split_queue.pop()
+ basestate.curblock = later_jitstate.curblock
+ basestate.curoutgoinglink = later_jitstate.curoutgoinglink
+ basestate.curvalue = later_jitstate.curvalue
+ for box in redboxes:
+ outredboxes.append(box)
+ return exitindex
return_queue = jitstate.ll_get_return_queue()
basestate = jitstate.ll_basestate()
first_redbox = return_queue[0][1]
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 17 19:49:50 2006
@@ -162,7 +162,6 @@
assert insns == {}
def test_loop_merging():
- py.test.skip('Work in progress')
def ll_function(x, y):
tot = 0
while x:
@@ -171,4 +170,20 @@
return tot
insns, res = timeshift(ll_function, [7, 2], [])
assert res == 14
- # assert insns == {}
+ assert insns['int_add'] == 2
+ assert insns['int_is_true'] == 2
+
+ insns, res = timeshift(ll_function, [7, 2], [0])
+ assert res == 14
+ assert insns['int_add'] == 2
+ assert insns['int_is_true'] == 1
+
+ insns, res = timeshift(ll_function, [7, 2], [1])
+ assert res == 14
+ assert insns['int_add'] == 1
+ assert insns['int_is_true'] == 2
+
+ insns, res = timeshift(ll_function, [7, 2], [0, 1])
+ assert res == 14
+ assert insns['int_add'] == 1
+ assert insns['int_is_true'] == 1
More information about the Pypy-commit
mailing list