Author: Richard Plangger <r...@pasra.at> Branch: vecopt2 Changeset: r77106:24298bf280c1 Date: 2015-04-08 16:36 +0200 http://bitbucket.org/pypy/pypy/changeset/24298bf280c1/
Log: starting to modify the dependency construction to track all integral modifications 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 @@ -53,6 +53,10 @@ else: self.defs[arg] = [(index,argcell)] + def redefintions(self, arg): + for _def in self.defs[arg]: + yield _def[0] + def definition_index(self, arg, index = -1, argcell=None): def_chain = self.defs[arg] if len(def_chain) == 1: @@ -103,6 +107,8 @@ self.integral_mod = IntegralMod() self.schedulable_nodes = [0] # label is always scheduleable self.build_dependencies() + self.index_vars = {} + self.guards = [] def build_dependencies(self): """ This is basically building the definition-use chain and saving this @@ -114,7 +120,7 @@ """ tracker = DefTracker(self.memory_refs) # - guards = [] + intformod = IntegralForwardModification(self.index_vars) # pass 1 for i,op in enumerate(self.operations): # the label operation defines all operations at the @@ -122,6 +128,9 @@ if op.getopnum() == rop.LABEL: for arg in op.getarglist(): tracker.define(arg, 0) + if isinstance(arg, BoxInt): + assert arg not in self.index_vars + self.index_vars[arg] = IndexVar(arg) continue # prevent adding edge to the label itself # definition of a new variable if op.result is not None: @@ -133,21 +142,20 @@ for arg in op.getarglist(): self._def_use(arg, i, tracker) elif op.is_guard(): - guards.append(i) + self.guards.append(i) else: self._build_non_pure_dependencies(op, i, tracker) - # + intformod.inspect_operation(op, i) # pass 2 correct guard dependencies - for guard_idx in guards: + for guard_idx in self.guards: self._build_guard_dependencies(guard_idx, op.getopnum(), tracker) # pass 3 find schedulable nodes jump_pos = len(self.operations)-1 for i,op in enumerate(self.operations): if len(self.adjacent_list[i]) == 0: self.schedulable_nodes.append(i) - # every leaf instruction points to the jump_op. in theory - # every instruction points to jump_op, this is an optimization - # to prevent the scheduling of ops before the jump operation + # 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 if i != jump_pos: for dep in self.adjacent_list[i]: if dep.idx_to > i: @@ -170,7 +178,6 @@ for arg in guard_op.getarglist(): self._def_use(arg, guard_idx, tracker) - print "guard[", guard_idx, "]", guard_op variables = [] for dep in self.depends(guard_idx): idx = dep.idx_from @@ -178,18 +185,16 @@ for arg in op.getarglist(): if isinstance(arg, Box): variables.append(arg) - print " + in spe", arg if op.result: variables.append(op.result) - print " + in spe res", op.result # for var in variables: try: def_idx = tracker.definition_index(var) for dep in self.provides(def_idx): if var in dep.args and dep.idx_to > guard_idx: - print "checking", var, "def at", def_idx, " -> ", dep - print " ==> yes" + #print "checking", var, "def at", def_idx, " -> ", dep + #print " ==> yes" self._put_edge(guard_idx, dep.idx_to, var) except KeyError: pass @@ -198,8 +203,9 @@ if op.getfailargs(): for arg in op.getfailargs(): try: - def_idx = tracker.definition_index(arg) - #self._put_edge(def_idx, guard_idx, arg) + for def_idx in tracker.redefintions(arg): + self._put_edge(def_idx, guard_idx, arg) + #print "put arg", arg, ":", def_idx, guard_idx,"!!!" except KeyError: assert False # @@ -300,6 +306,7 @@ return args def _update_memory_ref(self, op, index, tracker): + # deprecated if index not in self.memory_refs: return memref = self.memory_refs[index] @@ -327,9 +334,10 @@ assert idx_from != idx_to dep = self.directly_depends(idx_from, idx_to) if not dep: - dep = Dependency(idx_from, idx_to, arg) - self.adjacent_list[idx_from].append(dep) - self.adjacent_list[idx_to].append(dep) + if self.independent(idx_from, idx_to): + dep = Dependency(idx_from, idx_to, arg) + self.adjacent_list[idx_from].append(dep) + self.adjacent_list[idx_to].append(dep) else: if arg not in dep.args: dep.args.append(arg) @@ -399,6 +407,7 @@ def directly_depends(self, from_idx, to_idx): return self.instr_dependency(from_idx, to_idx) + def instr_dependency(self, from_instr_idx, to_instr_idx): # XXX """ Does there exist a dependency from the instruction to another? @@ -512,6 +521,83 @@ def is_schedulable(self, idx): return self.graph.depends_count(idx) == 0 +class IntegralForwardModification(object): + """ Calculates integral modifications on an integer box. """ + def __init__(self, index_vars): + self.index_vars = index_vars + + def is_const_integral(self, box): + if isinstance(box, ConstInt): + return True + return False + + additive_func_source = """ + def operation_{name}(self, op, index): + box_r = op.result + if not box_r: + return + box_a0 = op.getarg(0) + box_a1 = op.getarg(1) + if self.is_const_integral(box_a0) and self.is_const_integral(box_a1): + idx_ref = IndexVar(box_r) + idx_ref.constant = box_a0.getint() {op} box_a1.getint()) + self.index_vars[box_r] = idx_ref + elif self.is_const_integral(box_a0): + idx_ref = self.index_vars[box_a0] + idx_ref = idx_ref.clone(box_r) + idx_ref.constant {op}= box_a0.getint() + self.index_vars[box_r] = idx_ref + elif self.is_const_integral(box_a1): + idx_ref = self.index_vars[box_a1] + idx_ref = idx_ref.clone(box_r) + idx_ref.constant {op}= box_a1.getint() + self.index_vars[box_r] = idx_ref + """ + exec py.code.Source(additive_func_source.format(name='INT_ADD', + op='+')).compile() + exec py.code.Source(additive_func_source.format(name='INT_SUB', + op='-')).compile() + del additive_func_source + + multiplicative_func_source = """ + def operation_{name}(self, op): + box_r = op.result + if not box_r: + return + box_a0 = op.getarg(0) + box_a1 = op.getarg(1) + if self.is_const_integral(box_a0) and self.is_const_integral(box_a1): + idx_ref = IndexVar(box_r) + idx_ref.constant = box_a0.getint() {cop} box_a1.getint()) + self.index_vars[box_r] = idx_ref + elif self.is_const_integral(box_a0): + idx_ref = self.index_vars[box_a0] + idx_ref = idx_ref.clone(box_r) + self.coefficient_{tgt} *= box_a0.getint() + self.constant {cop}= box_a0.getint() + self.index_vars[box_r] = idx_ref + elif self.is_const_integral(box_a1): + idx_ref = self.index_vars[box_a1] + idx_ref = idx_ref.clone(box_r) + self.coefficient_{tgt} {op}= box_a1.getint() + self.constant {cop}= box_a1.getint() + self.index_vars[box_r] = idx_ref + """ + exec py.code.Source(multiplicative_func_source.format(name='INT_MUL', + op='*', tgt='mul', + cop='*')).compile() + exec py.code.Source(multiplicative_func_source.format(name='INT_FLOORDIV', + op='*', tgt='div', + cop='/')).compile() + exec py.code.Source(multiplicative_func_source.format(name='UINT_FLOORDIV', + op='*', tgt='div', + cop='/')).compile() + del multiplicative_func_source + +integral_dispatch_opt = make_dispatcher_method(IntegralForwardModification, 'operation_') +IntegralForwardModification.inspect_operation = integral_dispatch_opt +del integral_dispatch_opt + class IntegralMod(object): """ Calculates integral modifications on an integer object. The operations must be provided in backwards direction and of one @@ -532,11 +618,6 @@ def _update_additive(self, i): return (i * self.coefficient_mul) / self.coefficient_div - def is_const_integral(self, box): - if isinstance(box, ConstInt): - return True - return False - additive_func_source = """ def operation_{name}(self, op): box_a0 = op.getarg(0) @@ -592,6 +673,11 @@ cop='/')).compile() del multiplicative_func_source + def is_const_integral(self, box): + if isinstance(box, ConstInt): + return True + return False + def update_memory_ref(self, memref): memref.constant = self.constant memref.coefficient_mul = self.coefficient_mul @@ -605,6 +691,43 @@ IntegralMod.inspect_operation = integral_dispatch_opt del integral_dispatch_opt +class IndexVar(object): + def __init__(self, var): + self.var = var + self.coefficient_mul = 1 + self.coefficient_div = 1 + self.constant = 0 + + def __eq__(self, other): + if self.same_variable(other): + return self.diff(other) == 0 + return False + + def __ne__(self, other): + return not self.__eq__(other) + + def clone(self, box): + c = IndexVar(box) + c.coefficient_mul = self.coefficient_mul + c.coefficient_div = self.coefficient_div + c.constant = self.constant + return c + + def same_variable(self, other): + assert isinstance(other, IndexVar) + return other.var == self.var + + def diff(self, other): + """ calculates the difference as a second parameter """ + assert isinstance(other, IndexVar) + mycoeff = self.coefficient_mul // self.coefficient_div + othercoeff = other.coefficient_mul // other.coefficient_div + return mycoeff + self.constant - (othercoeff + other.constant) + + def __repr__(self): + return 'IndexVar(%s*(%s/%s)+%s)' % (self.var, self.coefficient_mul, + self.coefficient_div, self.constant) + class MemoryRef(object): """ a memory reference to an array object. IntegralMod is able to propagate changes to this object if applied in backwards direction. @@ -616,33 +739,37 @@ will result in the linear combination i0 * (2/1) + 2 """ - def __init__(self, array, origin, descr): + def __init__(self, array, origin, descr, index_ref, byte_index=False): assert descr is not None self.array = array - self.origin = origin self.descr = descr - self.coefficient_mul = 1 - self.coefficient_div = 1 - self.constant = 0 + self.index_ref = index_ref + self.byte_index = byte_index def is_adjacent_to(self, other): """ this is a symmetric relation """ - match, off = self.calc_difference(other) stride = self.stride() - if match and stride != 0: - return abs(off) - stride == 0 + if self.match(other): + return abs(self.index_ref.diff(other.index_ref)) - stride == 0 + return False + + def match(self, other): + assert isinstance(other, MemoryRef) + if self.array == other.array and self.descr == other.descr: + return self.index_ref.same_variable(other.index_ref): return False def stride(self): """ the stride in bytes """ + if not self.byte_index: + return 1 return self.descr.get_item_size_in_bytes() def is_adjacent_after(self, other): """ the asymetric relation to is_adjacent_to """ - match, off = self.calc_difference(other) stride = self.stride() - if match and stride != 0: - return off == stride # must be equal to the positive stride + if self.match(other): + return self.index_ref.diff(other.index_ref) == stride return False def indices_can_alias(self, other): @@ -650,35 +777,21 @@ self.origin != other.origin, or their linear combination point to the same element. """ - match, off = self.calc_difference(other) - if match: - return abs(off) < self.stride() + if self.index_ref.same_variable(other.index_ref): + return True + stride = self.stride() + if self.match(other): + return abs(self.index_ref.diff(other.index_ref)) < stride return False def __eq__(self, other): - match, off = self.calc_difference(other) - if match: - return off == 0 + if self.match(other): + return self.index_ref.diff(other.index_ref) == 0 return False def __ne__(self, other): return not self.__eq__(other) - def accesses_same_object(self, other): - assert isinstance(other, MemoryRef) - return self.array == other.array - - def calc_difference(self, other): - """ calculates the difference in bytes as second return value """ - assert isinstance(other, MemoryRef) - if self.array == other.array \ - and self.origin == other.origin: - mycoeff = self.coefficient_mul // self.coefficient_div - othercoeff = other.coefficient_mul // other.coefficient_div - diff = other.constant - self.constant - return mycoeff == othercoeff, diff - return False, 0 - def __repr__(self): - return 'MemoryRef(%s*(%s/%s)+%s)' % (self.origin, self.coefficient_mul, + return 'MemRef(%s,%s*(%s/%s)+%s)' % (self.array, self.origin, self.coefficient_mul, self.coefficient_div, self.constant) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py --- a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py @@ -766,15 +766,25 @@ self.assert_packset_empty(vopt.packset, len(loop.operations), [(5,11), (4,10), (6,12)]) - @pytest.mark.parametrize("descr,stride", - [('char',1),('float',8),('int',8),('singlefloat',4)]) - def test_packset_combine_simple(self,descr,stride): + @pytest.mark.parametrize("descr", ['char','float','int','singlefloat']) + def test_packset_combine_simple(self,descr): ops = """ [p0,i0] i3 = getarrayitem_gc(p0, i0, descr={descr}arraydescr) - i1 = int_add(i0,{stride}) + i1 = int_add(i0,1) jump(p0,i1) - """.format(descr=descr,stride=stride) + """.format(descr=descr) + loop = self.parse_loop(ops) + vopt = self.combine_packset(loop,3) + assert len(vopt.vec_info.memory_refs) == 4 + assert len(vopt.packset.packs) == 1 + self.assert_pack(vopt.packset.packs[0], (1,3,5,7)) + ops = """ + [p0,i0] + i3 = getarrayitem_raw(p0, i0, descr={descr}arraydescr) + i1 = int_add(i0,1) + jump(p0,i1) + """.format(descr=descr) loop = self.parse_loop(ops) vopt = self.combine_packset(loop,3) assert len(vopt.vec_info.memory_refs) == 4 @@ -786,15 +796,18 @@ def test_packset_combine_2_loads_in_trace(self, descr, stride): ops = """ [p0,i0] - i3 = getarrayitem_gc(p0, i0, descr={type}arraydescr) + i3 = raw_load(p0, i0, descr={type}arraydescr) i1 = int_add(i0,{stride}) - i4 = getarrayitem_gc(p0, i1, descr={type}arraydescr) + i4 = raw_load(p0, i1, descr={type}arraydescr) i2 = int_add(i1,{stride}) jump(p0,i2) """.format(type=descr,stride=stride) loop = self.parse_loop(ops) vopt = self.combine_packset(loop,3) assert len(vopt.vec_info.memory_refs) == 8 + print "---" + for p in vopt.packset.packs: + print p assert len(vopt.packset.packs) == 1 self.assert_pack(vopt.packset.packs[0], (1,3,5,7,9,11,13,15)) @@ -856,10 +869,10 @@ i1 = int_add(i0, {stride}) i10 = int_le(i1, 128) guard_true(i10) [] - i2 = getarrayitem_gc(p0, i0, descr={descr}arraydescr) - i3 = getarrayitem_gc(p1, i0, descr={descr}arraydescr) + i2 = raw_load(p0, i0, descr={descr}arraydescr) + i3 = raw_load(p1, i0, descr={descr}arraydescr) i4 = {op}(i2,i3) - setarrayitem_gc(p2, i0, i4, descr={descr}arraydescr) + raw_store(p2, i0, i4, descr={descr}arraydescr) jump(p0,p1,p2,i1) """.format(op=op,descr=descr,stride=stride) loop = self.parse_loop(ops) @@ -896,7 +909,7 @@ setarrayitem_gc(p2, i0, i4, descr={descr}arraydescr) # 6, 13, 20, 27 i1 = int_add(i0, {stride}) # 7, 14, 21, 28 jump(p0,p1,p2,i1) # 29 - """.format(op=op,descr=descr,stride=stride) + """.format(op=op,descr=descr,stride=1) # stride getarray is always 1 vops = """ [p0,p1,p2,i0] i10 = int_le(i0, 128) @@ -910,7 +923,7 @@ v3 = {op}(v1,v2) vec_raw_store(p2, i0, v3, 2, descr={descr}arraydescr) jump(p0,p1,p2,i12) - """.format(op='vec_'+op,descr=descr,stride=stride) + """.format(op='vec_'+op,descr=descr,stride=1) loop = self.parse_loop(ops) vopt = self.schedule(loop,1) self.debug_print_operations(vopt.loop) @@ -959,19 +972,20 @@ print "_--" * 10 self.debug_print_operations(vopt.loop) - def test_vectorize_raw_load_add_index_item_byte_size(self): + def test_123(self): ops = """ - [i0, i1, i2, i3, i4, i5, i6, i7] - i8 = raw_load(i3, i0, descr=intarraydescr) - i9 = raw_load(i4, i0, descr=intarraydescr) - i10 = int_add(i8, i9) - raw_store(i5, i0, i10, descr=intarraydescr) - i12 = int_add(i0, 8) - i14 = int_mul(i7, 8) - i15 = int_lt(i12, i14) - guard_true(i15) [i7, i10, i5, i4, i3, i9, i8, i12] - guard_future_condition() [] - jump(i12, i8, i9, i3, i4, i5, i10, i7) + [i0, i1, i2, i3, i4] + debug_merge_point(0, 0, '1') + i6 = int_mul(i0, 8) + i7 = raw_load(i2, i6, descr=intarraydescr) + i8 = raw_load(i3, i6, descr=intarraydescr) + i9 = int_add(i7, i8) + raw_store(i4, i6, i9, descr=intarraydescr) + i11 = int_add(i0, 1) + i12 = int_lt(i11, i1) + guard_true(i12) [i4, i3, i2, i1, i11] + debug_merge_point(0, 0, '2') + label(i11, i1, i2, i3, i4) """ vopt = self.schedule(self.parse_loop(ops),1) self.debug_print_operations(vopt.loop) 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 @@ -32,18 +32,15 @@ else: print "" -def must_unpack_result_to_exec(var, op): +def must_unpack_result_to_exec(op, target_op): # TODO either move to resop or util - if op.vector == -1: - return True - if op.getopnum() == rop.RAW_LOAD or \ - op.getopnum() == rop.GETARRAYITEM_GC or \ - op.getopnum() == rop.GETARRAYITEM_RAW: - return True - if op.getopnum() == rop.RAW_STORE or \ - op.getopnum() == rop.SETARRAYITEM_GC or \ - op.getopnum() == rop.SETARRAYITEM_RAW: - if op.getarg(1) == var: + if op.vector != -1: + return False + return True + +def prohibit_packing(op1, op2): + if op2.is_array_op(): + if op2.getarg(1) == op1.result: return True return False @@ -147,9 +144,7 @@ try: value = rename_map[arg] copied_op.setarg(i, value) - print "rename", arg, " to ", value except KeyError: - print "failing", arg, i pass # not only the arguments, but also the fail args need # to be adjusted. rd_snapshot stores the live variables @@ -191,6 +186,7 @@ print "box", box, "=>", value except KeyError: print "FAIL:", i, box + pass snapshot = Snapshot(self.clone_snapshot(snapshot.prev, rename_map), new_boxes) @@ -235,9 +231,24 @@ self.combine_packset() self.schedule() + def relax_guard_dependencies(self): + int_mod = IntegralMod() + for idx, guard in self.vec_info.guards.items(): + int_mod.reset() + for dep in self.dependency_graph.depends(idx): + op = self.operations[dep.idx_from] + if op.returns_bool_result(): + for arg in op.getarglist(): + if isinstance(arg, Box): + self._track_integral_modification(arg) + + def _track_integral_modification(self, arg): + ref = MemoryRef(None, arg, None) + def build_dependency_graph(self): self.dependency_graph = \ DependencyGraph(self.loop.operations, self.vec_info.memory_refs) + self.relax_guard_dependencies() def find_adjacent_memory_refs(self): """ the pre pass already builds a hash of memory references and the @@ -323,6 +334,8 @@ end_ij = len(self.packset.packs) while True: len_before = len(self.packset.packs) + print "loop", len_before + i = 0 while i < end_ij: while j < end_ij and i < end_ij: if i == j: @@ -335,6 +348,7 @@ elif pack2.rightmost_match_leftmost(pack1): end_ij = self.packset.combine(j,i) j += 1 + j = 0 i += 1 if len_before == len(self.packset.packs): break @@ -500,18 +514,25 @@ into account the benefit of executing this instruction as SIMD instruction. """ - savings = -1 # 1 point for loading and 1 point for storing + savings = -1 - # without loss of generatlity: only check the left side + # without loss of generatlity: only check 'left' operation lop = self.operations[lopidx] target_op = self.operations[pack.left.opidx] + if prohibit_packing(lop, target_op): + return -1 + if not expand_forward: - if not must_unpack_result_to_exec(lop.result, target_op): + print " backward savings", savings + if not must_unpack_result_to_exec(target_op, lop): savings += 1 + print " => backward savings", savings else: - if not must_unpack_result_to_exec(target_op.result, lop): + print " forward savings", savings + if not must_unpack_result_to_exec(target_op, lop): savings += 1 + print " => forward savings", savings return savings @@ -595,15 +616,25 @@ def __init__(self): self.smallest_type_bytes = 0 self.memory_refs = {} + self.guards = {} self.track_memory_refs = False self.index = 0 + guard_source = """ + def operation_{name}(self, op): + if self.track_memory_refs: + self.guards[self.index] = op + """ + for op in ['GUARD_TRUE','GUARD_FALSE']: + exec py.code.Source(guard_source.format(name=op)).compile() + del guard_source + array_access_source = """ def operation_{name}(self, op): descr = op.getdescr() if self.track_memory_refs: self.memory_refs[self.index] = \ - MemoryRef(op.getarg(0), op.getarg(1), op.getdescr()) + MemoryRef(op.getarg(0), op.getarg(1), op.getdescr(), {elemidx}) if not descr.is_array_of_pointers(): byte_count = descr.get_item_size_in_bytes() if self.smallest_type_bytes == 0 \ @@ -611,17 +642,17 @@ self.smallest_type_bytes = byte_count """ exec py.code.Source(array_access_source - .format(name='RAW_LOAD')).compile() + .format(name='RAW_LOAD',elemidx=True)).compile() exec py.code.Source(array_access_source - .format(name='RAW_STORE')).compile() + .format(name='RAW_STORE',elemidx=True)).compile() exec py.code.Source(array_access_source - .format(name='GETARRAYITEM_GC')).compile() + .format(name='GETARRAYITEM_GC',elemidx=False)).compile() exec py.code.Source(array_access_source - .format(name='SETARRAYITEM_GC')).compile() + .format(name='SETARRAYITEM_GC',elemidx=False)).compile() exec py.code.Source(array_access_source - .format(name='GETARRAYITEM_RAW')).compile() + .format(name='GETARRAYITEM_RAW',elemidx=False)).compile() exec py.code.Source(array_access_source - .format(name='SETARRAYITEM_RAW')).compile() + .format(name='SETARRAYITEM_RAW',elemidx=False)).compile() del array_access_source def default_operation(self, operation): 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 @@ -171,6 +171,11 @@ def is_vector_arithmetic(self): return rop._VEC_ARITHMETIC_FIRST <= self.getopnum() <= rop._VEC_ARITHMETIC_LAST + def is_array_op(self): + on = self.getopnum() + return rop.GETARRAYITEM_GC <= on <= rop.VEC_RAW_LOAD or \ + rop.SETARRAYITEM_GC <= on <= rop.VEC_RAW_STORE + def is_comparison(self): return self.is_always_pure() and self.returns_bool_result() @@ -500,9 +505,9 @@ 'GETARRAYITEM_GC/2d', 'GETARRAYITEM_RAW/2d', - 'GETINTERIORFIELD_GC/2d', 'RAW_LOAD/2d', 'VEC_RAW_LOAD/3d', + 'GETINTERIORFIELD_GC/2d', 'GETFIELD_GC/1d', 'GETFIELD_RAW/1d', '_MALLOC_FIRST', @@ -523,10 +528,10 @@ 'INCREMENT_DEBUG_COUNTER/1', 'SETARRAYITEM_GC/3d', 'SETARRAYITEM_RAW/3d', + 'RAW_STORE/3d', + 'VEC_RAW_STORE/4d', 'SETINTERIORFIELD_GC/3d', 'SETINTERIORFIELD_RAW/3d', # right now, only used by tests - 'RAW_STORE/3d', - 'VEC_RAW_STORE/4d', 'SETFIELD_GC/2d', 'ZERO_PTR_FIELD/2', # only emitted by the rewrite, clears a pointer field # at a given constant offset, no descr 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 @@ -8,7 +8,7 @@ from rpython.rlib.jit import JitDriver, hint, set_param from rpython.rlib.objectmodel import compute_hash from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.rlib.rarithmetic import r_uint +from rpython.rlib.rarithmetic import r_uint, intmask from rpython.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem, free_raw_storage, raw_storage_getitem) @@ -24,7 +24,7 @@ def test_vectorize_simple_load_arith_store_mul(self): myjitdriver = JitDriver(greens = [], reds = ['i','d','va','vb','vc'], - vectorize=True) + 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) @@ -96,7 +96,7 @@ self.check_trace_count(1) def test_guard(self): - pytest.skip() + py.test.skip('abc') myjitdriver = JitDriver(greens = [], reds = ['a','b','c'], vectorize=True) @@ -117,5 +117,40 @@ assert res == 42 self.check_trace_count(1) + @py.test.mark.parametrize('i',[8]) + def test_vectorize_array_get_set(self,i): + myjitdriver = JitDriver(greens = [], + reds = ['i','d','va','vb','vc'], + vectorize=True) + ET = rffi.SIGNED + T = lltype.Array(ET, hints={'nolength': True}) + def f(d): + i = 0 + va = lltype.malloc(T, d, flavor='raw', zero=True) + vb = lltype.malloc(T, d, flavor='raw', zero=True) + vc = lltype.malloc(T, d, flavor='raw', zero=True) + for j in range(d): + va[j] = j + vb[j] = j + 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) + + a = va[i] + b = vb[i] + vc[i] = a+b + + i += 1 + res = 0 + for j in range(d): + res += intmask(vc[j]) + lltype.free(va, flavor='raw') + lltype.free(vb, flavor='raw') + lltype.free(vc, flavor='raw') + return res + res = self.meta_interp(f, [i]) + assert res == f(i) + self.check_trace_count(1) + class TestLLtype(VectorizeTest, LLJitMixin): pass _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit