Author: Richard Plangger <r...@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit