cg_arcs.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /*
  2. * Copyright (c) 1983, 1993, 2001
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include "gprof.h"
  30. #include "libiberty.h"
  31. #include "search_list.h"
  32. #include "source.h"
  33. #include "symtab.h"
  34. #include "call_graph.h"
  35. #include "cg_arcs.h"
  36. #include "cg_dfn.h"
  37. #include "cg_print.h"
  38. #include "utils.h"
  39. #include "sym_ids.h"
  40. static int cmp_topo (const PTR, const PTR);
  41. static void propagate_time (Sym *);
  42. static void cycle_time (void);
  43. static void cycle_link (void);
  44. static void inherit_flags (Sym *);
  45. static void propagate_flags (Sym **);
  46. static int cmp_total (const PTR, const PTR);
  47. Sym *cycle_header;
  48. unsigned int num_cycles;
  49. Arc **arcs;
  50. unsigned int numarcs;
  51. /*
  52. * Return TRUE iff PARENT has an arc to covers the address
  53. * range covered by CHILD.
  54. */
  55. Arc *
  56. arc_lookup (Sym *parent, Sym *child)
  57. {
  58. Arc *arc;
  59. if (!parent || !child)
  60. {
  61. printf ("[arc_lookup] parent == 0 || child == 0\n");
  62. return 0;
  63. }
  64. DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n",
  65. parent->name, child->name));
  66. for (arc = parent->cg.children; arc; arc = arc->next_child)
  67. {
  68. DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n",
  69. arc->parent->name, arc->child->name));
  70. if (child->addr >= arc->child->addr
  71. && child->end_addr <= arc->child->end_addr)
  72. {
  73. return arc;
  74. }
  75. }
  76. return 0;
  77. }
  78. /*
  79. * Add (or just increment) an arc:
  80. */
  81. void
  82. arc_add (Sym *parent, Sym *child, unsigned long count)
  83. {
  84. static unsigned int maxarcs = 0;
  85. Arc *arc, **newarcs;
  86. DBG (TALLYDEBUG, printf ("[arc_add] %lu arcs from %s to %s\n",
  87. count, parent->name, child->name));
  88. arc = arc_lookup (parent, child);
  89. if (arc)
  90. {
  91. /*
  92. * A hit: just increment the count.
  93. */
  94. DBG (TALLYDEBUG, printf ("[tally] hit %lu += %lu\n",
  95. arc->count, count));
  96. arc->count += count;
  97. return;
  98. }
  99. arc = (Arc *) xmalloc (sizeof (*arc));
  100. memset (arc, 0, sizeof (*arc));
  101. arc->parent = parent;
  102. arc->child = child;
  103. arc->count = count;
  104. /* If this isn't an arc for a recursive call to parent, then add it
  105. to the array of arcs. */
  106. if (parent != child)
  107. {
  108. /* If we've exhausted space in our current array, get a new one
  109. and copy the contents. We might want to throttle the doubling
  110. factor one day. */
  111. if (numarcs == maxarcs)
  112. {
  113. /* Determine how much space we want to allocate. */
  114. if (maxarcs == 0)
  115. maxarcs = 1;
  116. maxarcs *= 2;
  117. /* Allocate the new array. */
  118. newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs);
  119. /* Copy the old array's contents into the new array. */
  120. memcpy (newarcs, arcs, numarcs * sizeof (Arc *));
  121. /* Free up the old array. */
  122. free (arcs);
  123. /* And make the new array be the current array. */
  124. arcs = newarcs;
  125. }
  126. /* Place this arc in the arc array. */
  127. arcs[numarcs++] = arc;
  128. }
  129. /* prepend this child to the children of this parent: */
  130. arc->next_child = parent->cg.children;
  131. parent->cg.children = arc;
  132. /* prepend this parent to the parents of this child: */
  133. arc->next_parent = child->cg.parents;
  134. child->cg.parents = arc;
  135. }
  136. static int
  137. cmp_topo (const PTR lp, const PTR rp)
  138. {
  139. const Sym *left = *(const Sym **) lp;
  140. const Sym *right = *(const Sym **) rp;
  141. return left->cg.top_order - right->cg.top_order;
  142. }
  143. static void
  144. propagate_time (Sym *parent)
  145. {
  146. Arc *arc;
  147. Sym *child;
  148. double share, prop_share;
  149. if (parent->cg.prop.fract == 0.0)
  150. {
  151. return;
  152. }
  153. /* gather time from children of this parent: */
  154. for (arc = parent->cg.children; arc; arc = arc->next_child)
  155. {
  156. child = arc->child;
  157. if (arc->count == 0 || child == parent || child->cg.prop.fract == 0)
  158. {
  159. continue;
  160. }
  161. if (child->cg.cyc.head != child)
  162. {
  163. if (parent->cg.cyc.num == child->cg.cyc.num)
  164. {
  165. continue;
  166. }
  167. if (parent->cg.top_order <= child->cg.top_order)
  168. {
  169. fprintf (stderr, "[propagate] toporder botches\n");
  170. }
  171. child = child->cg.cyc.head;
  172. }
  173. else
  174. {
  175. if (parent->cg.top_order <= child->cg.top_order)
  176. {
  177. fprintf (stderr, "[propagate] toporder botches\n");
  178. continue;
  179. }
  180. }
  181. if (child->ncalls == 0)
  182. {
  183. continue;
  184. }
  185. /* distribute time for this arc: */
  186. arc->time = child->hist.time * (((double) arc->count)
  187. / ((double) child->ncalls));
  188. arc->child_time = child->cg.child_time
  189. * (((double) arc->count) / ((double) child->ncalls));
  190. share = arc->time + arc->child_time;
  191. parent->cg.child_time += share;
  192. /* (1 - cg.prop.fract) gets lost along the way: */
  193. prop_share = parent->cg.prop.fract * share;
  194. /* fix things for printing: */
  195. parent->cg.prop.child += prop_share;
  196. arc->time *= parent->cg.prop.fract;
  197. arc->child_time *= parent->cg.prop.fract;
  198. /* add this share to the parent's cycle header, if any: */
  199. if (parent->cg.cyc.head != parent)
  200. {
  201. parent->cg.cyc.head->cg.child_time += share;
  202. parent->cg.cyc.head->cg.prop.child += prop_share;
  203. }
  204. DBG (PROPDEBUG,
  205. printf ("[prop_time] child \t");
  206. print_name (child);
  207. printf (" with %f %f %lu/%lu\n", child->hist.time,
  208. child->cg.child_time, arc->count, child->ncalls);
  209. printf ("[prop_time] parent\t");
  210. print_name (parent);
  211. printf ("\n[prop_time] share %f\n", share));
  212. }
  213. }
  214. /*
  215. * Compute the time of a cycle as the sum of the times of all
  216. * its members.
  217. */
  218. static void
  219. cycle_time (void)
  220. {
  221. Sym *member, *cyc;
  222. for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc)
  223. {
  224. for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
  225. {
  226. if (member->cg.prop.fract == 0.0)
  227. {
  228. /*
  229. * All members have the same propfraction except those
  230. * that were excluded with -E.
  231. */
  232. continue;
  233. }
  234. cyc->hist.time += member->hist.time;
  235. }
  236. cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time;
  237. }
  238. }
  239. static void
  240. cycle_link (void)
  241. {
  242. Sym *sym, *cyc, *member;
  243. Arc *arc;
  244. int num;
  245. /* count the number of cycles, and initialize the cycle lists: */
  246. num_cycles = 0;
  247. for (sym = symtab.base; sym < symtab.limit; ++sym)
  248. {
  249. /* this is how you find unattached cycles: */
  250. if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
  251. {
  252. ++num_cycles;
  253. }
  254. }
  255. /*
  256. * cycle_header is indexed by cycle number: i.e. it is origin 1,
  257. * not origin 0.
  258. */
  259. cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym));
  260. /*
  261. * Now link cycles to true cycle-heads, number them, accumulate
  262. * the data for the cycle.
  263. */
  264. num = 0;
  265. cyc = cycle_header;
  266. for (sym = symtab.base; sym < symtab.limit; ++sym)
  267. {
  268. if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
  269. {
  270. continue;
  271. }
  272. ++num;
  273. ++cyc;
  274. sym_init (cyc);
  275. cyc->cg.print_flag = true; /* should this be printed? */
  276. cyc->cg.top_order = DFN_NAN; /* graph call chain top-sort order */
  277. cyc->cg.cyc.num = num; /* internal number of cycle on */
  278. cyc->cg.cyc.head = cyc; /* pointer to head of cycle */
  279. cyc->cg.cyc.next = sym; /* pointer to next member of cycle */
  280. DBG (CYCLEDEBUG, printf ("[cycle_link] ");
  281. print_name (sym);
  282. printf (" is the head of cycle %d\n", num));
  283. /* link members to cycle header: */
  284. for (member = sym; member; member = member->cg.cyc.next)
  285. {
  286. member->cg.cyc.num = num;
  287. member->cg.cyc.head = cyc;
  288. }
  289. /*
  290. * Count calls from outside the cycle and those among cycle
  291. * members:
  292. */
  293. for (member = sym; member; member = member->cg.cyc.next)
  294. {
  295. for (arc = member->cg.parents; arc; arc = arc->next_parent)
  296. {
  297. if (arc->parent == member)
  298. {
  299. continue;
  300. }
  301. if (arc->parent->cg.cyc.num == num)
  302. {
  303. cyc->cg.self_calls += arc->count;
  304. }
  305. else
  306. {
  307. cyc->ncalls += arc->count;
  308. }
  309. }
  310. }
  311. }
  312. }
  313. /*
  314. * Check if any parent of this child (or outside parents of this
  315. * cycle) have their print flags on and set the print flag of the
  316. * child (cycle) appropriately. Similarly, deal with propagation
  317. * fractions from parents.
  318. */
  319. static void
  320. inherit_flags (Sym *child)
  321. {
  322. Sym *head, *parent, *member;
  323. Arc *arc;
  324. head = child->cg.cyc.head;
  325. if (child == head)
  326. {
  327. /* just a regular child, check its parents: */
  328. child->cg.print_flag = false;
  329. child->cg.prop.fract = 0.0;
  330. for (arc = child->cg.parents; arc; arc = arc->next_parent)
  331. {
  332. parent = arc->parent;
  333. if (child == parent)
  334. {
  335. continue;
  336. }
  337. child->cg.print_flag |= parent->cg.print_flag;
  338. /*
  339. * If the child was never actually called (e.g., this arc
  340. * is static (and all others are, too)) no time propagates
  341. * along this arc.
  342. */
  343. if (child->ncalls != 0)
  344. {
  345. child->cg.prop.fract += parent->cg.prop.fract
  346. * (((double) arc->count) / ((double) child->ncalls));
  347. }
  348. }
  349. }
  350. else
  351. {
  352. /*
  353. * Its a member of a cycle, look at all parents from outside
  354. * the cycle.
  355. */
  356. head->cg.print_flag = false;
  357. head->cg.prop.fract = 0.0;
  358. for (member = head->cg.cyc.next; member; member = member->cg.cyc.next)
  359. {
  360. for (arc = member->cg.parents; arc; arc = arc->next_parent)
  361. {
  362. if (arc->parent->cg.cyc.head == head)
  363. {
  364. continue;
  365. }
  366. parent = arc->parent;
  367. head->cg.print_flag |= parent->cg.print_flag;
  368. /*
  369. * If the cycle was never actually called (e.g. this
  370. * arc is static (and all others are, too)) no time
  371. * propagates along this arc.
  372. */
  373. if (head->ncalls != 0)
  374. {
  375. head->cg.prop.fract += parent->cg.prop.fract
  376. * (((double) arc->count) / ((double) head->ncalls));
  377. }
  378. }
  379. }
  380. for (member = head; member; member = member->cg.cyc.next)
  381. {
  382. member->cg.print_flag = head->cg.print_flag;
  383. member->cg.prop.fract = head->cg.prop.fract;
  384. }
  385. }
  386. }
  387. /*
  388. * In one top-to-bottom pass over the topologically sorted symbols
  389. * propagate:
  390. * cg.print_flag as the union of parents' print_flags
  391. * propfraction as the sum of fractional parents' propfractions
  392. * and while we're here, sum time for functions.
  393. */
  394. static void
  395. propagate_flags (Sym **symbols)
  396. {
  397. int sym_index;
  398. Sym *old_head, *child;
  399. old_head = 0;
  400. for (sym_index = symtab.len - 1; sym_index >= 0; --sym_index)
  401. {
  402. child = symbols[sym_index];
  403. /*
  404. * If we haven't done this function or cycle, inherit things
  405. * from parent. This way, we are linear in the number of arcs
  406. * since we do all members of a cycle (and the cycle itself)
  407. * as we hit the first member of the cycle.
  408. */
  409. if (child->cg.cyc.head != old_head)
  410. {
  411. old_head = child->cg.cyc.head;
  412. inherit_flags (child);
  413. }
  414. DBG (PROPDEBUG,
  415. printf ("[prop_flags] ");
  416. print_name (child);
  417. printf ("inherits print-flag %d and prop-fract %f\n",
  418. child->cg.print_flag, child->cg.prop.fract));
  419. if (!child->cg.print_flag)
  420. {
  421. /*
  422. * Printflag is off. It gets turned on by being in the
  423. * INCL_GRAPH table, or there being an empty INCL_GRAPH
  424. * table and not being in the EXCL_GRAPH table.
  425. */
  426. if (sym_lookup (&syms[INCL_GRAPH], child->addr)
  427. || (syms[INCL_GRAPH].len == 0
  428. && !sym_lookup (&syms[EXCL_GRAPH], child->addr)))
  429. {
  430. child->cg.print_flag = true;
  431. }
  432. }
  433. else
  434. {
  435. /*
  436. * This function has printing parents: maybe someone wants
  437. * to shut it up by putting it in the EXCL_GRAPH table.
  438. * (But favor INCL_GRAPH over EXCL_GRAPH.)
  439. */
  440. if (!sym_lookup (&syms[INCL_GRAPH], child->addr)
  441. && sym_lookup (&syms[EXCL_GRAPH], child->addr))
  442. {
  443. child->cg.print_flag = false;
  444. }
  445. }
  446. if (child->cg.prop.fract == 0.0)
  447. {
  448. /*
  449. * No parents to pass time to. Collect time from children
  450. * if its in the INCL_TIME table, or there is an empty
  451. * INCL_TIME table and its not in the EXCL_TIME table.
  452. */
  453. if (sym_lookup (&syms[INCL_TIME], child->addr)
  454. || (syms[INCL_TIME].len == 0
  455. && !sym_lookup (&syms[EXCL_TIME], child->addr)))
  456. {
  457. child->cg.prop.fract = 1.0;
  458. }
  459. }
  460. else
  461. {
  462. /*
  463. * It has parents to pass time to, but maybe someone wants
  464. * to shut it up by puttting it in the EXCL_TIME table.
  465. * (But favor being in INCL_TIME tabe over being in
  466. * EXCL_TIME table.)
  467. */
  468. if (!sym_lookup (&syms[INCL_TIME], child->addr)
  469. && sym_lookup (&syms[EXCL_TIME], child->addr))
  470. {
  471. child->cg.prop.fract = 0.0;
  472. }
  473. }
  474. child->cg.prop.self = child->hist.time * child->cg.prop.fract;
  475. print_time += child->cg.prop.self;
  476. DBG (PROPDEBUG,
  477. printf ("[prop_flags] ");
  478. print_name (child);
  479. printf (" ends up with printflag %d and prop-fract %f\n",
  480. child->cg.print_flag, child->cg.prop.fract);
  481. printf ("[prop_flags] time %f propself %f print_time %f\n",
  482. child->hist.time, child->cg.prop.self, print_time));
  483. }
  484. }
  485. /*
  486. * Compare by decreasing propagated time. If times are equal, but one
  487. * is a cycle header, say that's first (e.g. less, i.e. -1). If one's
  488. * name doesn't have an underscore and the other does, say that one is
  489. * first. All else being equal, compare by names.
  490. */
  491. static int
  492. cmp_total (const PTR lp, const PTR rp)
  493. {
  494. const Sym *left = *(const Sym **) lp;
  495. const Sym *right = *(const Sym **) rp;
  496. double diff;
  497. diff = (left->cg.prop.self + left->cg.prop.child)
  498. - (right->cg.prop.self + right->cg.prop.child);
  499. if (diff < 0.0)
  500. {
  501. return 1;
  502. }
  503. if (diff > 0.0)
  504. {
  505. return -1;
  506. }
  507. if (!left->name && left->cg.cyc.num != 0)
  508. {
  509. return -1;
  510. }
  511. if (!right->name && right->cg.cyc.num != 0)
  512. {
  513. return 1;
  514. }
  515. if (!left->name)
  516. {
  517. return -1;
  518. }
  519. if (!right->name)
  520. {
  521. return 1;
  522. }
  523. if (left->name[0] != '_' && right->name[0] == '_')
  524. {
  525. return -1;
  526. }
  527. if (left->name[0] == '_' && right->name[0] != '_')
  528. {
  529. return 1;
  530. }
  531. if (left->ncalls > right->ncalls)
  532. {
  533. return -1;
  534. }
  535. if (left->ncalls < right->ncalls)
  536. {
  537. return 1;
  538. }
  539. return strcmp (left->name, right->name);
  540. }
  541. /* Topologically sort the graph (collapsing cycles), and propagates
  542. time bottom up and flags top down. */
  543. Sym **
  544. cg_assemble (void)
  545. {
  546. Sym *parent, **time_sorted_syms, **top_sorted_syms;
  547. unsigned int sym_index;
  548. Arc *arc;
  549. /* Initialize various things:
  550. Zero out child times.
  551. Count self-recursive calls.
  552. Indicate that nothing is on cycles. */
  553. for (parent = symtab.base; parent < symtab.limit; parent++)
  554. {
  555. parent->cg.child_time = 0.0;
  556. arc = arc_lookup (parent, parent);
  557. if (arc && parent == arc->child)
  558. {
  559. parent->ncalls -= arc->count;
  560. parent->cg.self_calls = arc->count;
  561. }
  562. else
  563. {
  564. parent->cg.self_calls = 0;
  565. }
  566. parent->cg.prop.fract = 0.0;
  567. parent->cg.prop.self = 0.0;
  568. parent->cg.prop.child = 0.0;
  569. parent->cg.print_flag = false;
  570. parent->cg.top_order = DFN_NAN;
  571. parent->cg.cyc.num = 0;
  572. parent->cg.cyc.head = parent;
  573. parent->cg.cyc.next = 0;
  574. if (ignore_direct_calls)
  575. find_call (parent, parent->addr, (parent + 1)->addr);
  576. }
  577. /* Topologically order things. If any node is unnumbered, number
  578. it and any of its descendents. */
  579. for (parent = symtab.base; parent < symtab.limit; parent++)
  580. {
  581. if (parent->cg.top_order == DFN_NAN)
  582. cg_dfn (parent);
  583. }
  584. /* Link together nodes on the same cycle. */
  585. cycle_link ();
  586. /* Sort the symbol table in reverse topological order. */
  587. top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  588. for (sym_index = 0; sym_index < symtab.len; ++sym_index)
  589. top_sorted_syms[sym_index] = &symtab.base[sym_index];
  590. qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
  591. DBG (DFNDEBUG,
  592. printf ("[cg_assemble] topological sort listing\n");
  593. for (sym_index = 0; sym_index < symtab.len; ++sym_index)
  594. {
  595. printf ("[cg_assemble] ");
  596. printf ("%d:", top_sorted_syms[sym_index]->cg.top_order);
  597. print_name (top_sorted_syms[sym_index]);
  598. printf ("\n");
  599. }
  600. );
  601. /* Starting from the topological top, propagate print flags to
  602. children. also, calculate propagation fractions. this happens
  603. before time propagation since time propagation uses the
  604. fractions. */
  605. propagate_flags (top_sorted_syms);
  606. /* Starting from the topological bottom, propagate children times
  607. up to parents. */
  608. cycle_time ();
  609. for (sym_index = 0; sym_index < symtab.len; ++sym_index)
  610. propagate_time (top_sorted_syms[sym_index]);
  611. free (top_sorted_syms);
  612. /* Now, sort by CG.PROP.SELF + CG.PROP.CHILD. Sorting both the regular
  613. function names and cycle headers. */
  614. time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
  615. for (sym_index = 0; sym_index < symtab.len; sym_index++)
  616. time_sorted_syms[sym_index] = &symtab.base[sym_index];
  617. for (sym_index = 1; sym_index <= num_cycles; sym_index++)
  618. time_sorted_syms[symtab.len + sym_index - 1] = &cycle_header[sym_index];
  619. qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
  620. cmp_total);
  621. for (sym_index = 0; sym_index < symtab.len + num_cycles; sym_index++)
  622. time_sorted_syms[sym_index]->cg.index = sym_index + 1;
  623. return time_sorted_syms;
  624. }