Commit d6683f89 by Martin Liska Committed by Martin Liska

gcov: emit hotness colors to easily find hot code.

2018-09-17  Martin Liska  <mliska@suse.cz>

	* doc/gcov.texi: Document new option --use-hotness-colors.
	* gcov.c (struct source_info): Declare new field.
	(source_info::source_info): Set default for maximum_count.
	(print_usage): Add new -q option.
	(process_args): Process it.
	(accumulate_line_info): Save src->maximum_count.
	(output_line_beginning): Make color line number if
	flag_use_hotness_colors is set.
	(output_line_details): Pass default argument value.
	(output_lines): Pass src->maximum_count.

From-SVN: r264360
parent 7dc58b50
2018-09-17 Martin Liska <mliska@suse.cz> 2018-09-17 Martin Liska <mliska@suse.cz>
* doc/gcov.texi: Document new option --use-hotness-colors.
* gcov.c (struct source_info): Declare new field.
(source_info::source_info): Set default for maximum_count.
(print_usage): Add new -q option.
(process_args): Process it.
(accumulate_line_info): Save src->maximum_count.
(output_line_beginning): Make color line number if
flag_use_hotness_colors is set.
(output_line_details): Pass default argument value.
(output_lines): Pass src->maximum_count.
2018-09-17 Martin Liska <mliska@suse.cz>
* common/config/i386/i386-common.c (ix86_get_valid_option_values): * common/config/i386/i386-common.c (ix86_get_valid_option_values):
Use processor_names table. Use processor_names table.
* config/i386/i386.c (ix86_default_align): Use * config/i386/i386.c (ix86_default_align): Use
......
...@@ -132,6 +132,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] ...@@ -132,6 +132,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
[@option{-n}|@option{--no-output}] [@option{-n}|@option{--no-output}]
[@option{-o}|@option{--object-directory} @var{directory|file}] [@option{-o}|@option{--object-directory} @var{directory|file}]
[@option{-p}|@option{--preserve-paths}] [@option{-p}|@option{--preserve-paths}]
[@option{-q}|@option{--use-hotness-colors}]
[@option{-r}|@option{--relative-only}] [@option{-r}|@option{--relative-only}]
[@option{-s}|@option{--source-prefix} @var{directory}] [@option{-s}|@option{--source-prefix} @var{directory}]
[@option{-t}|@option{--stdout}] [@option{-t}|@option{--stdout}]
...@@ -264,7 +265,6 @@ Use colors for lines of code that have zero coverage. We use red color for ...@@ -264,7 +265,6 @@ Use colors for lines of code that have zero coverage. We use red color for
non-exceptional lines and cyan for exceptional. Same colors are used for non-exceptional lines and cyan for exceptional. Same colors are used for
basic blocks with @option{-a} option. basic blocks with @option{-a} option.
@item -l @item -l
@itemx --long-file-names @itemx --long-file-names
Create long file names for included source files. For example, if the Create long file names for included source files. For example, if the
...@@ -305,6 +305,12 @@ removed and unremoveable @file{..} ...@@ -305,6 +305,12 @@ removed and unremoveable @file{..}
components renamed to @samp{^}. This is useful if sourcefiles are in several components renamed to @samp{^}. This is useful if sourcefiles are in several
different directories. different directories.
@item -q
@itemx --use-hotness-colors
Emit perf-like colored output for hot lines. Legend of the color scale
is printed at the very beginning of the output file.
@item -r @item -r
@itemx --relative-only @itemx --relative-only
Only output information about source files with a relative pathname Only output information about source files with a relative pathname
......
...@@ -339,13 +339,16 @@ struct source_info ...@@ -339,13 +339,16 @@ struct source_info
coverage_info coverage; coverage_info coverage;
/* Maximum line count in the source file. */
unsigned int maximum_count;
/* Functions in this source file. These are in ascending line /* Functions in this source file. These are in ascending line
number order. */ number order. */
vector <function_info *> functions; vector <function_info *> functions;
}; };
source_info::source_info (): index (0), name (NULL), file_time (), source_info::source_info (): index (0), name (NULL), file_time (),
lines (), coverage (), functions () lines (), coverage (), maximum_count (0), functions ()
{ {
} }
...@@ -502,6 +505,10 @@ static int flag_verbose = 0; ...@@ -502,6 +505,10 @@ static int flag_verbose = 0;
static int flag_use_colors = 0; static int flag_use_colors = 0;
/* Use perf-like colors to indicate hot lines. */
static int flag_use_hotness_colors = 0;
/* Output count information for every basic block, not merely those /* Output count information for every basic block, not merely those
that contain line number information. */ that contain line number information. */
...@@ -839,6 +846,7 @@ print_usage (int error_p) ...@@ -839,6 +846,7 @@ print_usage (int error_p)
fnotice (file, " -n, --no-output Do not create an output file\n"); fnotice (file, " -n, --no-output Do not create an output file\n");
fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n"); fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
fnotice (file, " -p, --preserve-paths Preserve all pathname components\n"); fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
fnotice (file, " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n");
fnotice (file, " -r, --relative-only Only show data for relative sources\n"); fnotice (file, " -r, --relative-only Only show data for relative sources\n");
fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n"); fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
fnotice (file, " -t, --stdout Output to stdout instead of a file\n"); fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
...@@ -890,6 +898,7 @@ static const struct option options[] = ...@@ -890,6 +898,7 @@ static const struct option options[] =
{ "display-progress", no_argument, NULL, 'd' }, { "display-progress", no_argument, NULL, 'd' },
{ "hash-filenames", no_argument, NULL, 'x' }, { "hash-filenames", no_argument, NULL, 'x' },
{ "use-colors", no_argument, NULL, 'k' }, { "use-colors", no_argument, NULL, 'k' },
{ "use-hotness-colors", no_argument, NULL, 'q' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
...@@ -900,7 +909,7 @@ process_args (int argc, char **argv) ...@@ -900,7 +909,7 @@ process_args (int argc, char **argv)
{ {
int opt; int opt;
const char *opts = "abcdfhijklmno:prs:tuvwx"; const char *opts = "abcdfhijklmno:pqrs:tuvwx";
while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1) while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
{ {
switch (opt) switch (opt)
...@@ -929,6 +938,9 @@ process_args (int argc, char **argv) ...@@ -929,6 +938,9 @@ process_args (int argc, char **argv)
case 'k': case 'k':
flag_use_colors = 1; flag_use_colors = 1;
break; break;
case 'q':
flag_use_hotness_colors = 1;
break;
case 'm': case 'm':
flag_demangled_names = 1; flag_demangled_names = 1;
break; break;
...@@ -2580,6 +2592,9 @@ static void accumulate_line_info (line_info *line, source_info *src, ...@@ -2580,6 +2592,9 @@ static void accumulate_line_info (line_info *line, source_info *src,
/* Now, add the count of loops entirely on this line. */ /* Now, add the count of loops entirely on this line. */
count += get_cycles_count (*line); count += get_cycles_count (*line);
line->count = count; line->count = count;
if (line->count > src->maximum_count)
src->maximum_count = line->count;
} }
if (line->exists && add_coverage) if (line->exists && add_coverage)
...@@ -2756,7 +2771,8 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional, ...@@ -2756,7 +2771,8 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional,
bool has_unexecuted_block, bool has_unexecuted_block,
gcov_type count, unsigned line_num, gcov_type count, unsigned line_num,
const char *exceptional_string, const char *exceptional_string,
const char *unexceptional_string) const char *unexceptional_string,
unsigned int maximum_count)
{ {
string s; string s;
if (exists) if (exists)
...@@ -2806,7 +2822,23 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional, ...@@ -2806,7 +2822,23 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional,
pad_count_string (s); pad_count_string (s);
} }
fprintf (f, "%s:%5u", s.c_str (), line_num); /* Format line number in output. */
char buffer[16];
sprintf (buffer, "%5u", line_num);
string linestr (buffer);
if (flag_use_hotness_colors && maximum_count)
{
if (count * 2 > maximum_count) /* > 50%. */
linestr.insert (0, SGR_SEQ (COLOR_BG_RED));
else if (count * 5 > maximum_count) /* > 20%. */
linestr.insert (0, SGR_SEQ (COLOR_BG_YELLOW));
else if (count * 10 > maximum_count) /* > 10%. */
linestr.insert (0, SGR_SEQ (COLOR_BG_GREEN));
linestr += SGR_RESET;
}
fprintf (f, "%s:%s", s.c_str (), linestr.c_str ());
} }
static void static void
...@@ -2839,7 +2871,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num) ...@@ -2839,7 +2871,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num)
output_line_beginning (f, line->exists, output_line_beginning (f, line->exists,
(*it)->exceptional, false, (*it)->exceptional, false,
(*it)->count, line_num, (*it)->count, line_num,
"%%%%%", "$$$$$"); "%%%%%", "$$$$$", 0);
fprintf (f, "-block %2d", ix++); fprintf (f, "-block %2d", ix++);
if (flag_verbose) if (flag_verbose)
fprintf (f, " (BB %u)", (*it)->id); fprintf (f, " (BB %u)", (*it)->id);
...@@ -2902,6 +2934,15 @@ output_lines (FILE *gcov_file, const source_info *src) ...@@ -2902,6 +2934,15 @@ output_lines (FILE *gcov_file, const source_info *src)
FILE *source_file; FILE *source_file;
const char *retval; const char *retval;
/* Print legend of color hotness syntax. */
if (flag_use_hotness_colors)
fprintf (gcov_file, "%s", DEFAULT_LINE_START "Hotness legend: " \
SGR_SEQ (COLOR_BG_RED) "> 50%" SGR_RESET " " \
SGR_SEQ (COLOR_BG_YELLOW) "> 20%" SGR_RESET " " \
SGR_SEQ (COLOR_BG_GREEN) "> 10%" SGR_RESET "\n");
fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name); fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
if (!multiple_files) if (!multiple_files)
{ {
...@@ -2964,7 +3005,7 @@ output_lines (FILE *gcov_file, const source_info *src) ...@@ -2964,7 +3005,7 @@ output_lines (FILE *gcov_file, const source_info *src)
line so that tabs won't be messed up. */ line so that tabs won't be messed up. */
output_line_beginning (gcov_file, line->exists, line->unexceptional, output_line_beginning (gcov_file, line->exists, line->unexceptional,
line->has_unexecuted_block, line->count, line->has_unexecuted_block, line->count,
line_num, "=====", "#####"); line_num, "=====", "#####", src->maximum_count);
print_source_line (gcov_file, source_lines, line_num); print_source_line (gcov_file, source_lines, line_num);
output_line_details (gcov_file, line, line_num); output_line_details (gcov_file, line, line_num);
...@@ -3009,7 +3050,8 @@ output_lines (FILE *gcov_file, const source_info *src) ...@@ -3009,7 +3050,8 @@ output_lines (FILE *gcov_file, const source_info *src)
line->unexceptional, line->unexceptional,
line->has_unexecuted_block, line->has_unexecuted_block,
line->count, line->count,
l, "=====", "#####"); l, "=====", "#####",
src->maximum_count);
print_source_line (gcov_file, source_lines, l); print_source_line (gcov_file, source_lines, l);
output_line_details (gcov_file, line, l); output_line_details (gcov_file, line, l);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment