[pypy-svn] r74049 - in pypy/branch/blackhole-improvement/pypy/jit/codewriter: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Apr 25 11:38:54 CEST 2010
Author: arigo
Date: Sun Apr 25 11:38:53 2010
New Revision: 74049
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
Log:
Add SwitchDictDescr to handle large switches.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py Sun Apr 25 11:38:53 2010
@@ -42,6 +42,9 @@
def __iter__(self):
return iter(self.content)
+class SwitchDictDescr(AbstractDescr):
+ "Get a 'dict' attribute mapping integer values to bytecode positions."
+
KINDS = ['int', 'ref', 'float']
# ____________________________________________________________
@@ -126,12 +129,15 @@
def insert_exits(self, block):
if len(block.exits) == 1:
+ # A single link, fall-through
link = block.exits[0]
assert link.exitcase is None
self.make_link(link)
+ #
elif len(block.exits) == 2 and (
isinstance(block.exitswitch, tuple) or
block.exitswitch.concretetype == lltype.Bool):
+ # Two exit links with a boolean condition
linkfalse, linktrue = block.exits
if linkfalse.llexitcase == True:
linkfalse, linktrue = linktrue, linkfalse
@@ -151,14 +157,40 @@
# false path:
self.emitline(Label(linkfalse))
self.make_link(linkfalse)
+ #
else:
+ # A switch.
+ #
+ def emitdefaultpath():
+ if block.exits[-1].exitcase == 'default':
+ self.make_link(block.exits[-1])
+ else:
+ self.emitline('unreachable')
+ #
switches = [link for link in block.exits
if link.exitcase != 'default']
- if len(switches) >= 5 and isinstance(block.exitswitch.concretetype,
- lltype.Primitive):
- XXX
+ switches.sort(key=lambda link: link.llexitcase)
+ kind = getkind(block.exitswitch.concretetype)
+ if len(switches) >= 5 and kind == 'int':
+ # A large switch on an integer, implementable efficiently
+ # with the help of a SwitchDictDescr
+ switchdict = SwitchDictDescr()
+ switchdict._labels = []
+ self.emitline('switch', self.getcolor(block.exitswitch),
+ switchdict)
+ emitdefaultpath()
+ #
+ for switch in switches:
+ key = lltype.cast_primitive(lltype.Signed,
+ switch.llexitcase)
+ switchdict._labels.append((key, TLabel(switch)))
+ # emit code for that path
+ self.emitline(Label(switch))
+ self.make_link(switch)
+ #
else:
- kind = getkind(block.exitswitch.concretetype)
+ # A switch with several possible answers, though not too
+ # many of them -- a chain of int_eq comparisons is fine
assert kind == 'int' # XXX
for switch in switches:
# make the case described by 'switch'
@@ -172,10 +204,7 @@
# finally, emit the label for the "non-taken" path
self.emitline(Label(switch))
#
- if block.exits[-1].exitcase == 'default':
- self.make_link(block.exits[-1])
- else:
- self.emitline('unreachable')
+ emitdefaultpath()
def insert_renamings(self, link):
renamings = {}
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py Sun Apr 25 11:38:53 2010
@@ -1,7 +1,7 @@
import py
from pypy.objspace.flow.model import Constant
from pypy.jit.codewriter.flatten import SSARepr, Label, TLabel, Register
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import ListOfKind, SwitchDictDescr
from pypy.jit.metainterp.history import AbstractDescr
@@ -19,19 +19,19 @@
return getlabelname(x)
elif isinstance(x, ListOfKind):
return '%s[%s]' % (x.kind[0].upper(), ', '.join(map(repr, x)))
+ elif isinstance(x, SwitchDictDescr):
+ return '<SwitchDictDescr %s>' % (
+ ', '.join(['%s:%s' % (key, getlabelname(lbl))
+ for key, lbl in x._labels]))
elif isinstance(x, AbstractDescr):
return '%r' % (x,)
else:
return '<unknown object: %r>' % (x,)
#
seenlabels = {}
- for asm in ssarepr.insns:
- for x in asm:
- if isinstance(x, TLabel):
- seenlabels[x.name] = -1
labelcount = [0]
def getlabelname(lbl):
- if seenlabels[lbl.name] == -1:
+ if lbl.name not in seenlabels:
labelcount[0] += 1
seenlabels[lbl.name] = labelcount[0]
return 'L%d' % seenlabels[lbl.name]
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py Sun Apr 25 11:38:53 2010
@@ -176,3 +176,29 @@
L3:
int_return $42
""")
+
+ def test_switch_dict(self):
+ def f(x):
+ if x == 1: return 61
+ elif x == 2: return 511
+ elif x == 3: return -22
+ elif x == 4: return 81
+ elif x == 5: return 17
+ elif x == 6: return 54
+ return -1
+ self.encoding_test(f, [65], """
+ switch %i0, <SwitchDictDescr 1:L1, 2:L2, 3:L3, 4:L4, 5:L5, 6:L6>
+ int_return $-1
+ L1:
+ int_return $61
+ L2:
+ int_return $511
+ L3:
+ int_return $-22
+ L4:
+ int_return $81
+ L5:
+ int_return $17
+ L6:
+ int_return $54
+ """)
More information about the Pypy-commit
mailing list