c-opts.c (missing_arg): Use cl_options[opt_index].opt_code instead of just opt_index...
[gcc.git] / gcc / profile.c
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3 2000, 2001 Free Software Foundation, Inc.
4 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5 based on some ideas from Dain Samples of UC Berkeley.
6 Further mangling by Bob Manson, Cygnus Support.
7
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
25 /* Generate basic block profile instrumentation and auxiliary files.
26 Profile generation is optimized, so that not all arcs in the basic
27 block graph need instrumenting. First, the BB graph is closed with
28 one entry (function start), and one exit (function exit). Any
29 ABNORMAL_EDGE cannot be instrumented (because there is no control
30 path to place the code). We close the graph by inserting fake
31 EDGE_FAKE edges to the EXIT_BLOCK, from the sources of abnormal
32 edges that do not go to the exit_block. We ignore such abnormal
33 edges. Naturally these fake edges are never directly traversed,
34 and so *cannot* be directly instrumented. Some other graph
35 massaging is done. To optimize the instrumentation we generate the
36 BB minimal span tree, only edges that are not on the span tree
37 (plus the entry point) need instrumenting. From that information
38 all other edge counts can be deduced. By construction all fake
39 edges must be on the spanning tree. We also attempt to place
40 EDGE_CRITICAL edges on the spanning tree.
41
42 The two auxiliary files generated are <dumpbase>.bb and
43 <dumpbase>.bbg. The former contains the BB->linenumber
44 mappings, and the latter describes the BB graph.
45
46 The BB file contains line numbers for each block. For each basic
47 block, a zero count is output (to mark the start of a block), then
48 the line numbers of that block are listed. A zero ends the file
49 too.
50
51 The BBG file contains a count of the blocks, followed by edge
52 information, for every edge in the graph. The edge information
53 lists the source and target block numbers, and a bit mask
54 describing the type of edge.
55
56 The BB and BBG file formats are fully described in the gcov
57 documentation. */
58
59 /* ??? Register allocation should use basic block execution counts to
60 give preference to the most commonly executed blocks. */
61
62 /* ??? The .da files are not safe. Changing the program after creating .da
63 files or using different options when compiling with -fbranch-probabilities
64 can result the arc data not matching the program. Maybe add instrumented
65 arc count to .bbg file? Maybe check whether PFG matches the .bbg file? */
66
67 /* ??? Should calculate branch probabilities before instrumenting code, since
68 then we can use arc counts to help decide which arcs to instrument. */
69
70 #include "config.h"
71 #include "system.h"
72 #include "rtl.h"
73 #include "tree.h"
74 #include "flags.h"
75 #include "insn-config.h"
76 #include "output.h"
77 #include "regs.h"
78 #include "expr.h"
79 #include "function.h"
80 #include "toplev.h"
81 #include "ggc.h"
82 #include "hard-reg-set.h"
83 #include "basic-block.h"
84 #include "gcov-io.h"
85 #include "target.h"
86 #include "profile.h"
87 #include "libfuncs.h"
88 #include "langhooks.h"
89
90 /* Additional information about the edges we need. */
91 struct edge_info {
92 unsigned int count_valid : 1;
93
94 /* Is on the spanning tree. */
95 unsigned int on_tree : 1;
96
97 /* Pretend this edge does not exist (it is abnormal and we've
98 inserted a fake to compensate). */
99 unsigned int ignore : 1;
100 };
101
102 struct bb_info {
103 unsigned int count_valid : 1;
104
105 /* Number of successor and predecessor edges. */
106 gcov_type succ_count;
107 gcov_type pred_count;
108 };
109
110 #define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
111 #define BB_INFO(b) ((struct bb_info *) (b)->aux)
112
113 /* Keep all basic block indexes nonnegative in the gcov output. Index 0
114 is used for entry block, last block exit block. */
115 #define BB_TO_GCOV_INDEX(bb) ((bb) == ENTRY_BLOCK_PTR ? 0 \
116 : ((bb) == EXIT_BLOCK_PTR \
117 ? last_basic_block + 1 : (bb)->index + 1))
118
119 /* Instantiate the profile info structure. */
120
121 struct profile_info profile_info;
122
123 /* Name and file pointer of the output file for the basic block graph. */
124
125 static FILE *bbg_file;
126
127 /* Name and file pointer of the input file for the arc count data. */
128
129 static FILE *da_file;
130 static char *da_file_name;
131
132 /* Pointer of the output file for the basic block/line number map. */
133 static FILE *bb_file;
134
135 /* Last source file name written to bb_file. */
136
137 static char *last_bb_file_name;
138
139 /* Collect statistics on the performance of this pass for the entire source
140 file. */
141
142 static int total_num_blocks;
143 static int total_num_edges;
144 static int total_num_edges_ignored;
145 static int total_num_edges_instrumented;
146 static int total_num_blocks_created;
147 static int total_num_passes;
148 static int total_num_times_called;
149 static int total_hist_br_prob[20];
150 static int total_num_never_executed;
151 static int total_num_branches;
152
153 /* Forward declarations. */
154 static void find_spanning_tree PARAMS ((struct edge_list *));
155 static void init_edge_profiler PARAMS ((void));
156 static rtx gen_edge_profiler PARAMS ((int));
157 static void instrument_edges PARAMS ((struct edge_list *));
158 static void output_gcov_string PARAMS ((const char *, long));
159 static void compute_branch_probabilities PARAMS ((void));
160 static gcov_type * get_exec_counts PARAMS ((void));
161 static long compute_checksum PARAMS ((void));
162 static basic_block find_group PARAMS ((basic_block));
163 static void union_groups PARAMS ((basic_block, basic_block));
164
165 /* If nonzero, we need to output a constructor to set up the
166 per-object-file data. */
167 static int need_func_profiler = 0;
168 \f
169 /* Add edge instrumentation code to the entire insn chain.
170
171 F is the first insn of the chain.
172 NUM_BLOCKS is the number of basic blocks found in F. */
173
174 static void
175 instrument_edges (el)
176 struct edge_list *el;
177 {
178 int num_instr_edges = 0;
179 int num_edges = NUM_EDGES (el);
180 basic_block bb;
181 remove_fake_edges ();
182
183 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
184 {
185 edge e = bb->succ;
186 while (e)
187 {
188 struct edge_info *inf = EDGE_INFO (e);
189 if (!inf->ignore && !inf->on_tree)
190 {
191 if (e->flags & EDGE_ABNORMAL)
192 abort ();
193 if (rtl_dump_file)
194 fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
195 e->src->index, e->dest->index,
196 EDGE_CRITICAL_P (e) ? " (and split)" : "");
197 need_func_profiler = 1;
198 insert_insn_on_edge (
199 gen_edge_profiler (total_num_edges_instrumented
200 + num_instr_edges++), e);
201 }
202 e = e->succ_next;
203 }
204 }
205
206 profile_info.count_edges_instrumented_now = num_instr_edges;
207 total_num_edges_instrumented += num_instr_edges;
208 profile_info.count_instrumented_edges = total_num_edges_instrumented;
209
210 total_num_blocks_created += num_edges;
211 if (rtl_dump_file)
212 fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
213
214 commit_edge_insertions_watch_calls ();
215 }
216
217 /* Output STRING to bb_file, surrounded by DELIMITER. */
218
219 static void
220 output_gcov_string (string, delimiter)
221 const char *string;
222 long delimiter;
223 {
224 size_t temp;
225
226 /* Write a delimiter to indicate that a file name follows. */
227 __write_long (delimiter, bb_file, 4);
228
229 /* Write the string. */
230 temp = strlen (string) + 1;
231 fwrite (string, temp, 1, bb_file);
232
233 /* Append a few zeros, to align the output to a 4 byte boundary. */
234 temp = temp & 0x3;
235 if (temp)
236 {
237 char c[4];
238
239 c[0] = c[1] = c[2] = c[3] = 0;
240 fwrite (c, sizeof (char), 4 - temp, bb_file);
241 }
242
243 /* Store another delimiter in the .bb file, just to make it easy to find
244 the end of the file name. */
245 __write_long (delimiter, bb_file, 4);
246 }
247 \f
248
249 /* Computes hybrid profile for all matching entries in da_file.
250 Sets max_counter_in_program as a side effect. */
251
252 static gcov_type *
253 get_exec_counts ()
254 {
255 int num_edges = 0;
256 basic_block bb;
257 int okay = 1, i;
258 int mismatch = 0;
259 gcov_type *profile;
260 char *function_name_buffer;
261 int function_name_buffer_len;
262 gcov_type max_counter_in_run;
263 const char *name = IDENTIFIER_POINTER
264 (DECL_ASSEMBLER_NAME (current_function_decl));
265
266 profile_info.max_counter_in_program = 0;
267 profile_info.count_profiles_merged = 0;
268
269 /* No .da file, no execution counts. */
270 if (!da_file)
271 return 0;
272
273 /* Count the edges to be (possibly) instrumented. */
274
275 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
276 {
277 edge e;
278 for (e = bb->succ; e; e = e->succ_next)
279 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
280 num_edges++;
281 }
282
283 /* now read and combine all matching profiles. */
284
285 profile = xmalloc (sizeof (gcov_type) * num_edges);
286 rewind (da_file);
287 function_name_buffer_len = strlen (name) + 1;
288 function_name_buffer = xmalloc (function_name_buffer_len + 1);
289
290 for (i = 0; i < num_edges; i++)
291 profile[i] = 0;
292
293 while (1)
294 {
295 long magic, extra_bytes;
296 long func_count;
297 int i;
298
299 if (__read_long (&magic, da_file, 4) != 0)
300 break;
301
302 if (magic != -123)
303 {
304 okay = 0;
305 break;
306 }
307
308 if (__read_long (&func_count, da_file, 4) != 0)
309 {
310 okay = 0;
311 break;
312 }
313
314 if (__read_long (&extra_bytes, da_file, 4) != 0)
315 {
316 okay = 0;
317 break;
318 }
319
320 fseek (da_file, 4 + 8, SEEK_CUR);
321
322 /* read the maximal counter. */
323 __read_gcov_type (&max_counter_in_run, da_file, 8);
324
325 /* skip the rest of "statistics" emited by __bb_exit_func. */
326 fseek (da_file, extra_bytes - (4 + 8 + 8), SEEK_CUR);
327
328 for (i = 0; i < func_count; i++)
329 {
330 long arc_count;
331 long chksum;
332 int j;
333
334 if (__read_gcov_string
335 (function_name_buffer, function_name_buffer_len, da_file,
336 -1) != 0)
337 {
338 okay = 0;
339 break;
340 }
341
342 if (__read_long (&chksum, da_file, 4) != 0)
343 {
344 okay = 0;
345 break;
346 }
347
348 if (__read_long (&arc_count, da_file, 4) != 0)
349 {
350 okay = 0;
351 break;
352 }
353
354 if (strcmp (function_name_buffer, name) != 0)
355 {
356 /* skip */
357 if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
358 {
359 okay = 0;
360 break;
361 }
362 }
363 else if (arc_count != num_edges
364 || chksum != profile_info.current_function_cfg_checksum)
365 okay = 0, mismatch = 1;
366 else
367 {
368 gcov_type tmp;
369
370 profile_info.max_counter_in_program += max_counter_in_run;
371 profile_info.count_profiles_merged++;
372
373 for (j = 0; j < arc_count; j++)
374 if (__read_gcov_type (&tmp, da_file, 8) != 0)
375 {
376 okay = 0;
377 break;
378 }
379 else
380 {
381 profile[j] += tmp;
382 }
383 }
384 }
385
386 if (!okay)
387 break;
388
389 }
390
391 free (function_name_buffer);
392
393 if (!okay)
394 {
395 if (mismatch)
396 error
397 ("Profile does not match flowgraph of function %s (out of date?)",
398 current_function_name);
399 else
400 error (".da file corrupted");
401 free (profile);
402 return 0;
403 }
404 if (rtl_dump_file)
405 {
406 fprintf(rtl_dump_file, "Merged %i profiles with maximal count %i.\n",
407 profile_info.count_profiles_merged,
408 (int)profile_info.max_counter_in_program);
409 }
410
411 return profile;
412 }
413 \f
414
415 /* Compute the branch probabilities for the various branches.
416 Annotate them accordingly. */
417
418 static void
419 compute_branch_probabilities ()
420 {
421 basic_block bb;
422 int i;
423 int num_edges = 0;
424 int changes;
425 int passes;
426 int hist_br_prob[20];
427 int num_never_executed;
428 int num_branches;
429 gcov_type *exec_counts = get_exec_counts ();
430 int exec_counts_pos = 0;
431
432 /* Attach extra info block to each bb. */
433
434 alloc_aux_for_blocks (sizeof (struct bb_info));
435 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
436 {
437 edge e;
438
439 for (e = bb->succ; e; e = e->succ_next)
440 if (!EDGE_INFO (e)->ignore)
441 BB_INFO (bb)->succ_count++;
442 for (e = bb->pred; e; e = e->pred_next)
443 if (!EDGE_INFO (e)->ignore)
444 BB_INFO (bb)->pred_count++;
445 }
446
447 /* Avoid predicting entry on exit nodes. */
448 BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
449 BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
450
451 /* For each edge not on the spanning tree, set its execution count from
452 the .da file. */
453
454 /* The first count in the .da file is the number of times that the function
455 was entered. This is the exec_count for block zero. */
456
457 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
458 {
459 edge e;
460 for (e = bb->succ; e; e = e->succ_next)
461 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
462 {
463 num_edges++;
464 if (exec_counts)
465 {
466 e->count = exec_counts[exec_counts_pos++];
467 }
468 else
469 e->count = 0;
470
471 EDGE_INFO (e)->count_valid = 1;
472 BB_INFO (bb)->succ_count--;
473 BB_INFO (e->dest)->pred_count--;
474 if (rtl_dump_file)
475 {
476 fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
477 bb->index, e->dest->index);
478 fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
479 (HOST_WIDEST_INT) e->count);
480 }
481 }
482 }
483
484 if (rtl_dump_file)
485 fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
486
487 /* For every block in the file,
488 - if every exit/entrance edge has a known count, then set the block count
489 - if the block count is known, and every exit/entrance edge but one has
490 a known execution count, then set the count of the remaining edge
491
492 As edge counts are set, decrement the succ/pred count, but don't delete
493 the edge, that way we can easily tell when all edges are known, or only
494 one edge is unknown. */
495
496 /* The order that the basic blocks are iterated through is important.
497 Since the code that finds spanning trees starts with block 0, low numbered
498 edges are put on the spanning tree in preference to high numbered edges.
499 Hence, most instrumented edges are at the end. Graph solving works much
500 faster if we propagate numbers from the end to the start.
501
502 This takes an average of slightly more than 3 passes. */
503
504 changes = 1;
505 passes = 0;
506 while (changes)
507 {
508 passes++;
509 changes = 0;
510 FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
511 {
512 struct bb_info *bi = BB_INFO (bb);
513 if (! bi->count_valid)
514 {
515 if (bi->succ_count == 0)
516 {
517 edge e;
518 gcov_type total = 0;
519
520 for (e = bb->succ; e; e = e->succ_next)
521 total += e->count;
522 bb->count = total;
523 bi->count_valid = 1;
524 changes = 1;
525 }
526 else if (bi->pred_count == 0)
527 {
528 edge e;
529 gcov_type total = 0;
530
531 for (e = bb->pred; e; e = e->pred_next)
532 total += e->count;
533 bb->count = total;
534 bi->count_valid = 1;
535 changes = 1;
536 }
537 }
538 if (bi->count_valid)
539 {
540 if (bi->succ_count == 1)
541 {
542 edge e;
543 gcov_type total = 0;
544
545 /* One of the counts will be invalid, but it is zero,
546 so adding it in also doesn't hurt. */
547 for (e = bb->succ; e; e = e->succ_next)
548 total += e->count;
549
550 /* Seedgeh for the invalid edge, and set its count. */
551 for (e = bb->succ; e; e = e->succ_next)
552 if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
553 break;
554
555 /* Calculate count for remaining edge by conservation. */
556 total = bb->count - total;
557
558 if (! e)
559 abort ();
560 EDGE_INFO (e)->count_valid = 1;
561 e->count = total;
562 bi->succ_count--;
563
564 BB_INFO (e->dest)->pred_count--;
565 changes = 1;
566 }
567 if (bi->pred_count == 1)
568 {
569 edge e;
570 gcov_type total = 0;
571
572 /* One of the counts will be invalid, but it is zero,
573 so adding it in also doesn't hurt. */
574 for (e = bb->pred; e; e = e->pred_next)
575 total += e->count;
576
577 /* Seedgeh for the invalid edge, and set its count. */
578 for (e = bb->pred; e; e = e->pred_next)
579 if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
580 break;
581
582 /* Calculate count for remaining edge by conservation. */
583 total = bb->count - total + e->count;
584
585 if (! e)
586 abort ();
587 EDGE_INFO (e)->count_valid = 1;
588 e->count = total;
589 bi->pred_count--;
590
591 BB_INFO (e->src)->succ_count--;
592 changes = 1;
593 }
594 }
595 }
596 }
597 if (rtl_dump_file)
598 dump_flow_info (rtl_dump_file);
599
600 total_num_passes += passes;
601 if (rtl_dump_file)
602 fprintf (rtl_dump_file, "Graph solving took %d passes.\n\n", passes);
603
604 /* If the graph has been correctly solved, every block will have a
605 succ and pred count of zero. */
606 FOR_EACH_BB (bb)
607 {
608 if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
609 abort ();
610 }
611
612 /* For every edge, calculate its branch probability and add a reg_note
613 to the branch insn to indicate this. */
614
615 for (i = 0; i < 20; i++)
616 hist_br_prob[i] = 0;
617 num_never_executed = 0;
618 num_branches = 0;
619
620 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
621 {
622 edge e;
623 gcov_type total;
624 rtx note;
625
626 total = bb->count;
627 if (total)
628 {
629 for (e = bb->succ; e; e = e->succ_next)
630 {
631 e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
632 if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
633 {
634 error ("corrupted profile info: prob for %d-%d thought to be %d",
635 e->src->index, e->dest->index, e->probability);
636 e->probability = REG_BR_PROB_BASE / 2;
637 }
638 }
639 if (bb->index >= 0
640 && any_condjump_p (bb->end)
641 && bb->succ->succ_next)
642 {
643 int prob;
644 edge e;
645 int index;
646
647 /* Find the branch edge. It is possible that we do have fake
648 edges here. */
649 for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
650 e = e->succ_next)
651 continue; /* Loop body has been intentionally left blank. */
652
653 prob = e->probability;
654 index = prob * 20 / REG_BR_PROB_BASE;
655
656 if (index == 20)
657 index = 19;
658 hist_br_prob[index]++;
659
660 note = find_reg_note (bb->end, REG_BR_PROB, 0);
661 /* There may be already note put by some other pass, such
662 as builtin_expect expander. */
663 if (note)
664 XEXP (note, 0) = GEN_INT (prob);
665 else
666 REG_NOTES (bb->end)
667 = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
668 REG_NOTES (bb->end));
669 num_branches++;
670 }
671 }
672 /* Otherwise distribute the probabilities evenly so we get sane sum.
673 Use simple heuristics that if there are normal edges, give all abnormals
674 frequency of 0, otherwise distribute the frequency over abnormals
675 (this is the case of noreturn calls). */
676 else
677 {
678 for (e = bb->succ; e; e = e->succ_next)
679 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
680 total ++;
681 if (total)
682 {
683 for (e = bb->succ; e; e = e->succ_next)
684 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
685 e->probability = REG_BR_PROB_BASE / total;
686 else
687 e->probability = 0;
688 }
689 else
690 {
691 for (e = bb->succ; e; e = e->succ_next)
692 total ++;
693 for (e = bb->succ; e; e = e->succ_next)
694 e->probability = REG_BR_PROB_BASE / total;
695 }
696 if (bb->index >= 0
697 && any_condjump_p (bb->end)
698 && bb->succ->succ_next)
699 num_branches++, num_never_executed;
700 }
701 }
702
703 if (rtl_dump_file)
704 {
705 fprintf (rtl_dump_file, "%d branches\n", num_branches);
706 fprintf (rtl_dump_file, "%d branches never executed\n",
707 num_never_executed);
708 if (num_branches)
709 for (i = 0; i < 10; i++)
710 fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
711 (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
712 5 * i, 5 * i + 5);
713
714 total_num_branches += num_branches;
715 total_num_never_executed += num_never_executed;
716 for (i = 0; i < 20; i++)
717 total_hist_br_prob[i] += hist_br_prob[i];
718
719 fputc ('\n', rtl_dump_file);
720 fputc ('\n', rtl_dump_file);
721 }
722
723 free_aux_for_blocks ();
724 if (exec_counts)
725 free (exec_counts);
726 }
727
728 /* Compute checksum for the current function. */
729
730 #define CHSUM_HASH 500000003
731 #define CHSUM_SHIFT 2
732
733 static long
734 compute_checksum ()
735 {
736 long chsum = 0;
737 basic_block bb;
738
739 FOR_EACH_BB (bb)
740 {
741 edge e;
742
743 for (e = bb->succ; e; e = e->succ_next)
744 {
745 chsum = ((chsum << CHSUM_SHIFT) + (BB_TO_GCOV_INDEX (e->dest) + 1)) % CHSUM_HASH;
746 }
747
748 chsum = (chsum << CHSUM_SHIFT) % CHSUM_HASH;
749 }
750
751 return chsum;
752 }
753
754 /* Instrument and/or analyze program behavior based on program flow graph.
755 In either case, this function builds a flow graph for the function being
756 compiled. The flow graph is stored in BB_GRAPH.
757
758 When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
759 the flow graph that are needed to reconstruct the dynamic behavior of the
760 flow graph.
761
762 When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
763 information from a data file containing edge count information from previous
764 executions of the function being compiled. In this case, the flow graph is
765 annotated with actual execution counts, which are later propagated into the
766 rtl for optimization purposes.
767
768 Main entry point of this file. */
769
770 void
771 branch_prob ()
772 {
773 basic_block bb;
774 int i;
775 int num_edges, ignored_edges;
776 struct edge_list *el;
777 const char *name = IDENTIFIER_POINTER
778 (DECL_ASSEMBLER_NAME (current_function_decl));
779
780 profile_info.current_function_cfg_checksum = compute_checksum ();
781
782 if (rtl_dump_file)
783 fprintf (rtl_dump_file, "CFG checksum is %ld\n",
784 profile_info.current_function_cfg_checksum);
785
786 /* Start of a function. */
787 if (flag_test_coverage)
788 output_gcov_string (name, (long) -2);
789
790 total_num_times_called++;
791
792 flow_call_edges_add (NULL);
793 add_noreturn_fake_exit_edges ();
794
795 /* We can't handle cyclic regions constructed using abnormal edges.
796 To avoid these we replace every source of abnormal edge by a fake
797 edge from entry node and every destination by fake edge to exit.
798 This keeps graph acyclic and our calculation exact for all normal
799 edges except for exit and entrance ones.
800
801 We also add fake exit edges for each call and asm statement in the
802 basic, since it may not return. */
803
804 FOR_EACH_BB (bb)
805 {
806 int need_exit_edge = 0, need_entry_edge = 0;
807 int have_exit_edge = 0, have_entry_edge = 0;
808 rtx insn;
809 edge e;
810
811 /* Add fake edges from entry block to the call insns that may return
812 twice. The CFG is not quite correct then, as call insn plays more
813 role of CODE_LABEL, but for our purposes, everything should be OK,
814 as we never insert code to the beggining of basic block. */
815 for (insn = bb->head; insn != NEXT_INSN (bb->end);
816 insn = NEXT_INSN (insn))
817 {
818 if (GET_CODE (insn) == CALL_INSN
819 && find_reg_note (insn, REG_SETJMP, NULL))
820 {
821 if (GET_CODE (bb->head) == CODE_LABEL
822 || insn != NEXT_INSN (bb->head))
823 {
824 e = split_block (bb, PREV_INSN (insn));
825 make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
826 break;
827 }
828 else
829 {
830 /* We should not get abort here, as call to setjmp should not
831 be the very first instruction of function. */
832 if (bb == ENTRY_BLOCK_PTR)
833 abort ();
834 make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
835 }
836 }
837 }
838
839 for (e = bb->succ; e; e = e->succ_next)
840 {
841 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
842 && e->dest != EXIT_BLOCK_PTR)
843 need_exit_edge = 1;
844 if (e->dest == EXIT_BLOCK_PTR)
845 have_exit_edge = 1;
846 }
847 for (e = bb->pred; e; e = e->pred_next)
848 {
849 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
850 && e->src != ENTRY_BLOCK_PTR)
851 need_entry_edge = 1;
852 if (e->src == ENTRY_BLOCK_PTR)
853 have_entry_edge = 1;
854 }
855
856 if (need_exit_edge && !have_exit_edge)
857 {
858 if (rtl_dump_file)
859 fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n",
860 bb->index);
861 make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
862 }
863 if (need_entry_edge && !have_entry_edge)
864 {
865 if (rtl_dump_file)
866 fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n",
867 bb->index);
868 make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
869 }
870 }
871
872 el = create_edge_list ();
873 num_edges = NUM_EDGES (el);
874 alloc_aux_for_edges (sizeof (struct edge_info));
875
876 /* The basic blocks are expected to be numbered sequentially. */
877 compact_blocks ();
878
879 ignored_edges = 0;
880 for (i = 0 ; i < num_edges ; i++)
881 {
882 edge e = INDEX_EDGE (el, i);
883 e->count = 0;
884
885 /* Mark edges we've replaced by fake edges above as ignored. */
886 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
887 && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
888 {
889 EDGE_INFO (e)->ignore = 1;
890 ignored_edges++;
891 }
892 }
893
894 #ifdef ENABLE_CHECKING
895 verify_flow_info ();
896 #endif
897
898 /* Output line number information about each basic block for
899 GCOV utility. */
900 if (flag_test_coverage)
901 {
902 FOR_EACH_BB (bb)
903 {
904 rtx insn = bb->head;
905 static int ignore_next_note = 0;
906
907 /* We are looking for line number notes. Search backward before
908 basic block to find correct ones. */
909 insn = prev_nonnote_insn (insn);
910 if (!insn)
911 insn = get_insns ();
912 else
913 insn = NEXT_INSN (insn);
914
915 /* Output a zero to the .bb file to indicate that a new
916 block list is starting. */
917 __write_long (0, bb_file, 4);
918
919 while (insn != bb->end)
920 {
921 if (GET_CODE (insn) == NOTE)
922 {
923 /* Must ignore the line number notes that immediately
924 follow the end of an inline function to avoid counting
925 it twice. There is a note before the call, and one
926 after the call. */
927 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_REPEATED_LINE_NUMBER)
928 ignore_next_note = 1;
929 else if (NOTE_LINE_NUMBER (insn) > 0)
930 {
931 if (ignore_next_note)
932 ignore_next_note = 0;
933 else
934 {
935 /* If this is a new source file, then output the
936 file's name to the .bb file. */
937 if (! last_bb_file_name
938 || strcmp (NOTE_SOURCE_FILE (insn),
939 last_bb_file_name))
940 {
941 if (last_bb_file_name)
942 free (last_bb_file_name);
943 last_bb_file_name
944 = xstrdup (NOTE_SOURCE_FILE (insn));
945 output_gcov_string (NOTE_SOURCE_FILE (insn),
946 (long)-1);
947 }
948 /* Output the line number to the .bb file. Must be
949 done after the output_bb_profile_data() call, and
950 after the file name is written, to ensure that it
951 is correctly handled by gcov. */
952 __write_long (NOTE_LINE_NUMBER (insn), bb_file, 4);
953 }
954 }
955 }
956 insn = NEXT_INSN (insn);
957 }
958 }
959 __write_long (0, bb_file, 4);
960 }
961
962 /* Create spanning tree from basic block graph, mark each edge that is
963 on the spanning tree. We insert as many abnormal and critical edges
964 as possible to minimize number of edge splits necessary. */
965
966 find_spanning_tree (el);
967
968 /* Fake edges that are not on the tree will not be instrumented, so
969 mark them ignored. */
970 for (i = 0; i < num_edges; i++)
971 {
972 edge e = INDEX_EDGE (el, i);
973 struct edge_info *inf = EDGE_INFO (e);
974 if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
975 {
976 inf->ignore = 1;
977 ignored_edges++;
978 }
979 }
980
981 total_num_blocks += n_basic_blocks + 2;
982 if (rtl_dump_file)
983 fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);
984
985 total_num_edges += num_edges;
986 if (rtl_dump_file)
987 fprintf (rtl_dump_file, "%d edges\n", num_edges);
988
989 total_num_edges_ignored += ignored_edges;
990 if (rtl_dump_file)
991 fprintf (rtl_dump_file, "%d ignored edges\n", ignored_edges);
992
993 /* Create a .bbg file from which gcov can reconstruct the basic block
994 graph. First output the number of basic blocks, and then for every
995 edge output the source and target basic block numbers.
996 NOTE: The format of this file must be compatible with gcov. */
997
998 if (flag_test_coverage)
999 {
1000 int flag_bits;
1001
1002 __write_gcov_string (name, strlen (name), bbg_file, -1);
1003
1004 /* write checksum. */
1005 __write_long (profile_info.current_function_cfg_checksum, bbg_file, 4);
1006
1007 /* The plus 2 stands for entry and exit block. */
1008 __write_long (n_basic_blocks + 2, bbg_file, 4);
1009 __write_long (num_edges - ignored_edges + 1, bbg_file, 4);
1010
1011 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
1012 {
1013 edge e;
1014 long count = 0;
1015
1016 for (e = bb->succ; e; e = e->succ_next)
1017 if (!EDGE_INFO (e)->ignore)
1018 count++;
1019 __write_long (count, bbg_file, 4);
1020
1021 for (e = bb->succ; e; e = e->succ_next)
1022 {
1023 struct edge_info *i = EDGE_INFO (e);
1024 if (!i->ignore)
1025 {
1026 flag_bits = 0;
1027 if (i->on_tree)
1028 flag_bits |= 0x1;
1029 if (e->flags & EDGE_FAKE)
1030 flag_bits |= 0x2;
1031 if (e->flags & EDGE_FALLTHRU)
1032 flag_bits |= 0x4;
1033
1034 __write_long (BB_TO_GCOV_INDEX (e->dest), bbg_file, 4);
1035 __write_long (flag_bits, bbg_file, 4);
1036 }
1037 }
1038 }
1039 /* Emit fake loopback edge for EXIT block to maintain compatibility with
1040 old gcov format. */
1041 __write_long (1, bbg_file, 4);
1042 __write_long (0, bbg_file, 4);
1043 __write_long (0x1, bbg_file, 4);
1044
1045 /* Emit a -1 to separate the list of all edges from the list of
1046 loop back edges that follows. */
1047 __write_long (-1, bbg_file, 4);
1048 }
1049
1050 if (flag_branch_probabilities)
1051 compute_branch_probabilities ();
1052
1053 /* For each edge not on the spanning tree, add counting code as rtl. */
1054
1055 if (profile_arc_flag)
1056 {
1057 instrument_edges (el);
1058 allocate_reg_info (max_reg_num (), FALSE, FALSE);
1059 }
1060
1061 remove_fake_edges ();
1062 /* Re-merge split basic blocks and the mess introduced by
1063 insert_insn_on_edge. */
1064 cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
1065 if (rtl_dump_file)
1066 dump_flow_info (rtl_dump_file);
1067
1068 free_aux_for_edges ();
1069 free_edge_list (el);
1070 }
1071 \f
1072 /* Union find algorithm implementation for the basic blocks using
1073 aux fields. */
1074
1075 static basic_block
1076 find_group (bb)
1077 basic_block bb;
1078 {
1079 basic_block group = bb, bb1;
1080
1081 while ((basic_block) group->aux != group)
1082 group = (basic_block) group->aux;
1083
1084 /* Compress path. */
1085 while ((basic_block) bb->aux != group)
1086 {
1087 bb1 = (basic_block) bb->aux;
1088 bb->aux = (void *) group;
1089 bb = bb1;
1090 }
1091 return group;
1092 }
1093
1094 static void
1095 union_groups (bb1, bb2)
1096 basic_block bb1, bb2;
1097 {
1098 basic_block bb1g = find_group (bb1);
1099 basic_block bb2g = find_group (bb2);
1100
1101 /* ??? I don't have a place for the rank field. OK. Lets go w/o it,
1102 this code is unlikely going to be performance problem anyway. */
1103 if (bb1g == bb2g)
1104 abort ();
1105
1106 bb1g->aux = bb2g;
1107 }
1108 \f
1109 /* This function searches all of the edges in the program flow graph, and puts
1110 as many bad edges as possible onto the spanning tree. Bad edges include
1111 abnormals edges, which can't be instrumented at the moment. Since it is
1112 possible for fake edges to form an cycle, we will have to develop some
1113 better way in the future. Also put critical edges to the tree, since they
1114 are more expensive to instrument. */
1115
1116 static void
1117 find_spanning_tree (el)
1118 struct edge_list *el;
1119 {
1120 int i;
1121 int num_edges = NUM_EDGES (el);
1122 basic_block bb;
1123
1124 /* We use aux field for standard union-find algorithm. */
1125 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1126 bb->aux = bb;
1127
1128 /* Add fake edge exit to entry we can't instrument. */
1129 union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
1130
1131 /* First add all abnormal edges to the tree unless they form an cycle. Also
1132 add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
1133 setting return value from function. */
1134 for (i = 0; i < num_edges; i++)
1135 {
1136 edge e = INDEX_EDGE (el, i);
1137 if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
1138 || e->dest == EXIT_BLOCK_PTR
1139 )
1140 && !EDGE_INFO (e)->ignore
1141 && (find_group (e->src) != find_group (e->dest)))
1142 {
1143 if (rtl_dump_file)
1144 fprintf (rtl_dump_file, "Abnormal edge %d to %d put to tree\n",
1145 e->src->index, e->dest->index);
1146 EDGE_INFO (e)->on_tree = 1;
1147 union_groups (e->src, e->dest);
1148 }
1149 }
1150
1151 /* Now insert all critical edges to the tree unless they form an cycle. */
1152 for (i = 0; i < num_edges; i++)
1153 {
1154 edge e = INDEX_EDGE (el, i);
1155 if ((EDGE_CRITICAL_P (e))
1156 && !EDGE_INFO (e)->ignore
1157 && (find_group (e->src) != find_group (e->dest)))
1158 {
1159 if (rtl_dump_file)
1160 fprintf (rtl_dump_file, "Critical edge %d to %d put to tree\n",
1161 e->src->index, e->dest->index);
1162 EDGE_INFO (e)->on_tree = 1;
1163 union_groups (e->src, e->dest);
1164 }
1165 }
1166
1167 /* And now the rest. */
1168 for (i = 0; i < num_edges; i++)
1169 {
1170 edge e = INDEX_EDGE (el, i);
1171 if (find_group (e->src) != find_group (e->dest)
1172 && !EDGE_INFO (e)->ignore)
1173 {
1174 if (rtl_dump_file)
1175 fprintf (rtl_dump_file, "Normal edge %d to %d put to tree\n",
1176 e->src->index, e->dest->index);
1177 EDGE_INFO (e)->on_tree = 1;
1178 union_groups (e->src, e->dest);
1179 }
1180 }
1181
1182 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1183 bb->aux = NULL;
1184 }
1185 \f
1186 /* Perform file-level initialization for branch-prob processing. */
1187
1188 void
1189 init_branch_prob (filename)
1190 const char *filename;
1191 {
1192 int len = strlen (filename);
1193 int i;
1194
1195 if (flag_test_coverage)
1196 {
1197 char *data_file, *bbg_file_name;
1198
1199 /* Open an output file for the basic block/line number map. */
1200 data_file = (char *) alloca (len + 4);
1201 strcpy (data_file, filename);
1202 strcat (data_file, ".bb");
1203 if ((bb_file = fopen (data_file, "wb")) == 0)
1204 fatal_io_error ("can't open %s", data_file);
1205
1206 /* Open an output file for the program flow graph. */
1207 bbg_file_name = (char *) alloca (len + 5);
1208 strcpy (bbg_file_name, filename);
1209 strcat (bbg_file_name, ".bbg");
1210 if ((bbg_file = fopen (bbg_file_name, "wb")) == 0)
1211 fatal_io_error ("can't open %s", bbg_file_name);
1212
1213 /* Initialize to zero, to ensure that the first file name will be
1214 written to the .bb file. */
1215 last_bb_file_name = 0;
1216 }
1217
1218 da_file_name = (char *) xmalloc (len + 4);
1219 strcpy (da_file_name, filename);
1220 strcat (da_file_name, ".da");
1221
1222 if (flag_branch_probabilities)
1223 {
1224 da_file = fopen (da_file_name, "rb");
1225 if (!da_file)
1226 warning ("file %s not found, execution counts assumed to be zero",
1227 da_file_name);
1228 }
1229
1230 if (profile_arc_flag)
1231 init_edge_profiler ();
1232
1233 total_num_blocks = 0;
1234 total_num_edges = 0;
1235 total_num_edges_ignored = 0;
1236 total_num_edges_instrumented = 0;
1237 total_num_blocks_created = 0;
1238 total_num_passes = 0;
1239 total_num_times_called = 0;
1240 total_num_branches = 0;
1241 total_num_never_executed = 0;
1242 for (i = 0; i < 20; i++)
1243 total_hist_br_prob[i] = 0;
1244 }
1245
1246 /* Performs file-level cleanup after branch-prob processing
1247 is completed. */
1248
1249 void
1250 end_branch_prob ()
1251 {
1252 if (flag_test_coverage)
1253 {
1254 fclose (bb_file);
1255 fclose (bbg_file);
1256 unlink (da_file_name);
1257 }
1258
1259 if (flag_branch_probabilities && da_file)
1260 fclose (da_file);
1261
1262 if (rtl_dump_file)
1263 {
1264 fprintf (rtl_dump_file, "\n");
1265 fprintf (rtl_dump_file, "Total number of blocks: %d\n",
1266 total_num_blocks);
1267 fprintf (rtl_dump_file, "Total number of edges: %d\n", total_num_edges);
1268 fprintf (rtl_dump_file, "Total number of ignored edges: %d\n",
1269 total_num_edges_ignored);
1270 fprintf (rtl_dump_file, "Total number of instrumented edges: %d\n",
1271 total_num_edges_instrumented);
1272 fprintf (rtl_dump_file, "Total number of blocks created: %d\n",
1273 total_num_blocks_created);
1274 fprintf (rtl_dump_file, "Total number of graph solution passes: %d\n",
1275 total_num_passes);
1276 if (total_num_times_called != 0)
1277 fprintf (rtl_dump_file, "Average number of graph solution passes: %d\n",
1278 (total_num_passes + (total_num_times_called >> 1))
1279 / total_num_times_called);
1280 fprintf (rtl_dump_file, "Total number of branches: %d\n",
1281 total_num_branches);
1282 fprintf (rtl_dump_file, "Total number of branches never executed: %d\n",
1283 total_num_never_executed);
1284 if (total_num_branches)
1285 {
1286 int i;
1287
1288 for (i = 0; i < 10; i++)
1289 fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
1290 (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
1291 / total_num_branches, 5*i, 5*i+5);
1292 }
1293 }
1294 }
1295 \f
1296 /* The label used by the edge profiling code. */
1297
1298 static GTY(()) rtx profiler_label;
1299
1300 /* Initialize the profiler_label. */
1301
1302 static void
1303 init_edge_profiler ()
1304 {
1305 /* Generate and save a copy of this so it can be shared. */
1306 char buf[20];
1307 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
1308 profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1309 }
1310
1311 /* Output instructions as RTL to increment the edge execution count. */
1312
1313 static rtx
1314 gen_edge_profiler (edgeno)
1315 int edgeno;
1316 {
1317 enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1318 rtx mem_ref, tmp;
1319 rtx sequence;
1320
1321 start_sequence ();
1322
1323 tmp = force_reg (Pmode, profiler_label);
1324 tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
1325 mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
1326
1327 set_mem_alias_set (mem_ref, new_alias_set ());
1328
1329 tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
1330 mem_ref, 0, OPTAB_WIDEN);
1331
1332 if (tmp != mem_ref)
1333 emit_move_insn (copy_rtx (mem_ref), tmp);
1334
1335 sequence = get_insns ();
1336 end_sequence ();
1337 return sequence;
1338 }
1339
1340 /* Output code for a constructor that will invoke __bb_init_func, if
1341 this has not already been done. */
1342
1343 void
1344 output_func_start_profiler ()
1345 {
1346 tree fnname, fndecl;
1347 char *name;
1348 char buf[20];
1349 const char *cfnname;
1350 rtx table_address;
1351 enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1352 int save_flag_inline_functions = flag_inline_functions;
1353
1354 /* It's either already been output, or we don't need it because we're
1355 not doing profile-edges. */
1356 if (! need_func_profiler)
1357 return;
1358
1359 need_func_profiler = 0;
1360
1361 /* Synthesize a constructor function to invoke __bb_init_func with a
1362 pointer to this object file's profile block. */
1363
1364 /* Try and make a unique name given the "file function name".
1365
1366 And no, I don't like this either. */
1367
1368 fnname = get_file_function_name ('I');
1369 cfnname = IDENTIFIER_POINTER (fnname);
1370 name = concat (cfnname, "GCOV", NULL);
1371 fnname = get_identifier (name);
1372 free (name);
1373
1374 fndecl = build_decl (FUNCTION_DECL, fnname,
1375 build_function_type (void_type_node, NULL_TREE));
1376 DECL_EXTERNAL (fndecl) = 0;
1377
1378 /* It can be a static function as long as collect2 does not have
1379 to scan the object file to find its ctor/dtor routine. */
1380 TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;
1381
1382 TREE_USED (fndecl) = 1;
1383
1384 DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1385
1386 fndecl = (*lang_hooks.decls.pushdecl) (fndecl);
1387 rest_of_decl_compilation (fndecl, 0, 1, 0);
1388 announce_function (fndecl);
1389 current_function_decl = fndecl;
1390 DECL_INITIAL (fndecl) = error_mark_node;
1391 make_decl_rtl (fndecl, NULL);
1392 init_function_start (fndecl, input_filename, lineno);
1393 (*lang_hooks.decls.pushlevel) (0);
1394 expand_function_start (fndecl, 0);
1395 cfun->arc_profile = 0;
1396
1397 /* Actually generate the code to call __bb_init_func. */
1398 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 0);
1399 table_address = force_reg (Pmode,
1400 gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
1401 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__bb_init_func"), LCT_NORMAL,
1402 mode, 1, table_address, Pmode);
1403
1404 expand_function_end (input_filename, lineno, 0);
1405 (*lang_hooks.decls.poplevel) (1, 0, 1);
1406
1407 /* Since fndecl isn't in the list of globals, it would never be emitted
1408 when it's considered to be 'safe' for inlining, so turn off
1409 flag_inline_functions. */
1410 flag_inline_functions = 0;
1411
1412 rest_of_compilation (fndecl);
1413
1414 /* Reset flag_inline_functions to its original value. */
1415 flag_inline_functions = save_flag_inline_functions;
1416
1417 if (! quiet_flag)
1418 fflush (asm_out_file);
1419 current_function_decl = NULL_TREE;
1420
1421 if (targetm.have_ctors_dtors)
1422 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
1423 DEFAULT_INIT_PRIORITY);
1424 }
1425
1426 #include "gt-profile.h"