Author: Richard Plangger <r...@pasra.at> Branch: vecopt2 Changeset: r77115:0b90aa19f600 Date: 2015-04-16 13:01 +0200 http://bitbucket.org/pypy/pypy/changeset/0b90aa19f600/
Log: tested and adapted the trace optimizer for loops. trace jump targets are correctly set and the vec. optimizer avoids the unroller added vec_int_signext diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -563,14 +563,6 @@ else: return self.bh_raw_load_i(struct, offset, descr) - def bh_vec_raw_load(self, struct, offset, count, descr): - values = [] - stride = descr.get_item_size_in_bytes() - for i in range(count): - val = self.bh_raw_load(struct, offset + i*stride, descr) - values.append(val) - return values - def bh_increment_debug_counter(self, addr): p = rffi.cast(rffi.CArrayPtr(lltype.Signed), addr) p[0] += 1 @@ -603,11 +595,6 @@ else: self.bh_raw_store_i(struct, offset, newvalue, descr) - def bh_vec_raw_store(self, struct, offset, newvalues, count, descr): - stride = descr.get_item_size_in_bytes() - for i in range(count): - self.bh_raw_store(struct, offset + i*stride, newvalues[i], descr) - def bh_newstr(self, length): return lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(rstr.STR, length, @@ -678,6 +665,39 @@ def bh_new_raw_buffer(self, size): return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + # vector operations + def bh_vec_int_add(self, vx, vy, count): + assert len(vx) == count + assert len(vy) == count + return [_vx + _vy for _vx,_vy in zip(vx,vy)] + + def bh_vec_int_mul(self, vx, vy, count): + assert len(vx) == count + assert len(vy) == count + return [_vx * _vy for _vx,_vy in zip(vx,vy)] + + def bh_vec_int_sub(self, vx, vy, count): + assert len(vx) == count + assert len(vy) == count + return [_vx - _vy for _vx,_vy in zip(vx,vy)] + + def bh_vec_int_signext(self, vx, ext, count): + return [heaptracker.int_signext(_vx, ext) for _vx in vx] + + def bh_vec_raw_load(self, struct, offset, count, descr): + values = [] + stride = descr.get_item_size_in_bytes() + for i in range(count): + val = self.bh_raw_load(struct, offset + i*stride, descr) + values.append(val) + return values + + def bh_vec_raw_store(self, struct, offset, newvalues, count, descr): + stride = descr.get_item_size_in_bytes() + for i in range(count): + self.bh_raw_store(struct, offset + i*stride, newvalues[i], descr) + + def store_fail_descr(self, deadframe, descr): pass # I *think* @@ -826,6 +846,10 @@ argboxes = self.current_op.getarglist() self.do_renaming(argboxes, args) + def execute_guard_no_early_exit(self, descr): + # TODO + pass + def execute_guard_true(self, descr, arg): if not arg: self.fail_guard(descr) @@ -930,15 +954,6 @@ if not self.overflow_flag: self.fail_guard(descr) - def execute_vec_int_add(self, _, vx, vy): - return [_vx + _vy for _vx,_vy in zip(vx,vy)] - - def execute_vec_int_mul(self, _, vx, vy): - return [_vx * _vy for _vx,_vy in zip(vx,vy)] - - def execute_vec_int_sub(self, _, vx, vy): - return [_vx - _vy for _vx,_vy in zip(vx,vy)] - def execute_jump(self, descr, *args): raise Jump(descr._llgraph_target, args) diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -1482,6 +1482,8 @@ # if opnum == rop.GUARD_FUTURE_CONDITION: pass + elif opnum == rop.GUARD_NO_EARLY_EXIT: + self.position = 0 elif opnum == rop.GUARD_TRUE: # Produced directly by some goto_if_not_xxx() opcode that did not # jump, but which must now jump. The pc is just after the opcode. diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -685,6 +685,9 @@ class ResumeAtPositionDescr(ResumeGuardDescr): guard_opnum = rop.GUARD_FUTURE_CONDITION +class ResumeAtEarylExitDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NO_EARLY_EXIT + class AllVirtuals: llopaque = True cache = None @@ -773,7 +776,7 @@ elif opnum == rop.GUARD_FUTURE_CONDITION: resumedescr = ResumeAtPositionDescr() elif opnum == rop.GUARD_NO_EARLY_EXIT: - resumedescr = ResumeAtPositionDescr() + resumedescr = ResumeAtEarylExitDescr() elif opnum == rop.GUARD_VALUE: resumedescr = ResumeGuardValueDescr() elif opnum == rop.GUARD_NONNULL: diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py b/rpython/jit/metainterp/optimizeopt/dependency.py --- a/rpython/jit/metainterp/optimizeopt/dependency.py +++ b/rpython/jit/metainterp/optimizeopt/dependency.py @@ -1,4 +1,6 @@ import py + +from rpython.jit.metainterp.compile import ResumeAtEarylExitDescr from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method from rpython.jit.metainterp.resoperation import rop from rpython.jit.codewriter.effectinfo import EffectInfo @@ -77,14 +79,29 @@ def getindex(self): return self.opidx - def dependency_count(self): - return len(self.adjacent_list) - def getopnum(self): return self.op.getopnum() def getopname(self): return self.op.getopname() + def getfailarg_set(self): + args = set() + op = self.getoperation() + if op.getfailargs(): + for arg in op.getfailargs(): + args.add(arg) + return args + elif op.rd_snapshot: + ss = op.rd_snapshot + while ss != None: + for box in ss.boxes: + args.add(box) + ss = ss.prev + + return args + #set(target_guard.getoperation().getfailargs()) + + def relax_guard_to(self, guard): """ Relaxes a guard operation to an earlier guard. """ assert self.op.is_guard() @@ -92,7 +109,8 @@ my_op = self.getoperation() op = guard.getoperation() - my_op.setdescr(op.getdescr()) + my_op.setdescr(ResumeAtEarylExitDescr()) + print "set ", my_op.getdescr(), "=>", op.getdescr() my_op.setfailargs(op.getfailargs()) my_op.rd_snapshot = op.rd_snapshot @@ -116,16 +134,6 @@ _label = getattr(dep, 'label', '') dep.label = _label + ", " + label - def depends_on(self, to): - """ Does there exist a dependency from the instruction to another? - Returns None if there is no dependency or the Dependency object in - any other case. - """ - for edge in self.adjacent_list: - if edge.to == to: - return edge - return None - def clear_dependencies(self): self.adjacent_list = [] self.adjacent_list_back = [] @@ -176,6 +184,16 @@ def depends(self): return self.adjacent_list_back + def depends_on(self, to): + """ Does there exist a dependency from the instruction to another? + Returns None if there is no dependency or the Dependency object in + any other case. + """ + for edge in self.adjacent_list: + if edge.to == to: + return edge + return None + def dependencies(self): return self.adjacent_list[:] + self.adjacent_list_back[:] # COPY @@ -444,10 +462,9 @@ # pass 3 find schedulable nodes jump_node = self.nodes[jump_pos] label_node = self.nodes[label_pos] - self.schedulable_nodes.append(label_node) for node in self.nodes: if node != jump_node: - if node.dependency_count() == 0: + if node.depends_count() == 0: self.schedulable_nodes.append(node) # every leaf instruction points to the jump_op. in theory every instruction # points to jump_op. this forces the jump/finish op to be the last operation @@ -633,15 +650,16 @@ def schedule(self, index): node = self.schedulable_nodes[index] - assert not node.emitted + assert not node.emitted, "node " + str(node) + " cannot be emitted twice! op: " + str(node.getoperation()) del self.schedulable_nodes[index] to_del = [] print " schedule", node.getoperation() for dep in node.provides()[:]: # COPY - node.remove_edge_to(dep.to) - print " >=X=>", node, dep.to, "count",dep.to.depends_count() - if dep.to.depends_count() == 0: - self.schedulable_nodes.append(dep.to) + to = dep.to + node.remove_edge_to(to) + print " >=X=>", node, to, "count",to.depends_count() + if not to.emitted and to.depends_count() == 0: + self.schedulable_nodes.append(to) node.clear_dependencies() node.emitted = True diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -796,7 +796,9 @@ assert pendingfields is not None if op.getdescr() is not None: descr = op.getdescr() - assert isinstance(descr, compile.ResumeAtPositionDescr) + assert isinstance(descr, compile.ResumeAtPositionDescr) or \ + isinstance(descr, compile.ResumeAtEarylExitDescr) + else: descr = compile.invent_fail_descr_for_op(op.getopnum(), self) op.setdescr(descr) diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py b/rpython/jit/metainterp/optimizeopt/vectorize.py --- a/rpython/jit/metainterp/optimizeopt/vectorize.py +++ b/rpython/jit/metainterp/optimizeopt/vectorize.py @@ -1,7 +1,8 @@ import sys import py from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.jit.metainterp.history import ConstInt, VECTOR, BoxVector +from rpython.jit.metainterp.history import (ConstInt, VECTOR, BoxVector, + TargetToken, JitCellToken) from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer, Optimization from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph, @@ -57,17 +58,24 @@ self.memory_refs = [] self.dependency_graph = None self.first_debug_merge_point = False - self.last_debug_merge_point = None self.packset = None self.unroll_count = 0 self.smallest_type_bytes = 0 def propagate_all_forward(self): self.clear_newoperations() + label = self.loop.operations[0] + jump = self.loop.operations[-1] + if jump.getopnum() != rop.LABEL: + # compile_loop appends a additional label to all loops + # we cannot optimize normal traces + raise NotAVectorizeableLoop() + self.linear_find_smallest_type(self.loop) byte_count = self.smallest_type_bytes - if byte_count == 0: + if byte_count == 0 or label.getopnum() != rop.LABEL: # stop, there is no chance to vectorize this trace + # we cannot optimize normal traces (if there is no label) raise NotAVectorizeableLoop() # unroll @@ -88,15 +96,8 @@ self._newoperations.append(op) def emit_unrolled_operation(self, op): - if op.getopnum() == rop.DEBUG_MERGE_POINT: - self.last_debug_merge_point = op - if not self.first_debug_merge_point: - self.first_debug_merge_point = True - else: - return False self._last_emitted_op = op self._newoperations.append(op) - return True def unroll_loop_iterations(self, loop, unroll_count): """ Unroll the loop X times. unroll_count is an integral how @@ -104,10 +105,12 @@ """ op_count = len(loop.operations) - label_op = loop.operations[0] - jump_op = loop.operations[op_count-1] + label_op = loop.operations[0].clone() + jump_op = loop.operations[op_count-1].clone() + # use the target token of the label + jump_op = ResOperation(rop.JUMP, jump_op.getarglist(), None, label_op.getdescr()) assert label_op.getopnum() == rop.LABEL - assert jump_op.is_final() or jump_op.getopnum() == rop.LABEL + assert jump_op.is_final() # XXX self.vec_info.track_memory_refs = True @@ -124,8 +127,6 @@ op = loop.operations[i].clone() operations.append(op) self.emit_unrolled_operation(op) - #self.vec_info.index = len(self._newoperations)-1 - #self.vec_info.inspect_operation(op) orig_jump_args = jump_op.getarglist()[:] # it is assumed that #label_args == #jump_args @@ -167,14 +168,15 @@ copied_op.rd_snapshot = snapshot if not we_are_translated(): # ensure that in a test case the renaming is correct - args = copied_op.getfailargs()[:] - for i,arg in enumerate(args): - try: - value = rename_map[arg] - args[i] = value - except KeyError: - pass - copied_op.setfailargs(args) + if copied_op.getfailargs(): + args = copied_op.getfailargs()[:] + for i,arg in enumerate(args): + try: + value = rename_map[arg] + args[i] = value + except KeyError: + pass + copied_op.setfailargs(args) # self.emit_unrolled_operation(copied_op) @@ -189,9 +191,6 @@ except KeyError: pass - if self.last_debug_merge_point is not None: - self._last_emitted_op = self.last_debug_merge_point - self._newoperations.append(self.last_debug_merge_point) self.emit_unrolled_operation(jump_op) def clone_snapshot(self, snapshot, rename_map): @@ -335,10 +334,10 @@ print " P:", pack def schedule(self): + print self.dependency_graph.as_dot() self.clear_newoperations() scheduler = Scheduler(self.dependency_graph, VecScheduleData()) - print "scheduling loop" - i = 100 + print "scheduling loop. scheduleable are: " + str(scheduler.schedulable_nodes) while scheduler.has_more(): candidate = scheduler.next() print " candidate", candidate, "has pack?", candidate.pack != None, "pack", candidate.pack @@ -353,9 +352,6 @@ else: self.emit_operation(candidate.getoperation()) scheduler.schedule(0) - i += 1 - if i > 200: - assert False self.loop.operations = self._newoperations[:] if not we_are_translated(): @@ -415,8 +411,8 @@ return False def fail_args_break_dependency(guard, prev_op, target_guard): - failargs = set(guard.getoperation().getfailargs()) - new_failargs = set(target_guard.getoperation().getfailargs()) + failargs = guard.getfailarg_set() + new_failargs = target_guard.getfailarg_set() op = prev_op.getoperation() if not op.is_always_pure(): # TODO has_no_side_effect(): @@ -439,53 +435,52 @@ self.box_to_vbox = {} def as_vector_operation(self, pack): - assert len(pack.operations) > 1 + op_count = pack.operations + assert op_count > 1 self.pack = pack + # properties that hold for the pack are: + # isomorphism (see func above) op0 = pack.operations[0].getoperation() assert op0.vector != -1 args = op0.getarglist()[:] - if op0.vector in (rop.VEC_RAW_LOAD, rop.VEC_RAW_STORE): - args.append(ConstInt(0)) - vop = ResOperation(op0.vector, args, - op0.result, op0.getdescr()) - self._inspect_operation(vop) # op0 is for dispatch only - #if op0.vector not in (rop.VEC_RAW_LOAD, rop.VEC_RAW_STORE): - # op_count = len(pack.operations) - # args.append(ConstInt(op_count)) + args.append(ConstInt(len(op_count))) + vop = ResOperation(op0.vector, args, op0.result, op0.getdescr()) + self._inspect_operation(vop) return vop - def _pack_vector_arg(self, vop, op, i, vbox): - arg = op.getarg(i) - if vbox is None: - try: - _, vbox = self.box_to_vbox[arg] - except KeyError: - vbox = BoxVector(arg.type, 4, 0, True) - vop.setarg(i, vbox) - self.box_to_vbox[arg] = (i,vbox) - return vbox + def get_vbox_for(self, arg): + try: + _, vbox = self.box_to_vbox[arg] + return vbox + except KeyError: + # if this is not the case, then load operations must + # be emitted + assert False, "vector box MUST be defined before" - def _pack_vector_result(self, vop, op, vbox): - result = op.result - if vbox is None: - vbox = BoxVector(result.type, 4, 0, True) - vop.result = vbox - self.box_to_vbox[result] = (-1,vbox) - return vbox + def vector_result(self, vop): + ops = self.pack.operations + op0 = ops[0].getoperation() + result = op0.result + vbox = BoxVector(result.type, 4, 0, True) + vop.result = vbox + i = 0 + vboxcount = vbox.item_count = len(ops) + while i < vboxcount: + op = ops[i].getoperation() + self.box_to_vbox[result] = (i, vbox) + i += 1 + + def vector_arg(self, vop, argidx): + ops = self.pack.operations + op0 = ops[0].getoperation() + vbox = self.get_vbox_for(op0.getarg(argidx)) + vop.setarg(argidx, vbox) bin_arith_trans = """ def _vectorize_{name}(self, vop): - vbox_arg_0 = None - vbox_arg_1 = None - vbox_result = None - ops = self.pack.operations - for i, node in enumerate(ops): - op = node.getoperation() - vbox_arg_0 = self._pack_vector_arg(vop, op, 0, vbox_arg_0) - vbox_arg_1 = self._pack_vector_arg(vop, op, 1, vbox_arg_1) - vbox_result= self._pack_vector_result(vop, op, vbox_result) - vbox_arg_0.item_count = vbox_arg_1.item_count = \ - vbox_result.item_count = len(ops) + self.vector_arg(vop, 0) + self.vector_arg(vop, 1) + self.vector_result(vop) """ exec py.code.Source(bin_arith_trans.format(name='VEC_INT_ADD')).compile() exec py.code.Source(bin_arith_trans.format(name='VEC_INT_MUL')).compile() @@ -495,23 +490,16 @@ exec py.code.Source(bin_arith_trans.format(name='VEC_FLOAT_SUB')).compile() del bin_arith_trans + def _vectorize_VEC_INT_SIGNEXT(self, vop): + self.vector_arg(vop, 0) + # arg 1 is a constant + self.vector_result(vop) + def _vectorize_VEC_RAW_LOAD(self, vop): - vbox_result = None - ops = self.pack.operations - for i, node in enumerate(ops): - op = node.getoperation() - vbox_result= self._pack_vector_result(vop, op, vbox_result) - vbox_result.item_count = len(ops) - vop.setarg(vop.numargs()-1,ConstInt(len(ops))) + self.vector_result(vop) def _vectorize_VEC_RAW_STORE(self, vop): - vbox_arg_2 = None - ops = self.pack.operations - for i, node in enumerate(ops): - op = node.getoperation() - vbox_arg_2 = self._pack_vector_arg(vop, op, 2, vbox_arg_2) - vbox_arg_2.item_count = len(ops) - vop.setarg(vop.numargs()-1,ConstInt(len(ops))) + self.vector_arg(vop, 2) VecScheduleData._inspect_operation = \ make_dispatcher_method(VecScheduleData, '_vectorize_') diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -452,12 +452,13 @@ # # vector operations '_VEC_ARITHMETIC_FIRST', - 'VEC_INT_ADD/2d', - 'VEC_INT_SUB/2d', - 'VEC_INT_MUL/2d', - 'VEC_FLOAT_ADD/2d', - 'VEC_FLOAT_SUB/2d', - 'VEC_FLOAT_MUL/2d', + 'VEC_INT_ADD/3', + 'VEC_INT_SUB/3', + 'VEC_INT_MUL/3', + 'VEC_FLOAT_ADD/3', + 'VEC_FLOAT_SUB/3', + 'VEC_FLOAT_MUL/3', + 'VEC_INT_SIGNEXT/3', '_VEC_ARITHMETIC_LAST', # 'INT_LT/2b', @@ -703,20 +704,22 @@ rop.PTR_NE: rop.PTR_NE, } _opvector = { - rop.RAW_LOAD: rop.VEC_RAW_LOAD, + rop.RAW_LOAD: rop.VEC_RAW_LOAD, rop.GETARRAYITEM_RAW: rop.VEC_RAW_LOAD, - rop.GETARRAYITEM_GC: rop.VEC_RAW_LOAD, + rop.GETARRAYITEM_GC: rop.VEC_RAW_LOAD, - rop.RAW_STORE: rop.VEC_RAW_STORE, + rop.RAW_STORE: rop.VEC_RAW_STORE, rop.SETARRAYITEM_RAW: rop.VEC_RAW_STORE, - rop.SETARRAYITEM_GC: rop.VEC_RAW_STORE, + rop.SETARRAYITEM_GC: rop.VEC_RAW_STORE, - rop.INT_ADD: rop.VEC_INT_ADD, - rop.INT_SUB: rop.VEC_INT_SUB, - rop.INT_MUL: rop.VEC_INT_MUL, + rop.INT_ADD: rop.VEC_INT_ADD, + rop.INT_SUB: rop.VEC_INT_SUB, + rop.INT_MUL: rop.VEC_INT_MUL, rop.FLOAT_ADD: rop.VEC_FLOAT_ADD, rop.FLOAT_SUB: rop.VEC_FLOAT_SUB, rop.FLOAT_MUL: rop.VEC_FLOAT_MUL, + + rop.INT_SIGNEXT: rop.VEC_INT_SIGNEXT, } def setup2(): @@ -730,7 +733,6 @@ cls.boolinverse = _opboolinverse[opnum] if opnum in _opvector: cls.vector = _opvector[opnum] - setup2() del _opboolinverse del _opboolreflex diff --git a/rpython/jit/metainterp/test/test_vectorize.py b/rpython/jit/metainterp/test/test_vectorize.py --- a/rpython/jit/metainterp/test/test_vectorize.py +++ b/rpython/jit/metainterp/test/test_vectorize.py @@ -21,63 +21,24 @@ CPUClass=self.CPUClass, type_system=self.type_system) - def test_vectorize_simple_load_arith_store_mul(self): - myjitdriver = JitDriver(greens = [], - reds = ['i','d','va','vb','vc'], - vectorize=False) - def f(d): - va = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) - vb = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) - vc = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) - for i in range(d): - raw_storage_setitem(va, i*rffi.sizeof(rffi.SIGNED), - rffi.cast(rffi.SIGNED,i)) - raw_storage_setitem(vb, i*rffi.sizeof(rffi.SIGNED), - rffi.cast(rffi.SIGNED,i)) - i = 0 - while i < d: - myjitdriver.can_enter_jit(i=i, d=d, va=va, vb=vb, vc=vc) - myjitdriver.jit_merge_point(i=i, d=d, va=va, vb=vb, vc=vc) - pos = i*rffi.sizeof(rffi.SIGNED) - a = raw_storage_getitem(rffi.SIGNED,va,pos) - b = raw_storage_getitem(rffi.SIGNED,vb,pos) - c = a+b - raw_storage_setitem(vc, pos, rffi.cast(rffi.SIGNED,c)) - i += 1 - res = 0 - for i in range(d): - res += raw_storage_getitem(rffi.SIGNED,vc,i*rffi.sizeof(rffi.SIGNED)) - - free_raw_storage(va) - free_raw_storage(vb) - free_raw_storage(vc) - return res - i = 32 - res = self.meta_interp(f, [i]) - assert res == f(i) - self.check_trace_count(1) - i = 31 - res = self.meta_interp(f, [i]) - assert res == f(i) - - @py.test.mark.parametrize('i',range(0,32)) + @py.test.mark.parametrize('i',[3,4,5,6,7,8,9,50]) def test_vectorize_simple_load_arith_store_int_add_index(self,i): myjitdriver = JitDriver(greens = [], - reds = ['i','d','va','vb','vc'], + reds = ['i','d','bc','va','vb','vc'], vectorize=True) def f(d): - va = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) - vb = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) - vc = alloc_raw_storage(d*rffi.sizeof(rffi.SIGNED), zero=True) + bc = d*rffi.sizeof(rffi.SIGNED) + va = alloc_raw_storage(bc, zero=True) + vb = alloc_raw_storage(bc, zero=True) + vc = alloc_raw_storage(bc, zero=True) for i in range(d): - raw_storage_setitem(va, i*rffi.sizeof(rffi.SIGNED), - rffi.cast(rffi.SIGNED,i)) - raw_storage_setitem(vb, i*rffi.sizeof(rffi.SIGNED), - rffi.cast(rffi.SIGNED,i)) + j = i*rffi.sizeof(rffi.SIGNED) + raw_storage_setitem(va, j, rffi.cast(rffi.SIGNED,i)) + raw_storage_setitem(vb, j, rffi.cast(rffi.SIGNED,i)) i = 0 - while i < d*8: - myjitdriver.can_enter_jit(i=i, d=d, va=va, vb=vb, vc=vc) - myjitdriver.jit_merge_point(i=i, d=d, va=va, vb=vb, vc=vc) + while i < bc: + myjitdriver.can_enter_jit(i=i, d=d, va=va, vb=vb, vc=vc, bc=bc) + myjitdriver.jit_merge_point(i=i, d=d, va=va, vb=vb, vc=vc, bc=bc) a = raw_storage_getitem(rffi.SIGNED,va,i) b = raw_storage_getitem(rffi.SIGNED,vb,i) c = a+b @@ -92,8 +53,9 @@ free_raw_storage(vc) return res res = self.meta_interp(f, [i]) - assert res == f(i) #sum(range(i)) * 2 - self.check_trace_count(1) + assert res == f(i) + if i > 3: + self.check_trace_count(1) def test_guard(self): py.test.skip('abc') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit