From: Adam Nemet Date: Thu, 2 Mar 2017 17:00:59 +0000 (+0000) Subject: New tool: opt-diff.py X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a466e7794403b489e37e4235e982acb8d9d5ab9;p=llvm New tool: opt-diff.py This tool allows generating the different between two optimization record files. The result is a YAML file too that can be visualized with opt-viewer. This is very useful to see what optimization were added and removed by a change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296767 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/utils/opt-viewer/opt-diff.py b/utils/opt-viewer/opt-diff.py new file mode 100755 index 00000000000..c51e05e2152 --- /dev/null +++ b/utils/opt-viewer/opt-diff.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python2.7 + +from __future__ import print_function + +desc = '''Generate the difference of two YAML files into a new YAML file (works on +pair of directories too). A new attribute 'Added' is set to True or False +depending whether the entry is added or removed from the first input to the +next. + +The tools requires PyYAML.''' + +import yaml +# Try to use the C parser. +try: + from yaml import CLoader as Loader +except ImportError: + from yaml import Loader + +import optrecord +import argparse +from collections import defaultdict +from multiprocessing import cpu_count, Pool +import os, os.path + +def find_files(dir_or_file): + if os.path.isfile(dir_or_file): + return [dir_or_file] + + all = [] + for dir, subdirs, files in os.walk(dir_or_file): + for file in files: + all.append( os.path.join(dir, file)) + return all + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=desc) + parser.add_argument('yaml_dir_or_file_1') + parser.add_argument('yaml_dir_or_file_2') + parser.add_argument( + '--jobs', + '-j', + default=cpu_count(), + type=int, + help='Max job count (defaults to current CPU count)') + parser.add_argument('--output', '-o', default='diff.opt.yaml') + args = parser.parse_args() + + if args.jobs == 1: + pmap = map + else: + pool = Pool(processes=args.jobs) + pmap = pool.map + + files1 = find_files(args.yaml_dir_or_file_1) + files2 = find_files(args.yaml_dir_or_file_2) + + all_remarks1, _, _ = optrecord.gather_results(pmap, files1) + all_remarks2, _, _ = optrecord.gather_results(pmap, files2) + + added = set(all_remarks2.values()) - set(all_remarks1.values()) + removed = set(all_remarks1.values()) - set(all_remarks2.values()) + + for r in added: + r.Added = True + for r in removed: + r.Added = False + stream = file(args.output, 'w') + yaml.dump_all(added | removed, stream) diff --git a/utils/opt-viewer/opt-viewer.py b/utils/opt-viewer/opt-viewer.py index 0b7eaa8f493..a14aee5f298 100755 --- a/utils/opt-viewer/opt-viewer.py +++ b/utils/opt-viewer/opt-viewer.py @@ -90,7 +90,7 @@ class SourceFileRenderer: {r.RelativeHotness} -{r.Pass} +{r.PassWithDiffPrefix}
{indent}
{r.message}  {inlining_context} '''.format(**locals()), file=self.stream) @@ -133,7 +133,7 @@ class IndexRenderer: {r.DebugLocString} {r.RelativeHotness} {escaped_name} -{r.Pass} +{r.PassWithDiffPrefix} '''.format(**locals()), file=self.stream) def render(self, all_remarks): diff --git a/utils/opt-viewer/optrecord.py b/utils/opt-viewer/optrecord.py index 8b33c0abfe1..3dc77e9db01 100644 --- a/utils/opt-viewer/optrecord.py +++ b/utils/opt-viewer/optrecord.py @@ -88,6 +88,18 @@ class Remark(yaml.YAMLObject): else: return value + def getDiffPrefix(self): + if hasattr(self, 'Added'): + if self.Added: + return '+' + else: + return '-' + return '' + + @property + def PassWithDiffPrefix(self): + return self.getDiffPrefix() + self.Pass + @property def message(self): # Args is a list of mappings (dictionaries) @@ -103,7 +115,7 @@ class Remark(yaml.YAMLObject): @property def key(self): - k = (self.__class__, self.Pass, self.Name, self.File, self.Line, self.Column, self.Function) + k = (self.__class__, self.PassWithDiffPrefix, self.Name, self.File, self.Line, self.Column, self.Function) for arg in self.Args: for (key, value) in arg.iteritems(): if type(value) is dict: @@ -169,6 +181,11 @@ def get_remarks(input_file): file_remarks[remark.File][remark.Line].append(remark) + # If we're reading a back a diff yaml file, max_hotness is already + # captured which may actually be less than the max hotness found + # in the file. + if hasattr(remark, 'max_hotness'): + max_hotness = remark.max_hotness max_hotness = max(max_hotness, remark.Hotness) return max_hotness, all_remarks, file_remarks