Author: Richard Plangger <r...@pasra.at> Branch: vecopt-merge Changeset: r79052:8fa916fbce20 Date: 2015-08-19 13:19 +0200 http://bitbucket.org/pypy/pypy/changeset/8fa916fbce20/
Log: further cut down the search space to move guards to an earlier position, at the same time it seems that I have made it weaker. some guards are not moved anymore (need investigation) 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 @@ -674,6 +674,9 @@ cloned.copy_all_attributes_from(self) return cloned + def exits_early(self): + return True + class ResumeGuardNonnullDescr(ResumeGuardDescr): guard_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 @@ -4,6 +4,7 @@ from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method from rpython.jit.metainterp.resoperation import (rop, GuardResOp, ResOperation) from rpython.jit.metainterp.resume import Snapshot +from rpython.jit.metainterp.compile import ResumeGuardDescr from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import (BoxPtr, ConstPtr, ConstInt, BoxInt, Box, Const, BoxFloat, AbstractValue) @@ -61,8 +62,13 @@ count -= 1 while i < count: op = self.path[i].getoperation() - if op.getopnum() != rop.GUARD_EARLY_EXIT and not op.is_always_pure(): + if not op.is_always_pure(): return False + if op.is_guard(): + descr = op.getdescr() + assert isinstance(descr, ResumeGuardDescr) + if not descr or not descr.exits_early(): + return False i += 1 return True @@ -286,9 +292,8 @@ else: iterdir = node.provides() if index >= len(iterdir): - #if blacklist: - #blacklist_visit[node] = None - # print "blacklisting 1", node, "path", '->'.join([str(p.opidx) for p in path.path]) + if blacklist: + blacklist_visit[node] = None continue else: next_dep = iterdir[index] @@ -297,7 +302,6 @@ if index < len(iterdir): worklist.append((index, node, pathlen)) else: - print "blacklisting 2", node, "path", '->'.join([str(p.opidx) for p in path.path]) blacklist_visit[node] = None path.cut_off_at(pathlen) path.walk(next_node) @@ -385,9 +389,6 @@ return self.to == to def points_at(self, at): return self.at == at - def i_points_at(self, idx): - # REM - return self.at.opidx == idx def add_dependency(self, at, to, arg): self.args.append((at,arg)) @@ -576,17 +577,16 @@ # pass 2 correct guard dependencies for guard_node in self.guards: self.build_guard_dependencies(guard_node, tracker) - # pass 3 find schedulable nodes - jump_node = self.nodes[jump_pos] - label_node = self.nodes[label_pos] + + def prepare_for_scheduling(self): + jump_node = self.nodes[len(self.nodes)-1] + jump_node.emitted = True + label_node = self.nodes[0] for node in self.nodes: - if node != jump_node: - if node.depends_count() == 0: - self.schedulable_nodes.insert(0, 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 - if node.provides_count() == 0: - node.edge_to(jump_node, None, label='jump') + if node.depends_count() == 0: + self.schedulable_nodes.insert(0, node) + if not we_are_translated(): + assert self.schedulable_nodes[-1] == label_node def guard_argument_protection(self, guard_node, tracker): """ the parameters the guard protects are an indicator for diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py b/rpython/jit/metainterp/optimizeopt/schedule.py --- a/rpython/jit/metainterp/optimizeopt/schedule.py +++ b/rpython/jit/metainterp/optimizeopt/schedule.py @@ -98,6 +98,11 @@ raise AssertionError("schedule failed cannot continue. possible reason: cycle") + jump_node = self.graph.nodes[-1] + assert jump_node.getopnum() == rop.JUMP + self.sched_data.unpack_from_vector(jump_node.getoperation(), self) + oplist.append(jump_node.getoperation()) + def vectorbox_outof_box(box, count=-1, size=-1, type='-'): if box.type not in (FLOAT, INT): raise AssertionError("cannot create vector box of type %s" % (box.type)) 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 @@ -97,6 +97,7 @@ if cycle is not None: print "CYCLE found %s" % cycle self.show_dot_graph(opt.dependency_graph, "early_exit_" + self.test_name) + assert cycle is None opt.schedule(False) opt.unroll_loop_iterations(loop, unroll_factor) opt.loop.operations = opt.get_newoperations() @@ -1348,7 +1349,6 @@ guard_true(i22, descr=<ResumeGuardTrueDescr object at 0x7fc657d7bdc0>) [p1, p0, p5, p6, p7, p12, p13, i14] jump(p0, p1, p5, p6, p7, p12, p13, i31, i15, i16, i17, i18, i19, i20) """ - # schedule 885 -> ptype is non for raw_load? opt = self.vectorize(self.parse_loop(trace)) self.debug_print_operations(opt.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 @@ -469,6 +469,7 @@ if sched_data is None: sched_data = VecScheduleData(self.cpu.vector_register_size, self.costmodel, self.orig_label_args) + self.dependency_graph.prepare_for_scheduling() scheduler = Scheduler(self.dependency_graph, sched_data) renamer = Renamer() # @@ -515,49 +516,34 @@ label_node = graph.getnode(0) ee_guard_node = graph.getnode(ee_pos) guards = graph.guards - unique = set() for guard_node in guards: if guard_node is ee_guard_node: continue modify_later = [] last_prev_node = None - for path in guard_node.iterate_paths(ee_guard_node, backwards=True, blacklist=True): - p = '->'.join([str(p.opidx) for p in path.path]) - if p in unique: - assert 0 + valid = True + for prev_dep in guard_node.depends(): + prev_node = prev_dep.to + if prev_dep.is_failarg(): + # remove this edge later. + # 1) only because of failing, this dependency exists + # 2) non pure operation points to this guard. + # but if this guard only depends on pure operations, it can be checked + # at an earlier position, the non pure op can execute later! + modify_later.append((prev_node, guard_node)) else: - unique.add(p) - print "PATH:", p - if not we_are_translated(): - path.check_acyclic() - prev_node = path.second() - dep = prev_node.depends_on(guard_node) - if dep.is_failarg(): - # this dependency we are able to break because it is soley - # relevant due to one or multiple fail args - if prev_node is not last_prev_node: - # ... - # o o - # \ / - # (a) - # | - # (g) - # this graph yields 2 paths from (g), thus (a) is - # remembered and skipped the second time visited - modify_later.append((prev_node, guard_node)) - print " => remove guard -> second" - last_prev_node = prev_node - continue - if path.is_always_pure(exclude_first=True, exclude_last=True): - path.set_schedule_priority(10) - if path.last() is ee_guard_node: - modify_later.append((path.last_but_one(), None)) - print " => always pure" - else: - # transformation is invalid. - # exit and do not enter else branch! - break - else: + for path in prev_node.iterate_paths(ee_guard_node, backwards=True, blacklist=True): + if path.is_always_pure(exclude_first=True, exclude_last=True): + path.set_schedule_priority(10) + if path.last() is ee_guard_node: + modify_later.append((path.last_but_one(), None)) + else: + # transformation is invalid. + # exit and do not enter else branch! + valid = False + if not valid: + break + if valid: # transformation is valid, modify the graph and execute # this guard earlier for a,b in modify_later: @@ -568,7 +554,8 @@ if last_but_one is ee_guard_node: continue ee_guard_node.remove_edge_to(last_but_one) - label_node.edge_to(last_but_one, label='pullup') + #label_node.edge_to(last_but_one, label='pullup') + print "guard", guard_node, "moved earlier" # only the last guard needs a connection guard_node.edge_to(ee_guard_node, label='pullup-last-guard') self.relax_guard_to(guard_node, ee_guard_node) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit