[pypy-commit] pypy exc-later: Delay analysis of specialised exception exit cases until the end of build_flow()
rlamy
noreply at buildbot.pypy.org
Tue Mar 17 20:29:29 CET 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: exc-later
Changeset: r76439:35a38a39212e
Date: 2015-03-13 02:22 +0000
http://bitbucket.org/pypy/pypy/changeset/35a38a39212e/
Log: Delay analysis of specialised exception exit cases until the end of
build_flow()
This should enable simplifications of exception handling.
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -124,7 +124,7 @@
def guessexception(self, ctx, *cases):
block = self.crnt_block
links = []
- for case in [None] + list(cases):
+ for case in [None, Exception]:
if case is not None:
if case is Exception:
last_exc = Variable('last_exception')
@@ -398,6 +398,8 @@
block = self.pendingblocks.popleft()
if not block.dead:
self.record_block(block)
+ from rpython.translator.simplify import specialize_exceptions
+ specialize_exceptions(graph)
def record_block(self, block):
self.setstate(block.framestate)
diff --git a/rpython/translator/simplify.py b/rpython/translator/simplify.py
--- a/rpython/translator/simplify.py
+++ b/rpython/translator/simplify.py
@@ -9,13 +9,13 @@
from rpython.tool.algo.unionfind import UnionFind
from rpython.flowspace.model import (
- Variable, Constant, checkgraph, mkentrymap)
+ Variable, Constant, checkgraph, mkentrymap, const, Link)
from rpython.flowspace.operation import OverflowingOperation, op
from rpython.rlib import rarithmetic
from rpython.translator import unsimplify
from rpython.rtyper.lltypesystem import lloperation, lltype
from rpython.translator.backendopt.ssa import (
- SSA_to_SSI, DataFlowFamilyBuilder)
+ SSA_to_SSI, DataFlowFamilyBuilder)
def get_graph(arg, translator):
if isinstance(arg, Variable):
@@ -327,6 +327,62 @@
stack.extend(link.target.exits)
seen[link.target] = True
+def specialize_exceptions(graph):
+ for block in list(graph.iterblocks()):
+ if block.canraise:
+ op = block.raising_op
+ if op.canraise != [Exception]:
+ normal_exit, exc_exit = block.exits
+ exits = []
+ for case in op.canraise:
+ if case is Exception:
+ exits.append(exc_exit)
+ else:
+ v_exctype = const(case)
+ v_excvalue = Variable('last_exc_value')
+ subs = {
+ exc_exit.last_exception: v_exctype,
+ exc_exit.last_exc_value: v_excvalue}
+ link = exc_exit
+ computed_target = None
+ seen = set()
+ while True:
+ curr_target = link.target
+ assert link not in seen
+ seen.add(link)
+ for v_src, v_target in zip(link.args, curr_target.inputargs):
+ subs[v_target] = v_src.replace(subs)
+ for op in curr_target.operations:
+ new_op = op.replace(subs)
+ v_const = new_op.constfold()
+ if v_const is None:
+ computed_target = link.target
+ break
+ subs[op.result] = v_const
+ if computed_target:
+ break
+ if not curr_target.exits:
+ computed_target = curr_target
+ break
+ elif len(curr_target.exits) == 1 or curr_target.canraise:
+ link = curr_target.exits[0]
+ else:
+ v_case = curr_target.exitswitch.replace(subs)
+ if isinstance(v_case, Constant):
+ for exit in curr_target.exits:
+ if exit.exitcase == v_case.value:
+ link = exit
+ break
+ else:
+ assert False
+ vars = [v.replace(subs) for v in computed_target.inputargs]
+ new_link = Link(vars, computed_target, case)
+ new_link.extravars(v_exctype, v_excvalue)
+ exits.append(new_link)
+ exits = [normal_exit] + exits
+ block.recloseblock(*exits)
+
+
def remove_assertion_errors(graph):
"""Remove branches that go directly to raising an AssertionError,
assuming that AssertionError shouldn't occur at run-time. Note that
More information about the pypy-commit
mailing list