[pypy-svn] r46616 - in pypy/dist/pypy/translator: c/test cli jvm oosupport
antocuni at codespeak.net
antocuni at codespeak.net
Sat Sep 15 11:35:03 CEST 2007
Author: antocuni
Date: Sat Sep 15 11:35:03 2007
New Revision: 46616
Modified:
pypy/dist/pypy/translator/c/test/test_backendoptimized.py
pypy/dist/pypy/translator/cli/function.py
pypy/dist/pypy/translator/jvm/generator.py
pypy/dist/pypy/translator/jvm/node.py
pypy/dist/pypy/translator/oosupport/function.py
Log:
use jvm's tableswitch to implement numeric switch.
Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_backendoptimized.py (original)
+++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Sat Sep 15 11:35:03 2007
@@ -104,6 +104,34 @@
for x in (0,1,2,3,9,27,48, -9):
assert fn(x) == f(x)
+ def test_int_switch_nonsparse(self):
+ def f(x):
+ if x == 1:
+ return 9
+ elif x == 2:
+ return 27
+ elif x == 3:
+ return 3
+ return 0
+ codegenerator = self.CodeGenerator()
+ fn = codegenerator.getcompiled(f, [int])
+ for x in (0,1,2,3,9,27,48, -9):
+ assert fn(x) == f(x)
+
+ def test_int_switch_nonsparse_neg(self):
+ def f(x):
+ if x == -1:
+ return 9
+ elif x == 2:
+ return 27
+ elif x == 3:
+ return 3
+ return 0
+ codegenerator = self.CodeGenerator()
+ fn = codegenerator.getcompiled(f, [int])
+ for x in (0,1,2,3,9,27,48, -9):
+ assert fn(x) == f(x)
+
def test_uint_switch(self):
def f(x):
if x == r_uint(3):
Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py (original)
+++ pypy/dist/pypy/translator/cli/function.py Sat Sep 15 11:35:03 2007
@@ -166,28 +166,10 @@
self.render_numeric_switch_naive(block)
return
- cases = {}
- naive = False
- for link in block.exits:
- if link.exitcase == "default":
- default = link, self.next_label('switch')
- else:
- if block.exitswitch.concretetype in (ootype.Char, ootype.UniChar):
- value = ord(link.exitcase)
- else:
- value = link.exitcase
- if value < 0:
- naive = True
- break
- cases[value] = link, self.next_label('switch')
-
- try:
- max_case = max(cases.keys())
- except ValueError:
- max_case = 0
- if max_case > 3*len(cases) + 10: # the switch is very sparse, better to use the naive version
- naive = True
+ cases, min_case, max_case, default = self._collect_switch_cases(block)
+ is_sparse = self._is_sparse_switch(cases, min_case, max_case)
+ naive = (min_case < 0) or is_sparse
if naive:
self.render_numeric_switch_naive(block)
return
@@ -202,12 +184,6 @@
for link, lbl in cases.itervalues():
self.render_switch_case(link, lbl)
- def render_switch_case(self, link, label):
- target_label = self._get_block_name(link.target)
- self.set_label(label)
- self._setup_link(link)
- self.generator.branch_unconditionally(target_label)
-
# Those parts of the generator interface that are function
# specific
Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py (original)
+++ pypy/dist/pypy/translator/jvm/generator.py Sat Sep 15 11:35:03 2007
@@ -1380,6 +1380,7 @@
return self.curfunc.instr_counter
def emit_tableswitch(self, low, lbls, default):
- pass
-
-
+ self.curclass.out(' tableswitch %d\n' % low)
+ for label in lbls:
+ self.curclass.out(' %s\n' % label.jasmin_syntax())
+ self.curclass.out(' default: %s\n' % default.jasmin_syntax())
Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py (original)
+++ pypy/dist/pypy/translator/jvm/node.py Sat Sep 15 11:35:03 2007
@@ -35,6 +35,7 @@
push_constant
import pypy.translator.jvm.generator as jvmgen
+from pypy.translator.jvm.log import log
class Node(object):
def set_db(self, db):
@@ -327,6 +328,33 @@
self.ilasm.store(link.last_exc_value)
self._setup_link(link)
+ def render_numeric_switch(self, block):
+ if block.exitswitch.concretetype in (ootype.SignedLongLong, ootype.UnsignedLongLong):
+ # TODO: it could be faster to check is the values fit in
+ # 32bit, and perform a cast in that case
+ self.render_numeric_switch_naive(block)
+ return
+
+ cases, min_case, max_case, default = self._collect_switch_cases(block)
+ is_sparse = self._is_sparse_switch(cases, min_case, max_case)
+
+ if is_sparse:
+ log.WARNING('TODO: use lookupswitch to render sparse numeric_switches')
+ self.render_numeric_switch_naive(block)
+ return
+
+ targets = []
+ for i in xrange(min_case, max_case+1):
+ link, lbl = cases.get(i, default)
+ targets.append(lbl)
+
+ self.generator.load(block.exitswitch)
+ self.generator.emit_tableswitch(min_case, targets, default[1])
+
+ self.render_switch_case(*default)
+ for link, lbl in cases.itervalues():
+ self.render_switch_case(link, lbl)
+
def render_return_block(self, block):
return_var = block.inputargs[0]
return_ty = self.db.lltype_to_cts(return_var.concretetype)
Modified: pypy/dist/pypy/translator/oosupport/function.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/function.py (original)
+++ pypy/dist/pypy/translator/oosupport/function.py Sat Sep 15 11:35:03 2007
@@ -227,6 +227,37 @@
log.WARNING("The default version of render_numeric_switch is *slow*: please override it in the backend")
self.render_numeric_switch_naive(block)
+ def _collect_switch_cases(self, block):
+ cases = {}
+ for link in block.exits:
+ if link.exitcase == "default":
+ default = link, self.next_label('switch')
+ else:
+ if block.exitswitch.concretetype in (ootype.Char, ootype.UniChar):
+ value = ord(link.exitcase)
+ else:
+ value = link.exitcase
+ cases[value] = link, self.next_label('switch')
+
+ values = cases.keys()
+ try:
+ min_case = min(values)
+ max_case = max(values)
+ except ValueError:
+ min_case = max_case = 0
+ return cases, min_case, max_case, default
+
+ def _is_sparse_switch(self, cases, min_case, max_case):
+ if max_case-min_case > 3*len(cases) + 10: # the switch is very sparse, better to use the naive version
+ return True
+ return False
+
+ def render_switch_case(self, link, label):
+ target_label = self._get_block_name(link.target)
+ self.set_label(label)
+ self._setup_link(link)
+ self.generator.branch_unconditionally(target_label)
+
def render_numeric_switch_naive(self, block):
for link in block.exits:
target_label = self._get_block_name(link.target)
More information about the Pypy-commit
mailing list