[pypy-commit] pypy regalloc: added more information to the output of regalloc.py

plan_rich noreply at buildbot.pypy.org
Mon Jun 22 12:08:44 CEST 2015


Author: Richard Plangger <rich at pasra.at>
Branch: regalloc
Changeset: r78242:ce341006d844
Date: 2015-06-22 12:08 +0200
http://bitbucket.org/pypy/pypy/changeset/ce341006d844/

Log:	added more information to the output of regalloc.py

diff --git a/rpython/jit/backend/tool/regalloc.py b/rpython/jit/backend/tool/regalloc.py
--- a/rpython/jit/backend/tool/regalloc.py
+++ b/rpython/jit/backend/tool/regalloc.py
@@ -1,6 +1,9 @@
 #! /usr/bin/env python
 """
-    ./regalloc.py log
+    Prints information about the live range of a trace recorded in the specified logfiles.
+    It aggregates the information over all traces in the logfiles.
+
+    ./regalloc.py [--histogram] logfile1 [logfile2 ...]
 """
 
 import new
@@ -93,7 +96,7 @@
         if not isinstance(typedescr,str):
             typename = typedescr[0]
         lrt = self.entries.setdefault(typename,[])
-        lrt.append((arg, lr))
+        lrt.append((self.operations, lr))
 
     def active_live_ranges(self, position):
         active = []
@@ -120,8 +123,6 @@
             if start == loop_start and end == loop_end:
                 self.found_live_range(LR.WHOLE, arg, lr)
                 self.find_fail_type(LR.WHOLE, arg, lr)
-                if len(uses) == 2:
-                    self.found_live_range(LR.DUMMY, arg, lr)
             elif start == loop_start and end != loop_end:
                 self.found_live_range(LR.ENTER, arg, lr)
                 self.find_fail_type(LR.ENTER, arg, lr)
@@ -150,6 +151,8 @@
             op = self.operations[uses[-1]]
             if op.getfailargs() is not None and arg in op.getfailargs():
                 self.found_live_range('-'.join((typename, LR.FAIL[0], LR.END_FAIL[0])), arg, lr)
+            if len(uses) - 1 == used_in_guard:
+                self.found_live_range('-'.join((typename, LR.FAIL[0], LR.ONLY_FAIL[0])), arg, lr)
 
     def count(self, typedescr):
         return len(self.entries.get(typedescr[0],[]))
@@ -162,35 +165,34 @@
 class LR(object):
 
     WHOLE = ('whole', """
-    a live range that spans over the whole trace, use x times. (x > 0)
+    a live range that spans over the whole trace, used x times. (x > 0)
     """)
     ENTER = ('enter', """
-    a live range that spans from the label to an operation (not jump/label)
+    a live range that spans from the label to an operation (but not jump/label)
     """)
     EXIT = ('exit', """
-    a live range that starts at operation X (not at a label) and exits the trace in a jump or guard
+    a live range that starts at operation X (not at a label) and exits the trace in a jump
     """)
     VOLATILE = ('volatile', """
     a live range that starts at operation X (not a label) and ends at operation Y (not a jump/label)
     """)
     ALL_TYPES = [WHOLE, ENTER, EXIT, VOLATILE]
 
+    ONLY_FAIL = ('only failarg', """
+    a live range that is used only as fail arguments
+    """)
     FAIL = ('used as failargs', """
-    a live range that spans from the label to a guard exit may be used several times in between
+    a live range that is used in a guard exit as fail argument
     """)
     END_FAIL = ('end in failargs',"""
-    a live range that spans from the label to a guard exit (can be used only in guard fail args)
+    a live range that ends in a guard exit
     """)
     NO_FAIL = ('not in any failargs', """
-    same as enter, but is not used in guard exit
+    a live range that is not used as a fail argument
     """)
 
     FAIL_TYPES = [FAIL, NO_FAIL]
 
-    DUMMY = ('dummy', """
-    a live range that spans over the whole trace, but is never used
-    """)
-
     def __init__(self):
         self.loops = []
 
@@ -207,53 +209,107 @@
     def header(self, name):
         print name
 
-    def print_stats(self):
+    def print_stats(self, histogram=False):
         print
         self.header("STATS")
         normal = [l for l in self.loops if l.type == 'normal']
         loop_count = len(normal)
         peeled = [l for l in self.loops if l.type == 'peeled']
+        bridges = [l for l in self.loops if l.type == 'bridge']
         peeled_count = len(peeled)
         self.show("loop count", loop_count)
         self.show("peeled count", peeled_count)
+        self.show("bridge count", len(bridges))
+
+        self.header("")
+        self.header("BRIDGES")
+        self.print_for_loops(bridges, hist=histogram)
 
         self.header("")
         self.header("SHELL LOOPS (loop that are not unrolled or enter a peeled loop)")
-        self.print_for_loops(normal)
+        self.print_for_loops(normal, hist=histogram)
 
         self.header("")
         self.header("PEELED LOOPS")
-        self.print_for_loops(peeled)
+        self.print_for_loops(peeled, hist=histogram)
 
 
-    def print_for_loops(self, loops):
+    def show_help(self, help, descr, indent):
+        if help:
+            print " " * (indent * 2), "%s: %s" % (descr[0], descr[1].lstrip().rstrip())
+
+    def print_for_loops(self, loops, help=True, hist=True):
         lr_counts = []
         for loop in loops:
             lr_counts.append(len(loop.longevity))
-        self.show_cmv('lr count', lr_counts)
-        self.show_cmv('lr (overlap) max', map(lambda x: getattr(x, 'lr_active_max'), loops))
-        self.show_cmv('lr (overlap) min', map(lambda x: getattr(x, 'lr_active_min'), loops))
+        self.show_help(True, ('lr (overlap) max', 'the max number of live ranges that overlap in a trace'), 0)
+        self.show_cmv('lr (overlap) max', map(lambda x: getattr(x, 'lr_active_max'), loops), histogram=hist, integer=True)
+        self.show_help(True, ('lr (overlap) min', 'the min number of live ranges that overlap in a trace'), 0)
+        self.show_cmv('lr (overlap) min', map(lambda x: getattr(x, 'lr_active_min'), loops), histogram=False, integer=True)
+        self.show_help(True, ('lr count', 'the live range count'), 0)
+        self.show_cmv('lr count', lr_counts, histogram=hist, integer=True)
         for typedescr in LR.ALL_TYPES:
             typename = typedescr[0]
             lrs = self.all_entries(loops, typename)
-            counts = map(lambda e: len(e), lrs)
-            self.show_cmv(typename, counts, 0)
+            self.show_help(help, typedescr, 0)
+            self.show_cmv(typename, lrs, 0, histogram=hist)
             #
             for failtypedescr in LR.FAIL_TYPES:
                 failtypename = typename + '-' + failtypedescr[0]
                 lrs = self.all_entries(loops, failtypename)
-                counts = map(lambda e: len(e), lrs)
-                self.show_cmv(failtypename, counts, 1)
+                self.show_help(help, failtypedescr, 1)
+                self.show_cmv(failtypename, lrs, 1, histogram=hist)
 
                 if failtypedescr == LR.FAIL:
+                    self.show_help(help, LR.END_FAIL, 2)
                     failtypename = failtypename + '-' + LR.END_FAIL[0]
                     lrs = self.all_entries(loops, failtypename)
-                    counts = map(lambda e: len(e), lrs)
-                    self.show_cmv(failtypename, counts, 2)
+                    self.show_cmv(failtypename, lrs, 2, histogram=hist)
 
-    def show_cmv(self, name, counts, indent=0):
-        total = sum(counts)
-        self.show(name, "mean %.2f\tvar %.2f\tcount %d" % (self.mean(counts), self.var(counts), total), indent=indent)
+                    self.show_help(help, LR.ONLY_FAIL, 2)
+                    failtypename = failtypename + '-' + LR.ONLY_FAIL[0]
+                    lrs = self.all_entries(loops, failtypename)
+                    self.show_cmv(failtypename, lrs, 2, histogram=hist)
+
+    def show_cmv(self, name, loop_lrs, indent=0, histogram=True, integer=False):
+        indent = " " * (indent * 2)
+        if integer:
+            counts = loop_lrs
+        else:
+            counts = map(lambda e: len(e), loop_lrs)
+            use_count = []
+            use_guard_count = []
+            for lrs in loop_lrs:
+                for ops, lr in lrs:
+                    count = 0
+                    gcount = 0
+                    for use in lr[2][1:]:
+                        op = ops[use]
+                        if op.is_guard():
+                            gcount += 1
+                        count += 1
+                    use_count.append(count)
+                    use_guard_count.append(gcount)
+
+            if len(use_count) > 0:
+                print indent, " #use: mean %.2f std %.2f" % (self.mean(use_count), self.var(use_count))
+            if len(use_guard_count) > 0:
+                print indent, " guard #use: mean %.2f std %.2f" % (self.mean(use_guard_count), self.var(use_guard_count))
+
+        total = len(counts)
+        total_sum = sum(counts)
+        min_counts = min(counts)
+        max_counts = max(counts)
+        print indent," mean %.2f std %.2f" % (self.mean(counts),self.var(counts))
+        print indent," min %d max %d" % (min_counts,max_counts)
+        if histogram:
+            import numpy
+            hist, bins = numpy.histogram(counts,bins=5)
+            for i in range(5):
+                l = bins[i]
+                u = bins[i+1]
+                v = hist[i]
+                print indent, " [%.1f-%.1f): %d (%.1f%%)" % (l, u, int(v), (100*float(v)/len(counts)))
 
     def mean(self, values):
         if len(values) == 0:
@@ -270,74 +326,97 @@
             type = type[0]
         entries = []
         for loop in loops:
-            e = loop.entries.get(type, [])
-            entries.append(e)
+            lrs = loop.entries.get(type, [])
+            entries.append(lrs)
         return entries
 
 
