libgcov-util.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. /* Utility functions for reading gcda files into in-memory
  2. gcov_info structures and offline profile processing. */
  3. /* Copyright (C) 2014-2022 Free Software Foundation, Inc.
  4. Contributed by Rong Xu <xur@google.com>.
  5. This file is part of GCC.
  6. GCC is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 3, or (at your option) any later
  9. version.
  10. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. for more details.
  14. Under Section 7 of GPL version 3, you are granted additional
  15. permissions described in the GCC Runtime Library Exception, version
  16. 3.1, as published by the Free Software Foundation.
  17. You should have received a copy of the GNU General Public License and
  18. a copy of the GCC Runtime Library Exception along with this program;
  19. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  20. <http://www.gnu.org/licenses/>. */
  21. #define IN_GCOV_TOOL 1
  22. #include "libgcov.h"
  23. #include "intl.h"
  24. #include "diagnostic.h"
  25. #include "version.h"
  26. #include "demangle.h"
  27. #include "gcov-io.h"
  28. /* Borrowed from basic-block.h. */
  29. #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
  30. extern gcov_position_t gcov_position();
  31. extern int gcov_is_error();
  32. /* Verbose mode for debug. */
  33. static int verbose;
  34. /* Set verbose flag. */
  35. void gcov_set_verbose (void)
  36. {
  37. verbose = 1;
  38. }
  39. /* The following part is to read Gcda and reconstruct GCOV_INFO. */
  40. #include "obstack.h"
  41. #include <unistd.h>
  42. #ifdef HAVE_FTW_H
  43. #include <ftw.h>
  44. #endif
  45. static void tag_function (unsigned, int);
  46. static void tag_blocks (unsigned, int);
  47. static void tag_arcs (unsigned, int);
  48. static void tag_lines (unsigned, int);
  49. static void tag_counters (unsigned, int);
  50. static void tag_summary (unsigned, int);
  51. /* The gcov_info for the first module. */
  52. static struct gcov_info *curr_gcov_info;
  53. /* The gcov_info being processed. */
  54. static struct gcov_info *gcov_info_head;
  55. /* This variable contains all the functions in current module. */
  56. static struct obstack fn_info;
  57. /* The function being processed. */
  58. static struct gcov_fn_info *curr_fn_info;
  59. /* The number of functions seen so far. */
  60. static unsigned num_fn_info;
  61. /* This variable contains all the counters for current module. */
  62. static int k_ctrs_mask[GCOV_COUNTERS];
  63. /* The kind of counters that have been seen. */
  64. static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
  65. /* Number of kind of counters that have been seen. */
  66. static int k_ctrs_types;
  67. /* Merge functions for counters. */
  68. #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
  69. static gcov_merge_fn ctr_merge_functions[GCOV_COUNTERS] = {
  70. #include "gcov-counter.def"
  71. };
  72. #undef DEF_GCOV_COUNTER
  73. /* Set the ctrs field in gcov_fn_info object FN_INFO. */
  74. static void
  75. set_fn_ctrs (struct gcov_fn_info *fn_info)
  76. {
  77. int j = 0, i;
  78. for (i = 0; i < GCOV_COUNTERS; i++)
  79. {
  80. if (k_ctrs_mask[i] == 0)
  81. continue;
  82. fn_info->ctrs[j].num = k_ctrs[i].num;
  83. fn_info->ctrs[j].values = k_ctrs[i].values;
  84. j++;
  85. }
  86. if (k_ctrs_types == 0)
  87. k_ctrs_types = j;
  88. else
  89. gcc_assert (j == k_ctrs_types);
  90. }
  91. /* For each tag in gcda file, we have an entry here.
  92. TAG is the tag value; NAME is the tag name; and
  93. PROC is the handler function. */
  94. typedef struct tag_format
  95. {
  96. unsigned tag;
  97. char const *name;
  98. void (*proc) (unsigned, int);
  99. } tag_format_t;
  100. /* Handler table for various Tags. */
  101. static const tag_format_t tag_table[] =
  102. {
  103. {0, "NOP", NULL},
  104. {0, "UNKNOWN", NULL},
  105. {0, "COUNTERS", tag_counters},
  106. {GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
  107. {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
  108. {GCOV_TAG_ARCS, "ARCS", tag_arcs},
  109. {GCOV_TAG_LINES, "LINES", tag_lines},
  110. {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
  111. {0, NULL, NULL}
  112. };
  113. /* Handler for reading function tag. */
  114. static void
  115. tag_function (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
  116. {
  117. int i;
  118. /* write out previous fn_info. */
  119. if (num_fn_info)
  120. {
  121. set_fn_ctrs (curr_fn_info);
  122. obstack_ptr_grow (&fn_info, curr_fn_info);
  123. }
  124. /* Here we over allocate a bit, using GCOV_COUNTERS instead of the actual active
  125. counter types. */
  126. curr_fn_info = (struct gcov_fn_info *) xcalloc (sizeof (struct gcov_fn_info)
  127. + GCOV_COUNTERS * sizeof (struct gcov_ctr_info), 1);
  128. for (i = 0; i < GCOV_COUNTERS; i++)
  129. k_ctrs[i].num = 0;
  130. k_ctrs_types = 0;
  131. curr_fn_info->key = curr_gcov_info;
  132. curr_fn_info->ident = gcov_read_unsigned ();
  133. curr_fn_info->lineno_checksum = gcov_read_unsigned ();
  134. curr_fn_info->cfg_checksum = gcov_read_unsigned ();
  135. num_fn_info++;
  136. if (verbose)
  137. fnotice (stdout, "tag one function id=%d\n", curr_fn_info->ident);
  138. }
  139. /* Handler for reading block tag. */
  140. static void
  141. tag_blocks (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
  142. {
  143. /* TBD: gcov-tool currently does not handle gcno files. Assert here. */
  144. gcc_unreachable ();
  145. }
  146. /* Handler for reading flow arc tag. */
  147. static void
  148. tag_arcs (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
  149. {
  150. /* TBD: gcov-tool currently does not handle gcno files. Assert here. */
  151. gcc_unreachable ();
  152. }
  153. /* Handler for reading line tag. */
  154. static void
  155. tag_lines (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
  156. {
  157. /* TBD: gcov-tool currently does not handle gcno files. Assert here. */
  158. gcc_unreachable ();
  159. }
  160. /* Handler for reading counters array tag with value as TAG and length of LENGTH. */
  161. static void
  162. tag_counters (unsigned tag, int length)
  163. {
  164. unsigned n_counts = GCOV_TAG_COUNTER_NUM (abs (length));
  165. gcov_type *values;
  166. unsigned ix;
  167. unsigned tag_ix;
  168. tag_ix = GCOV_COUNTER_FOR_TAG (tag);
  169. gcc_assert (tag_ix < GCOV_COUNTERS);
  170. k_ctrs_mask [tag_ix] = 1;
  171. gcc_assert (k_ctrs[tag_ix].num == 0);
  172. k_ctrs[tag_ix].num = n_counts;
  173. k_ctrs[tag_ix].values = values = (gcov_type *) xcalloc (sizeof (gcov_type),
  174. n_counts);
  175. gcc_assert (values);
  176. if (length > 0)
  177. for (ix = 0; ix != n_counts; ix++)
  178. values[ix] = gcov_read_counter ();
  179. }
  180. /* Handler for reading summary tag. */
  181. static void
  182. tag_summary (unsigned tag ATTRIBUTE_UNUSED, int ATTRIBUTE_UNUSED)
  183. {
  184. gcov_read_summary (&curr_gcov_info->summary);
  185. }
  186. /* This function is called at the end of reading a gcda file.
  187. It flushes the contents in curr_fn_info to gcov_info object OBJ_INFO. */
  188. static void
  189. read_gcda_finalize (struct gcov_info *obj_info)
  190. {
  191. int i;
  192. set_fn_ctrs (curr_fn_info);
  193. obstack_ptr_grow (&fn_info, curr_fn_info);
  194. /* We set the following fields: merge, n_functions, functions
  195. and summary. */
  196. obj_info->n_functions = num_fn_info;
  197. obj_info->functions = (struct gcov_fn_info**) obstack_finish (&fn_info);
  198. /* wrap all the counter array. */
  199. for (i=0; i< GCOV_COUNTERS; i++)
  200. {
  201. if (k_ctrs_mask[i])
  202. obj_info->merge[i] = ctr_merge_functions[i];
  203. }
  204. }
  205. /* Read the content of a gcda file FILENAME, and return a gcov_info data structure.
  206. Program level summary CURRENT_SUMMARY will also be updated. */
  207. static struct gcov_info *
  208. read_gcda_file (const char *filename)
  209. {
  210. unsigned tags[4];
  211. unsigned depth = 0;
  212. unsigned version;
  213. struct gcov_info *obj_info;
  214. int i;
  215. for (i=0; i< GCOV_COUNTERS; i++)
  216. k_ctrs_mask[i] = 0;
  217. k_ctrs_types = 0;
  218. if (!gcov_open (filename))
  219. {
  220. fnotice (stderr, "%s:cannot open\n", filename);
  221. return NULL;
  222. }
  223. /* Read magic. */
  224. if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
  225. {
  226. fnotice (stderr, "%s:not a gcov data file\n", filename);
  227. gcov_close ();
  228. return NULL;
  229. }
  230. /* Read version. */
  231. version = gcov_read_unsigned ();
  232. if (version != GCOV_VERSION)
  233. {
  234. fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION);
  235. gcov_close ();
  236. return NULL;
  237. }
  238. /* Instantiate a gcov_info object. */
  239. curr_gcov_info = obj_info = (struct gcov_info *) xcalloc (sizeof (struct gcov_info) +
  240. sizeof (struct gcov_ctr_info) * GCOV_COUNTERS, 1);
  241. obj_info->version = version;
  242. obstack_init (&fn_info);
  243. num_fn_info = 0;
  244. curr_fn_info = 0;
  245. {
  246. size_t len = strlen (filename) + 1;
  247. char *str_dup = (char*) xmalloc (len);
  248. memcpy (str_dup, filename, len);
  249. obj_info->filename = str_dup;
  250. }
  251. /* Read stamp. */
  252. obj_info->stamp = gcov_read_unsigned ();
  253. /* Read checksum. */
  254. obj_info->checksum = gcov_read_unsigned ();
  255. while (1)
  256. {
  257. gcov_position_t base;
  258. unsigned tag, length;
  259. tag_format_t const *format;
  260. unsigned tag_depth;
  261. int error;
  262. unsigned mask;
  263. tag = gcov_read_unsigned ();
  264. if (!tag)
  265. break;
  266. int read_length = (int)gcov_read_unsigned ();
  267. length = read_length > 0 ? read_length : 0;
  268. base = gcov_position ();
  269. mask = GCOV_TAG_MASK (tag) >> 1;
  270. for (tag_depth = 4; mask; mask >>= 8)
  271. {
  272. if (((mask & 0xff) != 0xff))
  273. {
  274. warning (0, "%s:tag %qx is invalid", filename, tag);
  275. break;
  276. }
  277. tag_depth--;
  278. }
  279. for (format = tag_table; format->name; format++)
  280. if (format->tag == tag)
  281. goto found;
  282. format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
  283. found:;
  284. if (tag)
  285. {
  286. if (depth && depth < tag_depth)
  287. {
  288. if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
  289. warning (0, "%s:tag %qx is incorrectly nested",
  290. filename, tag);
  291. }
  292. depth = tag_depth;
  293. tags[depth - 1] = tag;
  294. }
  295. if (format->proc)
  296. {
  297. unsigned long actual_length;
  298. (*format->proc) (tag, read_length);
  299. actual_length = gcov_position () - base;
  300. if (actual_length > length)
  301. warning (0, "%s:record size mismatch %lu bytes overread",
  302. filename, actual_length - length);
  303. else if (length > actual_length)
  304. warning (0, "%s:record size mismatch %lu bytes unread",
  305. filename, length - actual_length);
  306. }
  307. gcov_sync (base, length);
  308. if ((error = gcov_is_error ()))
  309. {
  310. warning (0, error < 0 ? "%s:counter overflow at %lu" :
  311. "%s:read error at %lu", filename,
  312. (long unsigned) gcov_position ());
  313. break;
  314. }
  315. }
  316. read_gcda_finalize (obj_info);
  317. gcov_close ();
  318. return obj_info;
  319. }
  320. #ifdef HAVE_FTW_H
  321. /* This will be called by ftw(). It opens and read a gcda file FILENAME.
  322. Return a non-zero value to stop the tree walk. */
  323. static int
  324. ftw_read_file (const char *filename,
  325. const struct stat *status ATTRIBUTE_UNUSED,
  326. int type)
  327. {
  328. int filename_len;
  329. int suffix_len;
  330. struct gcov_info *obj_info;
  331. /* Only read regular files. */
  332. if (type != FTW_F)
  333. return 0;
  334. filename_len = strlen (filename);
  335. suffix_len = strlen (GCOV_DATA_SUFFIX);
  336. if (filename_len <= suffix_len)
  337. return 0;
  338. if (strcmp(filename + filename_len - suffix_len, GCOV_DATA_SUFFIX))
  339. return 0;
  340. if (verbose)
  341. fnotice (stderr, "reading file: %s\n", filename);
  342. obj_info = read_gcda_file (filename);
  343. if (!obj_info)
  344. return 0;
  345. obj_info->next = gcov_info_head;
  346. gcov_info_head = obj_info;
  347. return 0;
  348. }
  349. #endif
  350. /* Initializer for reading a profile dir. */
  351. static inline void
  352. read_profile_dir_init (void)
  353. {
  354. gcov_info_head = 0;
  355. }
  356. /* Driver for read a profile directory and convert into gcov_info list in memory.
  357. Return NULL on error,
  358. Return the head of gcov_info list on success. */
  359. struct gcov_info *
  360. gcov_read_profile_dir (const char* dir_name, int recompute_summary ATTRIBUTE_UNUSED)
  361. {
  362. char *pwd;
  363. int ret;
  364. read_profile_dir_init ();
  365. if (access (dir_name, R_OK) != 0)
  366. {
  367. fnotice (stderr, "cannot access directory %s\n", dir_name);
  368. return NULL;
  369. }
  370. pwd = getcwd (NULL, 0);
  371. gcc_assert (pwd);
  372. ret = chdir (dir_name);
  373. if (ret !=0)
  374. {
  375. fnotice (stderr, "%s is not a directory\n", dir_name);
  376. return NULL;
  377. }
  378. #ifdef HAVE_FTW_H
  379. ftw (".", ftw_read_file, 50);
  380. #endif
  381. chdir (pwd);
  382. free (pwd);
  383. return gcov_info_head;;
  384. }
  385. /* This part of the code is to merge profile counters. These
  386. variables are set in merge_wrapper and to be used by
  387. global function gcov_read_counter_mem() and gcov_get_merge_weight. */
  388. /* We save the counter value address to this variable. */
  389. static gcov_type *gcov_value_buf;
  390. /* The number of counter values to be read by current merging. */
  391. static gcov_unsigned_t gcov_value_buf_size;
  392. /* The index of counter values being read. */
  393. static gcov_unsigned_t gcov_value_buf_pos;
  394. /* The weight of current merging. */
  395. static unsigned gcov_merge_weight;
  396. /* Read a counter value from gcov_value_buf array. */
  397. gcov_type
  398. gcov_read_counter_mem (void)
  399. {
  400. gcov_type ret;
  401. gcc_assert (gcov_value_buf_pos < gcov_value_buf_size);
  402. ret = *(gcov_value_buf + gcov_value_buf_pos);
  403. ++gcov_value_buf_pos;
  404. return ret;
  405. }
  406. /* Return the recorded merge weight. */
  407. unsigned
  408. gcov_get_merge_weight (void)
  409. {
  410. return gcov_merge_weight;
  411. }
  412. /* A wrapper function for merge functions. It sets up the
  413. value buffer and weights and then calls the merge function. */
  414. static void
  415. merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n1,
  416. gcov_type *v2, gcov_unsigned_t n2, unsigned w)
  417. {
  418. gcov_value_buf = v2;
  419. gcov_value_buf_pos = 0;
  420. gcov_value_buf_size = n2;
  421. gcov_merge_weight = w;
  422. (*f) (v1, n1);
  423. }
  424. /* Convert on disk representation of a TOPN counter to in memory representation
  425. that is expected from __gcov_merge_topn function. */
  426. static void
  427. topn_to_memory_representation (struct gcov_ctr_info *info)
  428. {
  429. auto_vec<gcov_type> output;
  430. gcov_type *values = info->values;
  431. int count = info->num;
  432. while (count > 0)
  433. {
  434. output.safe_push (values[0]);
  435. gcov_type n = values[1];
  436. output.safe_push (n);
  437. if (n > 0)
  438. {
  439. struct gcov_kvp *tuples
  440. = (struct gcov_kvp *)xcalloc (sizeof (struct gcov_kvp), n);
  441. for (unsigned i = 0; i < n - 1; i++)
  442. tuples[i].next = &tuples[i + 1];
  443. for (unsigned i = 0; i < n; i++)
  444. {
  445. tuples[i].value = values[2 + 2 * i];
  446. tuples[i].count = values[2 + 2 * i + 1];
  447. }
  448. output.safe_push ((intptr_t)&tuples[0]);
  449. }
  450. else
  451. output.safe_push (0);
  452. unsigned len = 2 * n + 2;
  453. values += len;
  454. count -= len;
  455. }
  456. gcc_assert (count == 0);
  457. /* Allocate new buffer and copy it there. */
  458. info->num = output.length ();
  459. info->values = (gcov_type *)xmalloc (sizeof (gcov_type) * info->num);
  460. for (unsigned i = 0; i < info->num; i++)
  461. info->values[i] = output[i];
  462. }
  463. /* Offline tool to manipulate profile data.
  464. This tool targets on matched profiles. But it has some tolerance on
  465. unmatched profiles.
  466. When merging p1 to p2 (p2 is the dst),
  467. * m.gcda in p1 but not in p2: append m.gcda to p2 with specified weight;
  468. emit warning
  469. * m.gcda in p2 but not in p1: keep m.gcda in p2 and multiply by
  470. specified weight; emit warning.
  471. * m.gcda in both p1 and p2:
  472. ** p1->m.gcda->f checksum matches p2->m.gcda->f: simple merge.
  473. ** p1->m.gcda->f checksum does not matches p2->m.gcda->f: keep
  474. p2->m.gcda->f and
  475. drop p1->m.gcda->f. A warning is emitted. */
  476. /* Add INFO2's counter to INFO1, multiplying by weight W. */
  477. static int
  478. gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
  479. {
  480. unsigned f_ix;
  481. unsigned n_functions = info1->n_functions;
  482. int has_mismatch = 0;
  483. gcc_assert (info2->n_functions == n_functions);
  484. /* Merge summary. */
  485. info1->summary.runs += info2->summary.runs;
  486. info1->summary.sum_max += info2->summary.sum_max;
  487. for (f_ix = 0; f_ix < n_functions; f_ix++)
  488. {
  489. unsigned t_ix;
  490. struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
  491. struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
  492. struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
  493. if (!gfi_ptr1 || gfi_ptr1->key != info1)
  494. continue;
  495. if (!gfi_ptr2 || gfi_ptr2->key != info2)
  496. continue;
  497. if (gfi_ptr1->cfg_checksum != gfi_ptr2->cfg_checksum)
  498. {
  499. fnotice (stderr, "in %s, cfg_checksum mismatch, skipping\n",
  500. info1->filename);
  501. has_mismatch = 1;
  502. continue;
  503. }
  504. ci_ptr1 = gfi_ptr1->ctrs;
  505. ci_ptr2 = gfi_ptr2->ctrs;
  506. for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
  507. {
  508. gcov_merge_fn merge1 = info1->merge[t_ix];
  509. gcov_merge_fn merge2 = info2->merge[t_ix];
  510. gcc_assert (merge1 == merge2);
  511. if (!merge1)
  512. continue;
  513. if (merge1 == __gcov_merge_topn)
  514. topn_to_memory_representation (ci_ptr1);
  515. else
  516. gcc_assert (ci_ptr1->num == ci_ptr2->num);
  517. merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num,
  518. ci_ptr2->values, ci_ptr2->num, w);
  519. ci_ptr1++;
  520. ci_ptr2++;
  521. }
  522. }
  523. return has_mismatch;
  524. }
  525. /* Find and return the match gcov_info object for INFO from ARRAY.
  526. SIZE is the length of ARRAY.
  527. Return NULL if there is no match. */
  528. static struct gcov_info *
  529. find_match_gcov_info (struct gcov_info **array, int size,
  530. struct gcov_info *info)
  531. {
  532. struct gcov_info *gi_ptr;
  533. struct gcov_info *ret = NULL;
  534. int i;
  535. for (i = 0; i < size; i++)
  536. {
  537. gi_ptr = array[i];
  538. if (gi_ptr == 0)
  539. continue;
  540. if (!strcmp (gi_ptr->filename, info->filename))
  541. {
  542. ret = gi_ptr;
  543. array[i] = 0;
  544. break;
  545. }
  546. }
  547. if (ret && ret->n_functions != info->n_functions)
  548. {
  549. fnotice (stderr, "mismatched profiles in %s (%d functions"
  550. " vs %d functions)\n",
  551. ret->filename,
  552. ret->n_functions,
  553. info->n_functions);
  554. ret = NULL;
  555. }
  556. return ret;
  557. }
  558. /* Merge the list of gcov_info objects from SRC_PROFILE to TGT_PROFILE.
  559. Return 0 on success: without mismatch.
  560. Reutrn 1 on error. */
  561. int
  562. gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile,
  563. int w1, int w2)
  564. {
  565. struct gcov_info *gi_ptr;
  566. struct gcov_info **tgt_infos;
  567. struct gcov_info *tgt_tail;
  568. struct gcov_info **in_src_not_tgt;
  569. unsigned tgt_cnt = 0, src_cnt = 0;
  570. unsigned unmatch_info_cnt = 0;
  571. unsigned int i;
  572. for (gi_ptr = tgt_profile; gi_ptr; gi_ptr = gi_ptr->next)
  573. tgt_cnt++;
  574. for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
  575. src_cnt++;
  576. tgt_infos = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
  577. * tgt_cnt);
  578. gcc_assert (tgt_infos);
  579. in_src_not_tgt = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
  580. * src_cnt);
  581. gcc_assert (in_src_not_tgt);
  582. for (gi_ptr = tgt_profile, i = 0; gi_ptr; gi_ptr = gi_ptr->next, i++)
  583. tgt_infos[i] = gi_ptr;
  584. tgt_tail = tgt_infos[tgt_cnt - 1];
  585. /* First pass on tgt_profile, we multiply w1 to all counters. */
  586. if (w1 > 1)
  587. {
  588. for (i = 0; i < tgt_cnt; i++)
  589. gcov_merge (tgt_infos[i], tgt_infos[i], w1-1);
  590. }
  591. /* Second pass, add src_profile to the tgt_profile. */
  592. for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
  593. {
  594. struct gcov_info *gi_ptr1;
  595. gi_ptr1 = find_match_gcov_info (tgt_infos, tgt_cnt, gi_ptr);
  596. if (gi_ptr1 == NULL)
  597. {
  598. in_src_not_tgt[unmatch_info_cnt++] = gi_ptr;
  599. continue;
  600. }
  601. gcov_merge (gi_ptr1, gi_ptr, w2);
  602. }
  603. /* For modules in src but not in tgt. We adjust the counter and append. */
  604. for (i = 0; i < unmatch_info_cnt; i++)
  605. {
  606. gi_ptr = in_src_not_tgt[i];
  607. gcov_merge (gi_ptr, gi_ptr, w2 - 1);
  608. gi_ptr->next = NULL;
  609. tgt_tail->next = gi_ptr;
  610. tgt_tail = gi_ptr;
  611. }
  612. free (in_src_not_tgt);
  613. free (tgt_infos);
  614. return 0;
  615. }
  616. typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
  617. /* Performing FN upon arc counters. */
  618. static void
  619. __gcov_add_counter_op (gcov_type *counters, unsigned n_counters,
  620. counter_op_fn fn, void *data1, void *data2)
  621. {
  622. for (; n_counters; counters++, n_counters--)
  623. {
  624. gcov_type val = *counters;
  625. *counters = fn(val, data1, data2);
  626. }
  627. }
  628. /* Performing FN upon ior counters. */
  629. static void
  630. __gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
  631. unsigned n_counters ATTRIBUTE_UNUSED,
  632. counter_op_fn fn ATTRIBUTE_UNUSED,
  633. void *data1 ATTRIBUTE_UNUSED,
  634. void *data2 ATTRIBUTE_UNUSED)
  635. {
  636. /* Do nothing. */
  637. }
  638. /* Performing FN upon time-profile counters. */
  639. static void
  640. __gcov_time_profile_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
  641. unsigned n_counters ATTRIBUTE_UNUSED,
  642. counter_op_fn fn ATTRIBUTE_UNUSED,
  643. void *data1 ATTRIBUTE_UNUSED,
  644. void *data2 ATTRIBUTE_UNUSED)
  645. {
  646. /* Do nothing. */
  647. }
  648. /* Performing FN upon TOP N counters. */
  649. static void
  650. __gcov_topn_counter_op (gcov_type *counters, unsigned n_counters,
  651. counter_op_fn fn, void *data1, void *data2)
  652. {
  653. unsigned i, n_measures;
  654. gcc_assert (!(n_counters % 3));
  655. n_measures = n_counters / 3;
  656. for (i = 0; i < n_measures; i++, counters += 3)
  657. {
  658. counters[1] = fn (counters[1], data1, data2);
  659. counters[2] = fn (counters[2], data1, data2);
  660. }
  661. }
  662. /* Scaling the counter value V by multiplying *(float*) DATA1. */
  663. static gcov_type
  664. fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED)
  665. {
  666. float f = *(float *) data1;
  667. return (gcov_type) (v * f);
  668. }
  669. /* Scaling the counter value V by multiplying DATA2/DATA1. */
  670. static gcov_type
  671. int_scale (gcov_type v, void *data1, void *data2)
  672. {
  673. int n = *(int *) data1;
  674. int d = *(int *) data2;
  675. return (gcov_type) ( RDIV (v,d) * n);
  676. }
  677. /* Type of function used to process counters. */
  678. typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t,
  679. counter_op_fn, void *, void *);
  680. /* Function array to process profile counters. */
  681. #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) \
  682. __gcov ## FN_TYPE ## _counter_op,
  683. static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = {
  684. #include "gcov-counter.def"
  685. };
  686. #undef DEF_GCOV_COUNTER
  687. /* Driver for scaling profile counters. */
  688. int
  689. gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d)
  690. {
  691. struct gcov_info *gi_ptr;
  692. unsigned f_ix;
  693. if (verbose)
  694. fnotice (stdout, "scale_factor is %f or %d/%d\n", scale_factor, n, d);
  695. /* Scaling the counters. */
  696. for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
  697. for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
  698. {
  699. unsigned t_ix;
  700. const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
  701. const struct gcov_ctr_info *ci_ptr;
  702. if (!gfi_ptr || gfi_ptr->key != gi_ptr)
  703. continue;
  704. ci_ptr = gfi_ptr->ctrs;
  705. for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
  706. {
  707. gcov_merge_fn merge = gi_ptr->merge[t_ix];
  708. if (!merge)
  709. continue;
  710. if (d == 0)
  711. (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
  712. fp_scale, &scale_factor, NULL);
  713. else
  714. (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
  715. int_scale, &n, &d);
  716. ci_ptr++;
  717. }
  718. }
  719. return 0;
  720. }
  721. /* Driver to normalize profile counters. */
  722. int
  723. gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
  724. {
  725. struct gcov_info *gi_ptr;
  726. gcov_type curr_max_val = 0;
  727. unsigned f_ix;
  728. unsigned int i;
  729. float scale_factor;
  730. /* Find the largest count value. */
  731. for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
  732. for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
  733. {
  734. unsigned t_ix;
  735. const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
  736. const struct gcov_ctr_info *ci_ptr;
  737. if (!gfi_ptr || gfi_ptr->key != gi_ptr)
  738. continue;
  739. ci_ptr = gfi_ptr->ctrs;
  740. for (t_ix = 0; t_ix < 1; t_ix++)
  741. {
  742. for (i = 0; i < ci_ptr->num; i++)
  743. if (ci_ptr->values[i] > curr_max_val)
  744. curr_max_val = ci_ptr->values[i];
  745. ci_ptr++;
  746. }
  747. }
  748. scale_factor = (float)max_val / curr_max_val;
  749. if (verbose)
  750. fnotice (stdout, "max_val is %" PRId64 "\n", curr_max_val);
  751. return gcov_profile_scale (profile, scale_factor, 0, 0);
  752. }
  753. /* The following variables are defined in gcc/gcov-tool.c. */
  754. extern int overlap_func_level;
  755. extern int overlap_obj_level;
  756. extern int overlap_hot_only;
  757. extern int overlap_use_fullname;
  758. extern double overlap_hot_threshold;
  759. /* Compute the overlap score of two values. The score is defined as:
  760. min (V1/SUM_1, V2/SUM_2) */
  761. static double
  762. calculate_2_entries (const unsigned long v1, const unsigned long v2,
  763. const double sum_1, const double sum_2)
  764. {
  765. double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
  766. double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
  767. if (val2 < val1)
  768. val1 = val2;
  769. return val1;
  770. }
  771. /* Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
  772. This function also updates cumulative score CUM_1_RESULT and
  773. CUM_2_RESULT. */
  774. static double
  775. compute_one_gcov (const struct gcov_info *gcov_info1,
  776. const struct gcov_info *gcov_info2,
  777. const double sum_1, const double sum_2,
  778. double *cum_1_result, double *cum_2_result)
  779. {
  780. unsigned f_ix;
  781. double ret = 0;
  782. double cum_1 = 0, cum_2 = 0;
  783. const struct gcov_info *gcov_info = 0;
  784. double *cum_p;
  785. double sum;
  786. gcc_assert (gcov_info1 || gcov_info2);
  787. if (!gcov_info1)
  788. {
  789. gcov_info = gcov_info2;
  790. cum_p = cum_2_result;
  791. sum = sum_2;
  792. *cum_1_result = 0;
  793. } else
  794. if (!gcov_info2)
  795. {
  796. gcov_info = gcov_info1;
  797. cum_p = cum_1_result;
  798. sum = sum_1;
  799. *cum_2_result = 0;
  800. }
  801. if (gcov_info)
  802. {
  803. for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
  804. {
  805. const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
  806. if (!gfi_ptr || gfi_ptr->key != gcov_info)
  807. continue;
  808. const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
  809. unsigned c_num;
  810. for (c_num = 0; c_num < ci_ptr->num; c_num++)
  811. cum_1 += ci_ptr->values[c_num] / sum;
  812. }
  813. *cum_p = cum_1;
  814. return 0.0;
  815. }
  816. for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
  817. {
  818. double func_cum_1 = 0.0;
  819. double func_cum_2 = 0.0;
  820. double func_val = 0.0;
  821. int nonzero = 0;
  822. int hot = 0;
  823. const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
  824. const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
  825. if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
  826. continue;
  827. if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
  828. continue;
  829. const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
  830. const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
  831. unsigned c_num;
  832. for (c_num = 0; c_num < ci_ptr1->num; c_num++)
  833. {
  834. if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
  835. {
  836. func_val += calculate_2_entries (ci_ptr1->values[c_num],
  837. ci_ptr2->values[c_num],
  838. sum_1, sum_2);
  839. func_cum_1 += ci_ptr1->values[c_num] / sum_1;
  840. func_cum_2 += ci_ptr2->values[c_num] / sum_2;
  841. nonzero = 1;
  842. if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
  843. || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
  844. hot = 1;
  845. }
  846. }
  847. ret += func_val;
  848. cum_1 += func_cum_1;
  849. cum_2 += func_cum_2;
  850. if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
  851. {
  852. printf(" \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
  853. gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
  854. }
  855. }
  856. *cum_1_result = cum_1;
  857. *cum_2_result = cum_2;
  858. return ret;
  859. }
  860. /* Test if all counter values in this GCOV_INFO are cold.
  861. "Cold" is defined as the counter value being less than
  862. or equal to THRESHOLD. */
  863. static bool
  864. gcov_info_count_all_cold (const struct gcov_info *gcov_info,
  865. gcov_type threshold)
  866. {
  867. unsigned f_ix;
  868. for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
  869. {
  870. const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
  871. if (!gfi_ptr || gfi_ptr->key != gcov_info)
  872. continue;
  873. const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
  874. for (unsigned c_num = 0; c_num < ci_ptr->num; c_num++)
  875. if (ci_ptr->values[c_num] > threshold)
  876. return false;
  877. }
  878. return true;
  879. }
  880. /* Test if all counter values in this GCOV_INFO are 0. */
  881. static bool
  882. gcov_info_count_all_zero (const struct gcov_info *gcov_info)
  883. {
  884. return gcov_info_count_all_cold (gcov_info, 0);
  885. }
  886. /* A pair of matched GCOV_INFO.
  887. The flag is a bitvector:
  888. b0: obj1's all counts are 0;
  889. b1: obj1's all counts are cold (but no 0);
  890. b2: obj1 is hot;
  891. b3: no obj1 to match obj2;
  892. b4: obj2's all counts are 0;
  893. b5: obj2's all counts are cold (but no 0);
  894. b6: obj2 is hot;
  895. b7: no obj2 to match obj1;
  896. */
  897. struct overlap_t {
  898. const struct gcov_info *obj1;
  899. const struct gcov_info *obj2;
  900. char flag;
  901. };
  902. #define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
  903. #define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
  904. #define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
  905. /* Cumlative overlap dscore for profile1 and profile2. */
  906. static double overlap_sum_1, overlap_sum_2;
  907. /* The number of gcda files in the profiles. */
  908. static unsigned gcda_files[2];
  909. /* The number of unique gcda files in the profiles
  910. (not existing in the other profile). */
  911. static unsigned unique_gcda_files[2];
  912. /* The number of gcda files that all counter values are 0. */
  913. static unsigned zero_gcda_files[2];
  914. /* The number of gcda files that all counter values are cold (but not 0). */
  915. static unsigned cold_gcda_files[2];
  916. /* The number of gcda files that includes hot counter values. */
  917. static unsigned hot_gcda_files[2];
  918. /* The number of gcda files with hot count value in either profiles. */
  919. static unsigned both_hot_cnt;
  920. /* The number of gcda files with all counts cold (but not 0) in
  921. both profiles. */
  922. static unsigned both_cold_cnt;
  923. /* The number of gcda files with all counts 0 in both profiles. */
  924. static unsigned both_zero_cnt;
  925. /* Extract the basename of the filename NAME. */
  926. static char *
  927. extract_file_basename (const char *name)
  928. {
  929. char *str;
  930. int len = 0;
  931. char *path = xstrdup (name);
  932. char sep_str[2];
  933. sep_str[0] = DIR_SEPARATOR;
  934. sep_str[1] = 0;
  935. str = strstr(path, sep_str);
  936. do{
  937. len = strlen(str) + 1;
  938. path = &path[strlen(path) - len + 2];
  939. str = strstr(path, sep_str);
  940. } while(str);
  941. return path;
  942. }
  943. /* Utility function to get the filename. */
  944. static const char *
  945. get_file_basename (const char *name)
  946. {
  947. if (overlap_use_fullname)
  948. return name;
  949. return extract_file_basename (name);
  950. }
  951. /* A utility function to set the flag for the gcda files. */
  952. static void
  953. set_flag (struct overlap_t *e)
  954. {
  955. char flag = 0;
  956. if (!e->obj1)
  957. {
  958. unique_gcda_files[1]++;
  959. flag = 0x8;
  960. }
  961. else
  962. {
  963. gcda_files[0]++;
  964. if (gcov_info_count_all_zero (e->obj1))
  965. {
  966. zero_gcda_files[0]++;
  967. flag = 0x1;
  968. }
  969. else
  970. if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
  971. * overlap_hot_threshold))
  972. {
  973. cold_gcda_files[0]++;
  974. flag = 0x2;
  975. }
  976. else
  977. {
  978. hot_gcda_files[0]++;
  979. flag = 0x4;
  980. }
  981. }
  982. if (!e->obj2)
  983. {
  984. unique_gcda_files[0]++;
  985. flag |= (0x8 << 4);
  986. }
  987. else
  988. {
  989. gcda_files[1]++;
  990. if (gcov_info_count_all_zero (e->obj2))
  991. {
  992. zero_gcda_files[1]++;
  993. flag |= (0x1 << 4);
  994. }
  995. else
  996. if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
  997. * overlap_hot_threshold))
  998. {
  999. cold_gcda_files[1]++;
  1000. flag |= (0x2 << 4);
  1001. }
  1002. else
  1003. {
  1004. hot_gcda_files[1]++;
  1005. flag |= (0x4 << 4);
  1006. }
  1007. }
  1008. gcc_assert (flag);
  1009. e->flag = flag;
  1010. }
  1011. /* Test if INFO1 and INFO2 are from the matched source file.
  1012. Return 1 if they match; return 0 otherwise. */
  1013. static int
  1014. matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
  1015. {
  1016. /* For FDO, we have to match the name. This can be expensive.
  1017. Maybe we should use hash here. */
  1018. if (strcmp (info1->filename, info2->filename))
  1019. return 0;
  1020. if (info1->n_functions != info2->n_functions)
  1021. {
  1022. fnotice (stderr, "mismatched profiles in %s (%d functions"
  1023. " vs %d functions)\n",
  1024. info1->filename,
  1025. info1->n_functions,
  1026. info2->n_functions);
  1027. return 0;
  1028. }
  1029. return 1;
  1030. }
  1031. /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
  1032. GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
  1033. match and 1.0 meaning a perfect match. */
  1034. static double
  1035. calculate_overlap (struct gcov_info *gcov_list1,
  1036. struct gcov_info *gcov_list2)
  1037. {
  1038. unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
  1039. unsigned int i, j;
  1040. const struct gcov_info *gi_ptr;
  1041. struct overlap_t *all_infos;
  1042. for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
  1043. list1_cnt++;
  1044. for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
  1045. list2_cnt++;
  1046. all_cnt = list1_cnt + list2_cnt;
  1047. all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
  1048. * all_cnt * 2);
  1049. gcc_assert (all_infos);
  1050. i = 0;
  1051. for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
  1052. {
  1053. all_infos[i].obj1 = gi_ptr;
  1054. all_infos[i].obj2 = 0;
  1055. }
  1056. for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
  1057. {
  1058. all_infos[i].obj1 = 0;
  1059. all_infos[i].obj2 = gi_ptr;
  1060. }
  1061. for (i = list1_cnt; i < all_cnt; i++)
  1062. {
  1063. if (all_infos[i].obj2 == 0)
  1064. continue;
  1065. for (j = 0; j < list1_cnt; j++)
  1066. {
  1067. if (all_infos[j].obj2 != 0)
  1068. continue;
  1069. if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
  1070. {
  1071. all_infos[j].obj2 = all_infos[i].obj2;
  1072. all_infos[i].obj2 = 0;
  1073. break;
  1074. }
  1075. }
  1076. }
  1077. for (i = 0; i < all_cnt; i++)
  1078. if (all_infos[i].obj1 || all_infos[i].obj2)
  1079. {
  1080. set_flag (all_infos + i);
  1081. if (FLAG_ONE_HOT (all_infos[i].flag))
  1082. both_hot_cnt++;
  1083. if (FLAG_BOTH_COLD(all_infos[i].flag))
  1084. both_cold_cnt++;
  1085. if (FLAG_BOTH_ZERO(all_infos[i].flag))
  1086. both_zero_cnt++;
  1087. }
  1088. double prg_val = 0;
  1089. double sum_val = 0;
  1090. double sum_cum_1 = 0;
  1091. double sum_cum_2 = 0;
  1092. for (i = 0; i < all_cnt; i++)
  1093. {
  1094. double val;
  1095. double cum_1, cum_2;
  1096. const char *filename;
  1097. if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
  1098. continue;
  1099. if (FLAG_BOTH_ZERO (all_infos[i].flag))
  1100. continue;
  1101. if (all_infos[i].obj1)
  1102. filename = get_file_basename (all_infos[i].obj1->filename);
  1103. else
  1104. filename = get_file_basename (all_infos[i].obj2->filename);
  1105. if (overlap_func_level)
  1106. printf("\n processing %36s:\n", filename);
  1107. val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
  1108. overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
  1109. if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
  1110. {
  1111. printf(" obj=%36s overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
  1112. filename, val*100, cum_1*100, cum_2*100);
  1113. sum_val += val;
  1114. sum_cum_1 += cum_1;
  1115. sum_cum_2 += cum_2;
  1116. }
  1117. prg_val += val;
  1118. }
  1119. free (all_infos);
  1120. if (overlap_obj_level)
  1121. printf(" SUM:%36s overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
  1122. "", sum_val*100, sum_cum_1*100, sum_cum_2*100);
  1123. printf (" Statistics:\n"
  1124. " profile1_# profile2_# overlap_#\n");
  1125. printf (" gcda files: %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
  1126. gcda_files[0]-unique_gcda_files[0]);
  1127. printf (" unique files: %12u\t%12u\n", unique_gcda_files[0],
  1128. unique_gcda_files[1]);
  1129. printf (" hot files: %12u\t%12u\t%12u\n", hot_gcda_files[0],
  1130. hot_gcda_files[1], both_hot_cnt);
  1131. printf (" cold files: %12u\t%12u\t%12u\n", cold_gcda_files[0],
  1132. cold_gcda_files[1], both_cold_cnt);
  1133. printf (" zero files: %12u\t%12u\t%12u\n", zero_gcda_files[0],
  1134. zero_gcda_files[1], both_zero_cnt);
  1135. return prg_val;
  1136. }
  1137. /* Compute the overlap score of two lists of gcov_info objects PROFILE1 and
  1138. PROFILE2.
  1139. Return 0 on success: without mismatch. Reutrn 1 on error. */
  1140. int
  1141. gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
  1142. {
  1143. double result;
  1144. result = calculate_overlap (profile1, profile2);
  1145. if (result > 0)
  1146. {
  1147. printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
  1148. return 0;
  1149. }
  1150. return 1;
  1151. }