diff options
author | Martin Liska <mliska@suse.cz> | 2018-01-19 13:03:24 +0100 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2018-01-19 12:03:24 +0000 |
commit | d1b9a5724b8a05d2d2d51b3e5d13cc785326c74f (patch) | |
tree | d863029ec8847f8c570a3e805a923100689efd40 /contrib | |
parent | 09a7858b2c53eccf28f780f5f3e4f2764f440eb1 (diff) | |
download | gcc-d1b9a5724b8a05d2d2d51b3e5d13cc785326c74f.zip gcc-d1b9a5724b8a05d2d2d51b3e5d13cc785326c74f.tar.gz gcc-d1b9a5724b8a05d2d2d51b3e5d13cc785326c74f.tar.bz2 |
Fix usage of analyze_brprob.py script.
2018-01-19 Martin Liska <mliska@suse.cz>
* analyze_brprob.py: Support new format that can be easily
parsed. Add new column to report.
2018-01-19 Martin Liska <mliska@suse.cz>
* predict.c (dump_prediction): Add new format for
analyze_brprob.py script which is enabled with -details
suboption.
* profile-count.h (precise_p): New function.
From-SVN: r256886
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/ChangeLog | 5 | ||||
-rwxr-xr-x | contrib/analyze_brprob.py | 103 |
2 files changed, 77 insertions, 31 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog index b175060..a88e2f0 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,8 @@ +2018-01-19 Martin Liska <mliska@suse.cz> + + * analyze_brprob.py: Support new format that can be easily + parsed. Add new column to report. + 2018-01-03 Jakub Jelinek <jakub@redhat.com> * update-copyright.py: Skip pdt-5.f03 in gfortran.dg subdir. diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py index e03d1da..de5f474 100755 --- a/contrib/analyze_brprob.py +++ b/contrib/analyze_brprob.py @@ -71,6 +71,7 @@ from math import * counter_aggregates = set(['combined', 'first match', 'DS theory', 'no prediction']) +hot_threshold = 10 def percentage(a, b): return 100.0 * a / b @@ -131,47 +132,87 @@ class PredictDefFile: with open(self.path, 'w+') as f: for l in modified_lines: f.write(l + '\n') +class Heuristics: + def __init__(self, count, hits, fits): + self.count = count + self.hits = hits + self.fits = fits class Summary: def __init__(self, name): self.name = name - self.branches = 0 - self.successfull_branches = 0 - self.count = 0 - self.hits = 0 - self.fits = 0 + self.edges= [] + + def branches(self): + return len(self.edges) + + def hits(self): + return sum([x.hits for x in self.edges]) + + def fits(self): + return sum([x.fits for x in self.edges]) + + def count(self): + return sum([x.count for x in self.edges]) + + def successfull_branches(self): + return len([x for x in self.edges if 2 * x.hits >= x.count]) def get_hitrate(self): - return 100.0 * self.hits / self.count + return 100.0 * self.hits() / self.count() def get_branch_hitrate(self): - return 100.0 * self.successfull_branches / self.branches + return 100.0 * self.successfull_branches() / self.branches() def count_formatted(self): - v = self.count + v = self.count() for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']: if v < 1000: return "%3.2f%s" % (v, unit) v /= 1000.0 return "%.1f%s" % (v, 'Y') + def count(self): + return sum([x.count for x in self.edges]) + def print(self, branches_max, count_max, predict_def): + # filter out most hot edges (if requested) + self.edges = sorted(self.edges, reverse = True, key = lambda x: x.count) + if args.coverage_threshold != None: + threshold = args.coverage_threshold * self.count() / 100 + edges = [x for x in self.edges if x.count < threshold] + if len(edges) != 0: + self.edges = edges + predicted_as = None if predict_def != None and self.name in predict_def.predictors: predicted_as = predict_def.predictors[self.name] print('%-40s %8i %5.1f%% %11.2f%% %7.2f%% / %6.2f%% %14i %8s %5.1f%%' % - (self.name, self.branches, - percentage(self.branches, branches_max), + (self.name, self.branches(), + percentage(self.branches(), branches_max), self.get_branch_hitrate(), self.get_hitrate(), - percentage(self.fits, self.count), - self.count, self.count_formatted(), - percentage(self.count, count_max)), end = '') + percentage(self.fits(), self.count()), + self.count(), self.count_formatted(), + percentage(self.count(), count_max)), end = '') if predicted_as != None: print('%12i%% %5.1f%%' % (predicted_as, self.get_hitrate() - predicted_as), end = '') + else: + print(' ' * 20, end = '') + + # print details about the most important edges + if args.coverage_threshold == None: + edges = [x for x in self.edges[:100] if x.count * hot_threshold > self.count()] + if args.verbose: + for c in edges: + r = 100.0 * c.count / self.count() + print(' %.0f%%:%d' % (r, c.count), end = '') + elif len(edges) > 0: + print(' %0.0f%%:%d' % (100.0 * sum([x.count for x in edges]) / self.count(), len(edges)), end = '') + print() class Profile: @@ -185,33 +226,29 @@ class Profile: self.heuristics[name] = Summary(name) s = self.heuristics[name] - s.branches += 1 - s.count += count if prediction < 50: hits = count - hits remaining = count - hits - if hits >= remaining: - s.successfull_branches += 1 + fits = max(hits, remaining) - s.hits += hits - s.fits += max(hits, remaining) + s.edges.append(Heuristics(count, hits, fits)) def add_loop_niter(self, niter): if niter > 0: self.niter_vector.append(niter) def branches_max(self): - return max([v.branches for k, v in self.heuristics.items()]) + return max([v.branches() for k, v in self.heuristics.items()]) def count_max(self): - return max([v.count for k, v in self.heuristics.items()]) + return max([v.count() for k, v in self.heuristics.items()]) def print_group(self, sorting, group_name, heuristics, predict_def): count_max = self.count_max() branches_max = self.branches_max() - sorter = lambda x: x.branches + sorter = lambda x: x.branches() if sorting == 'branch-hitrate': sorter = lambda x: x.get_branch_hitrate() elif sorting == 'hitrate': @@ -221,10 +258,10 @@ class Profile: elif sorting == 'name': sorter = lambda x: x.name.lower() - print('%-40s %8s %6s %12s %18s %14s %8s %6s %12s %6s' % + print('%-40s %8s %6s %12s %18s %14s %8s %6s %12s %6s %s' % ('HEURISTICS', 'BRANCHES', '(REL)', 'BR. HITRATE', 'HITRATE', 'COVERAGE', 'COVERAGE', '(REL)', - 'predict.def', '(REL)')) + 'predict.def', '(REL)', 'HOT branches (>%d%%)' % hot_threshold)) for h in sorted(heuristics, key = sorter): h.print(branches_max, count_max, predict_def) @@ -266,19 +303,23 @@ parser.add_argument('-s', '--sorting', dest = 'sorting', parser.add_argument('-d', '--def-file', help = 'path to predict.def') parser.add_argument('-w', '--write-def-file', action = 'store_true', help = 'Modify predict.def file in order to set new numbers') +parser.add_argument('-c', '--coverage-threshold', type = int, + help = 'Ignore edges that have percentage coverage >= coverage-threshold') +parser.add_argument('-v', '--verbose', action = 'store_true', help = 'Print verbose informations') args = parser.parse_args() profile = Profile(args.dump_file) -r = re.compile(' (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)') loop_niter_str = ';; profile-based iteration count: ' + for l in open(args.dump_file): - m = r.match(l) - if m != None and m.group(3) == None: - name = m.group(1) - prediction = float(m.group(4)) - count = int(m.group(5)) - hits = int(m.group(6)) + if l.startswith(';;heuristics;'): + parts = l.strip().split(';') + assert len(parts) == 8 + name = parts[3] + prediction = float(parts[6]) + count = int(parts[4]) + hits = int(parts[5]) profile.add(name, prediction, count, hits) elif l.startswith(loop_niter_str): |