]>
Commit | Line | Data |
---|---|---|
6de9cd9a DN |
1 | /* Calculate branch probabilities, and basic block execution counts. |
2 | Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, | |
3 | 2000, 2001, 2002, 2003, 2004 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 | Converted to use trees by Dale Johannesen, Apple Computer. | |
8 | ||
9 | This file is part of GCC. | |
10 | ||
11 | GCC is free software; you can redistribute it and/or modify it under | |
12 | the terms of the GNU General Public License as published by the Free | |
13 | Software Foundation; either version 2, or (at your option) any later | |
14 | version. | |
15 | ||
16 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
17 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
18 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
19 | for more details. | |
20 | ||
21 | You should have received a copy of the GNU General Public License | |
22 | along with GCC; see the file COPYING. If not, write to the Free | |
23 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
24 | 02111-1307, USA. */ | |
25 | ||
26 | /* Generate basic block profile instrumentation and auxiliary files. | |
27 | Profile generation is optimized, so that not all arcs in the basic | |
28 | block graph need instrumenting. First, the BB graph is closed with | |
29 | one entry (function start), and one exit (function exit). Any | |
30 | ABNORMAL_EDGE cannot be instrumented (because there is no control | |
31 | path to place the code). We close the graph by inserting fake | |
32 | EDGE_FAKE edges to the EXIT_BLOCK, from the sources of abnormal | |
33 | edges that do not go to the exit_block. We ignore such abnormal | |
34 | edges. Naturally these fake edges are never directly traversed, | |
35 | and so *cannot* be directly instrumented. Some other graph | |
36 | massaging is done. To optimize the instrumentation we generate the | |
37 | BB minimal span tree, only edges that are not on the span tree | |
38 | (plus the entry point) need instrumenting. From that information | |
39 | all other edge counts can be deduced. By construction all fake | |
40 | edges must be on the spanning tree. We also attempt to place | |
41 | EDGE_CRITICAL edges on the spanning tree. | |
42 | ||
43 | The auxiliary file generated is <dumpbase>.bbg. The format is | |
44 | described in full in gcov-io.h. */ | |
45 | ||
46 | /* ??? Register allocation should use basic block execution counts to | |
47 | give preference to the most commonly executed blocks. */ | |
48 | ||
49 | /* ??? Should calculate branch probabilities before instrumenting code, since | |
50 | then we can use arc counts to help decide which arcs to instrument. */ | |
51 | ||
52 | #include "config.h" | |
53 | #include "system.h" | |
54 | #include "coretypes.h" | |
55 | #include "tm.h" | |
56 | #include "rtl.h" | |
57 | #include "flags.h" | |
58 | #include "output.h" | |
59 | #include "regs.h" | |
60 | #include "expr.h" | |
61 | #include "function.h" | |
62 | #include "toplev.h" | |
63 | #include "coverage.h" | |
64 | #include "tree.h" | |
65 | #include "tree-flow.h" | |
66 | #include "tree-dump.h" | |
67 | #include "tree-pass.h" | |
68 | #include "timevar.h" | |
69 | #include "value-prof.h" | |
70 | ||
71 | \f | |
f3df9541 AK |
72 | |
73 | /* Do initialization work for the edge profiler. */ | |
74 | ||
75 | static void | |
76 | tree_init_edge_profiler (void) | |
77 | { | |
78 | } | |
79 | ||
6de9cd9a DN |
80 | /* Output instructions as GIMPLE trees to increment the edge |
81 | execution count, and insert them on E. We rely on | |
82 | bsi_insert_on_edge to preserve the order. */ | |
83 | ||
84 | static void | |
85 | tree_gen_edge_profiler (int edgeno, edge e) | |
86 | { | |
87 | tree tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF"); | |
88 | tree tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF"); | |
89 | tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); | |
90 | tree stmt1 = build (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref); | |
91 | tree stmt2 = build (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2, | |
92 | build (PLUS_EXPR, GCOV_TYPE_NODE, | |
93 | tmp1, integer_one_node)); | |
94 | tree stmt3 = build (MODIFY_EXPR, GCOV_TYPE_NODE, ref, tmp2); | |
95 | bsi_insert_on_edge (e, stmt1); | |
96 | bsi_insert_on_edge (e, stmt2); | |
97 | bsi_insert_on_edge (e, stmt3); | |
98 | } | |
99 | ||
100 | /* Output instructions as GIMPLE trees to increment the interval histogram | |
101 | counter. VALUE is the expression whose value is profiled. TAG is the | |
102 | tag of the section for counters, BASE is offset of the counter position. */ | |
103 | ||
104 | static void | |
6d9901e7 | 105 | tree_gen_interval_profiler (histogram_value value ATTRIBUTE_UNUSED, |
6de9cd9a DN |
106 | unsigned tag ATTRIBUTE_UNUSED, |
107 | unsigned base ATTRIBUTE_UNUSED) | |
108 | { | |
109 | /* FIXME implement this. */ | |
1e128c5f GB |
110 | #ifdef ENABLE_CHECKING |
111 | internal_error ("unimplemented functionality"); | |
112 | #endif | |
113 | gcc_unreachable (); | |
6de9cd9a DN |
114 | } |
115 | ||
116 | /* Output instructions as GIMPLE trees to increment the power of two histogram | |
117 | counter. VALUE is the expression whose value is profiled. TAG is the tag | |
118 | of the section for counters, BASE is offset of the counter position. */ | |
119 | ||
120 | static void | |
6d9901e7 | 121 | tree_gen_pow2_profiler (histogram_value value ATTRIBUTE_UNUSED, |
6de9cd9a DN |
122 | unsigned tag ATTRIBUTE_UNUSED, |
123 | unsigned base ATTRIBUTE_UNUSED) | |
124 | { | |
125 | /* FIXME implement this. */ | |
1e128c5f GB |
126 | #ifdef ENABLE_CHECKING |
127 | internal_error ("unimplemented functionality"); | |
128 | #endif | |
129 | gcc_unreachable (); | |
6de9cd9a DN |
130 | } |
131 | ||
132 | /* Output instructions as GIMPLE trees for code to find the most common value. | |
133 | VALUE is the expression whose value is profiled. TAG is the tag of the | |
134 | section for counters, BASE is offset of the counter position. */ | |
135 | ||
136 | static void | |
6d9901e7 | 137 | tree_gen_one_value_profiler (histogram_value value ATTRIBUTE_UNUSED, |
6de9cd9a DN |
138 | unsigned tag ATTRIBUTE_UNUSED, |
139 | unsigned base ATTRIBUTE_UNUSED) | |
140 | { | |
141 | /* FIXME implement this. */ | |
1e128c5f GB |
142 | #ifdef ENABLE_CHECKING |
143 | internal_error ("unimplemented functionality"); | |
144 | #endif | |
145 | gcc_unreachable (); | |
6de9cd9a DN |
146 | } |
147 | ||
148 | /* Output instructions as GIMPLE trees for code to find the most common value | |
149 | of a difference between two evaluations of an expression. | |
150 | VALUE is the expression whose value is profiled. TAG is the tag of the | |
151 | section for counters, BASE is offset of the counter position. */ | |
152 | ||
153 | static void | |
6d9901e7 | 154 | tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, |
6de9cd9a DN |
155 | unsigned tag ATTRIBUTE_UNUSED, |
156 | unsigned base ATTRIBUTE_UNUSED) | |
157 | { | |
158 | /* FIXME implement this. */ | |
1e128c5f GB |
159 | #ifdef ENABLE_CHECKING |
160 | internal_error ("unimplemented functionality"); | |
161 | #endif | |
162 | gcc_unreachable (); | |
6de9cd9a DN |
163 | } |
164 | ||
165 | /* Return 1 if tree-based profiling is in effect, else 0. | |
166 | If it is, set up hooks for tree-based profiling. | |
167 | Gate for pass_tree_profile. */ | |
168 | ||
878f99d2 JH |
169 | static bool do_tree_profiling (void) |
170 | { | |
bbd236a1 JH |
171 | if (flag_tree_based_profiling |
172 | && (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)) | |
6de9cd9a DN |
173 | { |
174 | tree_register_profile_hooks (); | |
175 | tree_register_value_prof_hooks (); | |
bbd236a1 | 176 | return true; |
6de9cd9a | 177 | } |
bbd236a1 | 178 | return false; |
6de9cd9a DN |
179 | } |
180 | ||
181 | /* Return the file on which profile dump output goes, if any. */ | |
182 | ||
183 | static FILE *tree_profile_dump_file (void) { | |
184 | return dump_file; | |
185 | } | |
186 | ||
187 | struct tree_opt_pass pass_tree_profile = | |
188 | { | |
189 | "tree_profile", /* name */ | |
190 | do_tree_profiling, /* gate */ | |
191 | branch_prob, /* execute */ | |
192 | NULL, /* sub */ | |
193 | NULL, /* next */ | |
194 | 0, /* static_pass_number */ | |
195 | TV_BRANCH_PROB, /* tv_id */ | |
196 | PROP_gimple_leh | PROP_cfg, /* properties_required */ | |
197 | PROP_gimple_leh | PROP_cfg, /* properties_provided */ | |
198 | 0, /* properties_destroyed */ | |
199 | 0, /* todo_flags_start */ | |
9f8628ba PB |
200 | TODO_verify_stmts, /* todo_flags_finish */ |
201 | 0 /* letter */ | |
6de9cd9a DN |
202 | }; |
203 | ||
204 | struct profile_hooks tree_profile_hooks = | |
205 | { | |
f3df9541 | 206 | tree_init_edge_profiler, /* init_edge_profiler */ |
6de9cd9a DN |
207 | tree_gen_edge_profiler, /* gen_edge_profiler */ |
208 | tree_gen_interval_profiler, /* gen_interval_profiler */ | |
209 | tree_gen_pow2_profiler, /* gen_pow2_profiler */ | |
210 | tree_gen_one_value_profiler, /* gen_one_value_profiler */ | |
211 | tree_gen_const_delta_profiler,/* gen_const_delta_profiler */ | |
212 | tree_profile_dump_file /* profile_dump_file */ | |
213 | }; |