[pypy-svn] r37479 - in pypy/dist/pypy: config translator/backendopt translator/c/src translator/c/test

pedronis at codespeak.net pedronis at codespeak.net
Sun Jan 28 18:07:02 CET 2007


Author: pedronis
Date: Sun Jan 28 18:06:57 2007
New Revision: 37479

Modified:
   pypy/dist/pypy/config/translationoption.py
   pypy/dist/pypy/translator/backendopt/all.py
   pypy/dist/pypy/translator/c/src/instrument.h
   pypy/dist/pypy/translator/c/test/test_standalone.py
Log:
let use all inlining strategies together with options for threshold and weight heuristic for all of them.

fix a bug with instrumentation counters where there were 0 of them in the produced executable, this would create
a -1 big file :(



Modified: pypy/dist/pypy/config/translationoption.py
==============================================================================
--- pypy/dist/pypy/config/translationoption.py	(original)
+++ pypy/dist/pypy/config/translationoption.py	Sun Jan 28 18:06:57 2007
@@ -6,6 +6,9 @@
 DEFL_INLINE_THRESHOLD = 32.4    # just enough to inline add__Int_Int()
 # and just small enough to prevend inlining of some rlist functions.
 
+DEFL_PROF_BASED_INLINE_THRESHOLD = 32.4
+DEFL_CLEVER_MALLOC_REMOVAL_INLINE_THRESHOLD = 32.4
+
 translation_optiondescription = OptionDescription(
         "translation", "Translation Options", [
     BoolOption("stackless", "compile stackless features in",
@@ -90,6 +93,14 @@
                  default=None, cmdline="--fork-before"),
 
     OptionDescription("backendopt", "Backend Optimization Options", [
+        # control inlining
+        FloatOption("inline_threshold", "Threshold when to inline functions",
+                  default=DEFL_INLINE_THRESHOLD, cmdline="--inline-threshold"),
+        StrOption("inline_heuristic", "Dotted name of an heuristic function "
+                  "for inlining",
+                default="pypy.translator.backendopt.inline.inlining_heuristic",
+                cmdline="--inline-heuristic"),
+        
         BoolOption("print_statistics", "Print statistics while optimizing",
                    default=False),
         BoolOption("merge_if_blocks", "Merge if ... elif chains",
@@ -103,17 +114,40 @@
         BoolOption("heap2stack", "Escape analysis and stack allocation",
                    default=False,
                    requires=[("translation.stackless", False)]),
-        BoolOption("clever_malloc_removal",
-                   "Remove mallocs in a clever way", default=False),
-        BoolOption("remove_asserts",
-                   "Kill 'raise AssertionError', which lets the C "
-                   "optimizer remove the asserts", default=False),
-        FloatOption("inline_threshold", "Threshold when to inline functions",
-                  default=DEFL_INLINE_THRESHOLD, cmdline="--inline-threshold"),
+        # control profile based inlining
         StrOption("profile_based_inline",
                   "Use call count profiling to drive inlining"
                   ", specify arguments",
                   default=None, cmdline="--prof-based-inline"),
+        FloatOption("profile_based_inline_threshold",
+                    "Threshold when to inline functions "
+                    "for profile based inlining",
+                  default=DEFL_PROF_BASED_INLINE_THRESHOLD,
+                  cmdline="--prof-based-inline-threshold"),
+        StrOption("profile_based_inline_heuristic",
+                  "Dotted name of an heuristic function "
+                  "for profile based inlining",
+                default="pypy.translator.backendopt.inline.inlining_heuristic",
+                cmdline="--prof-based-inline-heuristic"),
+        # control clever malloc removal
+        BoolOption("clever_malloc_removal",
+                   "Drives inlining to remove  mallocs in a clever way",
+                   default=False,
+                   cmdline="--clever-malloc-removal"),
+        FloatOption("clever_malloc_removal_threshold",
+                    "Threshold when to inline functions in "
+                    "clever malloc removal",
+                  default=DEFL_CLEVER_MALLOC_REMOVAL_INLINE_THRESHOLD,
+                  cmdline="--clever-malloc-removal-threshold"),
+        StrOption("clever_malloc_removal_heuristic",
+                  "Dotted name of an heuristic function "
+                  "for inlining in clever malloc removal",
+                default="pypy.translator.backendopt.inline.inlining_heuristic",
+                cmdline="--clever-malloc-removal-heuristic"),
+
+        BoolOption("remove_asserts",
+                   "Kill 'raise AssertionError', which lets the C "
+                   "optimizer remove the asserts", default=False),
     ]),
 
     OptionDescription("cli", "GenCLI options", [

Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Sun Jan 28 18:06:57 2007
@@ -15,6 +15,22 @@
 
 INLINE_THRESHOLD_FOR_TEST = 33
 
+def get_function(dottedname):
+    parts = dottedname.split('.')
+    module = '.'.join(parts[:-1])
+    name = parts[-1]
+    try:
+        mod = __import__(module, {}, {}, ['__doc__'])
+    except ImportError, e:
+        raise Exception, "Import error loading %s: %s" % (dottedname, e)
+
+    try:
+        func = getattr(mod, name)
+    except AttributeError:
+        raise Exception, "Function %s not found in module" % dottedname
+
+    return func
+
 def backend_optimizations(translator, graphs=None, secondary=False, **kwds):
     # sensible keywords are
     # raisingop2direct_call, inline_threshold, mallocs
@@ -48,35 +64,44 @@
         print "after no-op removal:"
         print_statistics(translator.graphs[0], translator)
 
-    if not config.clever_malloc_removal:
-        if config.profile_based_inline and not secondary:
-            inline_malloc_removal_phase(config, translator, graphs,
-                                        config.inline_threshold*.5) # xxx tune!
-            inline.instrument_inline_candidates(graphs, config.inline_threshold)
-            counters = translator.driver_instrument_result(
-                       config.profile_based_inline)
-            n = len(counters)
-            def call_count_pred(label):
-                if label >= n:
-                    return False
-                return counters[label] > 250 # xxx tune!
-        else:
-            call_count_pred = None
+    if config.inline_threshold != 0:
+        heuristic = get_function(config.inline_heuristic)
         inline_malloc_removal_phase(config, translator, graphs,
                                     config.inline_threshold,
-                                    call_count_pred=call_count_pred)
-    else:
-        count = mallocprediction.preparation(translator, graphs, 15)
-        count += mallocprediction.clever_inlining_and_malloc_removal(
-            translator, graphs, 33)
+                                    inline_heuristic=heuristic)
+
+    if config.clever_malloc_removal:
+        threshold = config.clever_malloc_removal_threshold
+        heuristic = get_function(config.clever_malloc_removal_heuristic)        
+        log.inlineandremove("phase with threshold factor: %s" % threshold)
+        log.inlineandremove("heuristic: %s.%s" % (heuristic.__module__,
+                                                  heuristic.__name__))
+        count = mallocprediction.clever_inlining_and_malloc_removal(
+            translator, graphs,
+            threshold = threshold,
+            heuristic=heuristic)
         log.inlineandremove("removed %d simple mallocs in total" % count)
+        constfold(config, graphs)
         if config.print_statistics:
             print "after clever inlining and malloc removal"
-            print_statistics(translator.graphs[0], translator)
+            print_statistics(translator.graphs[0], translator)        
 
-    if config.constfold:
-        for graph in graphs:
-            constant_fold_graph(graph)
+
+    if config.profile_based_inline and not secondary:
+        threshold = config.profile_based_inline_threshold
+        heuristic = get_function(config.profile_based_inline_heuristic)
+        inline.instrument_inline_candidates(graphs, threshold)
+        counters = translator.driver_instrument_result(
+            config.profile_based_inline)
+        n = len(counters)
+        def call_count_pred(label):
+            if label >= n:
+                return False
+            return counters[label] > 250 # xxx introduce an option for this
+        inline_malloc_removal_phase(config, translator, graphs,
+                                    threshold,
+                                    inline_heuristic=heuristic,
+                                    call_count_pred=call_count_pred)
 
     if config.remove_asserts:
         remove_asserts(translator, graphs)
@@ -96,15 +121,24 @@
     for graph in graphs:
         checkgraph(graph)
 
+def constfold(config, graphs):
+    if config.constfold:
+        for graph in graphs:
+            constant_fold_graph(graph)    
+
 def inline_malloc_removal_phase(config, translator, graphs, inline_threshold,
+                                inline_heuristic,
                                 call_count_pred=None):
 
     type_system = translator.rtyper.type_system.name
     log.inlining("phase with threshold factor: %s" % inline_threshold)
+    log.inlining("heuristic: %s.%s" % (inline_heuristic.__module__,
+                                       inline_heuristic.__name__))
 
     # inline functions in each other
     if inline_threshold:
         inline.auto_inline_graphs(translator, graphs, inline_threshold,
+                                  heuristic=inline_heuristic,
                                   call_count_pred=call_count_pred)
 
         if config.print_statistics:
@@ -119,7 +153,5 @@
             print "after malloc removal:"
             print_statistics(translator.graphs[0], translator)    
 
-    if config.constfold:
-        for graph in graphs:
-            constant_fold_graph(graph)
+    constfold(config, graphs)
 

Modified: pypy/dist/pypy/translator/c/src/instrument.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/instrument.h	(original)
+++ pypy/dist/pypy/translator/c/src/instrument.h	Sun Jan 28 18:06:57 2007
@@ -16,7 +16,7 @@
 
 typedef unsigned long instrument_count_t;
 
-instrument_count_t *_instrument_counters;
+instrument_count_t *_instrument_counters = NULL;
 
 void instrument_setup() {
 	char *fname = getenv("_INSTRUMENT_COUNTERS");
@@ -25,15 +25,17 @@
 		void *buf;
 		size_t sz = sizeof(instrument_count_t)*INSTRUMENT_NCOUNTER;
 		fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0744);
-		lseek(fd, sz-1, SEEK_SET);
-		write(fd, "", 1);
-		buf = mmap(NULL, sz, PROT_WRITE|PROT_READ, MAP_SHARED,
-		   fd, 0);
-		if (buf == MAP_FAILED) {
-			fprintf(stderr, "mapping instrument counters file failed\n");
-			abort();
+		if (sz > 0) {
+			lseek(fd, sz-1, SEEK_SET);
+			write(fd, "", 1);
+			buf = mmap(NULL, sz, PROT_WRITE|PROT_READ, MAP_SHARED,
+				   fd, 0);
+			if (buf == MAP_FAILED) {
+				fprintf(stderr, "mapping instrument counters file failed\n");
+				abort();
+			}
+			_instrument_counters = (instrument_count_t *)buf;
 		}
-		_instrument_counters = (instrument_count_t *)buf;
 	}
 }
 

Modified: pypy/dist/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_standalone.py	Sun Jan 28 18:06:57 2007
@@ -2,6 +2,7 @@
 import sys, os
 
 from pypy.translator.translator import TranslationContext
+from pypy.translator.backendopt import all
 from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.annotation.listdef import s_list_of_strings
 from pypy.tool.udir import udir
@@ -103,7 +104,16 @@
         return 0
     from pypy.translator.interactive import Translation
     t = Translation(entry_point, backend='c', standalone=True)
-    t.backendopt(profile_based_inline="500")
+    # no counters
+    t.backendopt(inline_threshold=100, profile_based_inline="500")
+    exe = t.compile()
+    out = py.process.cmdexec("%s 500" % exe)
+    assert int(out) == 500*501/2
+
+    t = Translation(entry_point, backend='c', standalone=True)
+    # counters
+    t.backendopt(inline_threshold=all.INLINE_THRESHOLD_FOR_TEST*0.5,
+                 profile_based_inline="500")
     exe = t.compile()
     out = py.process.cmdexec("%s 500" % exe)
     assert int(out) == 500*501/2



More information about the Pypy-commit mailing list