-    def examine(self, inputargs, operations, peeled=False):
+    def examine(self, inputargs, operations, peeled=False, bridge=False):
         llr = LoopLiveRanges(inputargs, operations)
         llr.type = 'normal'
         if peeled:
             llr.type = 'peeled'
+        if bridge:
+            llr.type = 'bridge'
         self.loops.append(llr)
 
 # ____________________________________________________________
 
 if __name__ == '__main__':
     from rpython.tool import logparser
-    log1 = logparser.parse_log_file(sys.argv[1])
-    loops = logparser.extract_category(log1, catprefix='jit-log-compiling-loop')
+    histogram = False
+    if '--histogram' in sys.argv:
+        histogram = True
+        sys.argv.remove('--histogram')
     lr = LR()
-    ns = {}
-    loop_count = len(loops)
-    print
     skipped = []
     skipped_not_loop = []
-    for j,text in enumerate(loops):
-        parser = RegallocParser(text)
-        loop = parser.parse()
-        unrolled_label = -1
-        first_label = -1
-        for i,op in enumerate(loop.operations):
-            if op.getopnum() == rop.LABEL:
+    total_trace_count = 0
+    for logfile in sys.argv[1:]:
+        print "reading",logfile,"..."
+        log1 = logparser.parse_log_file(logfile)
+        loops = logparser.extract_category(log1, catprefix='jit-log-opt-loop')
+        ns = {}
+        loop_count = len(loops)
+        total_trace_count += loop_count
+        for j,text in enumerate(loops):
+            parser = RegallocParser(text)
+            loop = parser.parse()
+            unrolled_label = -1
+            first_label = -1
+            for i,op in enumerate(loop.operations):
+                if op.getopnum() == rop.LABEL:
+                    if first_label == -1:
+                        first_label = i
+                    else:
+                        unrolled_label = i
+
+            if loop.operations[-1].getopnum() != rop.JUMP:
+                assert loop.operations[-1].getopnum() == rop.FINISH
+                skipped_not_loop.append(loop)
+                continue
+
+            if first_label != 0:
+                if first_label == -1 and loop.operations[-1].getopnum() == rop.JUMP:
+                    assert unrolled_label == -1
+                    # add an artificial instruction to support the live range computation
+                    #loop.operations.insert(0, ResOperation(rop.LABEL, [inputargs], None, None))
+                else:
+                    first_label = 0
+                    #skipped.append(loop)
+                    #continue
+
+            if unrolled_label > 0:
+                ops = loop.operations[first_label:unrolled_label+1]
+                #    for op in ops:
+                #        print op
+                #    print '=' * 80
+                inputargs = loop.inputargs
+                lr.examine(inputargs, ops, peeled=False)
+                # peeled loop
+                ops = loop.operations[unrolled_label:]
+                #for op in ops:
+                #    print op
+                label = ops[0]
+                inputargs = label.getarglist()
+                lr.examine(inputargs, ops, peeled=True)
+                #print '-' * 80
+            else:
                 if first_label == -1:
-                    first_label = i
+                    ops = loop.operations
+                    bridge = True
                 else:
-                    unrolled_label = i
-
-        if loop.operations[-1].getopnum() != rop.JUMP:
-            skipped_not_loop.append(loop)
-            continue
-        
-        if first_label != 0:
-            skipped.append(loop)
-            continue
-
-        if unrolled_label > 0:
-            ops = loop.operations[first_label:unrolled_label+1]
-            #    for op in ops:
-            #        print op
-            #    print '=' * 80
-            inputargs = loop.inputargs
-            lr.examine(inputargs, ops, peeled=False)
-            # peeled loop
-            ops = loop.operations[unrolled_label:]
-            #for op in ops:
-            #    print op
-            label = ops[0]
-            inputargs = label.getarglist()
-            lr.examine(inputargs, ops, peeled=True)
-            #print '-' * 80
-        else:
-            ops = loop.operations[first_label:]
-            #for op in ops:
-            #    print op
-            #print '-' * 80
-            inputargs = loop.inputargs
-            lr.examine(inputargs, ops, peeled=False)
-        print "\rloop %d/%d (%d%%)" % (j, loop_count, int(100.0 * j / loop_count)),
-        sys.stdout.flush()
+                    ops = loop.operations[first_label:]
+                    bridge = False
+                #for op in ops:
+                #    print op
+                #print '-' * 80
+                inputargs = loop.inputargs
+                lr.examine(inputargs, ops, peeled=False, bridge=bridge)
+            print "\rloop %d/%d (%d%%)" % (j, loop_count, int(100.0 * j / loop_count)),
+            sys.stdout.flush()
+        print
+    print "total trace count:", total_trace_count
     
     if len(skipped) > 0:
         print
@@ -347,4 +426,4 @@
         print
         print "skipped %d traces (not loops but traces)" % len(skipped_not_loop)
 
-    lr.print_stats()
+    lr.print_stats(histogram)


More information about the pypy-commit mailing list