00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "config.h"
00052 #include "system.h"
00053 #include "coretypes.h"
00054 #include "tm.h"
00055 #include "rtl.h"
00056 #include "flags.h"
00057 #include "output.h"
00058 #include "regs.h"
00059 #include "expr.h"
00060 #include "function.h"
00061 #include "toplev.h"
00062 #include "coverage.h"
00063 #include "value-prof.h"
00064 #include "tree.h"
00065 #include "ggc.h"
00066
00067
00068
00069 static void
00070 rtl_init_edge_profiler (void)
00071 {
00072
00073
00074 life_analysis (NULL, 0);
00075 }
00076
00077
00078
00079 static void
00080 rtl_gen_edge_profiler (int edgeno, edge e)
00081 {
00082 rtx ref = rtl_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
00083 rtx tmp;
00084 enum machine_mode mode = GET_MODE (ref);
00085 rtx sequence;
00086
00087 start_sequence ();
00088 ref = validize_mem (ref);
00089
00090 tmp = expand_simple_binop (mode, PLUS, ref, const1_rtx,
00091 ref, 0, OPTAB_WIDEN);
00092
00093 if (tmp != ref)
00094 emit_move_insn (copy_rtx (ref), tmp);
00095
00096 sequence = get_insns ();
00097 end_sequence ();
00098 safe_insert_insn_on_edge (sequence, e);
00099 rebuild_jump_labels (e->insns.r);
00100 }
00101
00102
00103
00104
00105
00106 static void
00107 rtl_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
00108 {
00109 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
00110 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
00111 rtx mem_ref, tmp, tmp1, mr, val;
00112 rtx sequence;
00113 rtx more_label = gen_label_rtx ();
00114 rtx less_label = gen_label_rtx ();
00115 rtx end_of_code_label = gen_label_rtx ();
00116 int per_counter = gcov_size / BITS_PER_UNIT;
00117 edge e = split_block (BLOCK_FOR_INSN ((rtx)value->insn),
00118 PREV_INSN ((rtx)value->insn));
00119
00120 start_sequence ();
00121
00122 if (value->seq)
00123 emit_insn (value->seq);
00124
00125 mr = gen_reg_rtx (Pmode);
00126
00127 tmp = rtl_coverage_counter_ref (tag, base);
00128 tmp = force_reg (Pmode, XEXP (tmp, 0));
00129
00130 val = expand_simple_binop (value->mode, MINUS,
00131 copy_rtx (value->value),
00132 GEN_INT (value->hdata.intvl.int_start),
00133 NULL_RTX, 0, OPTAB_WIDEN);
00134
00135 if (value->hdata.intvl.may_be_more)
00136 do_compare_rtx_and_jump (copy_rtx (val), GEN_INT (value->hdata.intvl.steps),
00137 GE, 0, value->mode, NULL_RTX, NULL_RTX, more_label);
00138 if (value->hdata.intvl.may_be_less)
00139 do_compare_rtx_and_jump (copy_rtx (val), const0_rtx, LT, 0, value->mode,
00140 NULL_RTX, NULL_RTX, less_label);
00141
00142
00143 tmp1 = expand_simple_binop (value->mode, MULT,
00144 copy_rtx (val), GEN_INT (per_counter),
00145 NULL_RTX, 0, OPTAB_WIDEN);
00146 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp), tmp1, mr,
00147 0, OPTAB_WIDEN);
00148 if (tmp1 != mr)
00149 emit_move_insn (copy_rtx (mr), tmp1);
00150
00151 if (value->hdata.intvl.may_be_more
00152 || value->hdata.intvl.may_be_less)
00153 {
00154 emit_jump_insn (gen_jump (end_of_code_label));
00155 emit_barrier ();
00156 }
00157
00158
00159 if (value->hdata.intvl.may_be_more)
00160 {
00161 emit_label (more_label);
00162 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
00163 GEN_INT (per_counter * value->hdata.intvl.steps),
00164 mr, 0, OPTAB_WIDEN);
00165 if (tmp1 != mr)
00166 emit_move_insn (copy_rtx (mr), tmp1);
00167 if (value->hdata.intvl.may_be_less)
00168 {
00169 emit_jump_insn (gen_jump (end_of_code_label));
00170 emit_barrier ();
00171 }
00172 }
00173
00174
00175 if (value->hdata.intvl.may_be_less)
00176 {
00177 emit_label (less_label);
00178 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
00179 GEN_INT (per_counter * (value->hdata.intvl.steps
00180 + (value->hdata.intvl.may_be_more ? 1 : 0))),
00181 mr, 0, OPTAB_WIDEN);
00182 if (tmp1 != mr)
00183 emit_move_insn (copy_rtx (mr), tmp1);
00184 }
00185
00186 if (value->hdata.intvl.may_be_more
00187 || value->hdata.intvl.may_be_less)
00188 emit_label (end_of_code_label);
00189
00190 mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
00191
00192 tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
00193 mem_ref, 0, OPTAB_WIDEN);
00194
00195 if (tmp != mem_ref)
00196 emit_move_insn (copy_rtx (mem_ref), tmp);
00197
00198 sequence = get_insns ();
00199 end_sequence ();
00200 rebuild_jump_labels (sequence);
00201 safe_insert_insn_on_edge (sequence, e);
00202 }
00203
00204
00205
00206
00207
00208 static void
00209 rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
00210 {
00211 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
00212 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
00213 rtx mem_ref, tmp, mr, uval;
00214 rtx sequence;
00215 rtx end_of_code_label = gen_label_rtx ();
00216 rtx loop_label = gen_label_rtx ();
00217 int per_counter = gcov_size / BITS_PER_UNIT;
00218 edge e = split_block (BLOCK_FOR_INSN ((rtx)value->insn),
00219 PREV_INSN ((rtx)value->insn));
00220
00221 start_sequence ();
00222
00223 if (value->seq)
00224 emit_insn (value->seq);
00225
00226 mr = gen_reg_rtx (Pmode);
00227 tmp = rtl_coverage_counter_ref (tag, base);
00228 tmp = force_reg (Pmode, XEXP (tmp, 0));
00229 emit_move_insn (mr, tmp);
00230
00231 uval = gen_reg_rtx (value->mode);
00232 emit_move_insn (uval, copy_rtx (value->value));
00233
00234
00235 if (value->hdata.pow2.may_be_other)
00236 {
00237 do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->mode,
00238 NULL_RTX, NULL_RTX, end_of_code_label);
00239 tmp = expand_simple_binop (value->mode, PLUS, copy_rtx (uval),
00240 constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
00241 tmp = expand_simple_binop (value->mode, AND, copy_rtx (uval), tmp,
00242 NULL_RTX, 0, OPTAB_WIDEN);
00243 do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->mode, NULL_RTX,
00244 NULL_RTX, end_of_code_label);
00245 }
00246
00247
00248 emit_label (loop_label);
00249
00250 tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter), mr, 0, OPTAB_WIDEN);
00251 if (tmp != mr)
00252 emit_move_insn (copy_rtx (mr), tmp);
00253
00254 tmp = expand_simple_binop (value->mode, ASHIFTRT, copy_rtx (uval), const1_rtx,
00255 uval, 0, OPTAB_WIDEN);
00256 if (tmp != uval)
00257 emit_move_insn (copy_rtx (uval), tmp);
00258
00259 do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, NE, 0, value->mode,
00260 NULL_RTX, NULL_RTX, loop_label);
00261
00262
00263 emit_label (end_of_code_label);
00264
00265 mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
00266
00267 tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
00268 mem_ref, 0, OPTAB_WIDEN);
00269
00270 if (tmp != mem_ref)
00271 emit_move_insn (copy_rtx (mem_ref), tmp);
00272
00273 sequence = get_insns ();
00274 end_sequence ();
00275 rebuild_jump_labels (sequence);
00276 safe_insert_insn_on_edge (sequence, e);
00277 }
00278
00279
00280
00281
00282
00283 static rtx
00284 rtl_gen_one_value_profiler_no_edge_manipulation (histogram_value value,
00285 unsigned tag, unsigned base)
00286 {
00287 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
00288 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
00289 rtx stored_value_ref, counter_ref, all_ref, stored_value, counter, all;
00290 rtx tmp, uval;
00291 rtx sequence;
00292 rtx same_label = gen_label_rtx ();
00293 rtx zero_label = gen_label_rtx ();
00294 rtx end_of_code_label = gen_label_rtx ();
00295
00296 start_sequence ();
00297
00298 if (value->seq)
00299 emit_insn (value->seq);
00300
00301 stored_value_ref = rtl_coverage_counter_ref (tag, base);
00302 counter_ref = rtl_coverage_counter_ref (tag, base + 1);
00303 all_ref = rtl_coverage_counter_ref (tag, base + 2);
00304 stored_value = validize_mem (stored_value_ref);
00305 counter = validize_mem (counter_ref);
00306 all = validize_mem (all_ref);
00307
00308 uval = gen_reg_rtx (mode);
00309 convert_move (uval, copy_rtx (value->value), 0);
00310
00311
00312 do_compare_rtx_and_jump (copy_rtx (uval), copy_rtx (stored_value), EQ,
00313 0, mode, NULL_RTX, NULL_RTX, same_label);
00314
00315
00316 do_compare_rtx_and_jump (copy_rtx (counter), const0_rtx, EQ, 0, mode,
00317 NULL_RTX, NULL_RTX, zero_label);
00318
00319
00320 tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), constm1_rtx,
00321 counter, 0, OPTAB_WIDEN);
00322
00323 if (tmp != counter)
00324 emit_move_insn (copy_rtx (counter), tmp);
00325
00326 emit_jump_insn (gen_jump (end_of_code_label));
00327 emit_barrier ();
00328
00329 emit_label (zero_label);
00330
00331 emit_move_insn (copy_rtx (stored_value), copy_rtx (uval));
00332
00333 emit_label (same_label);
00334
00335 tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), const1_rtx,
00336 counter, 0, OPTAB_WIDEN);
00337
00338 if (tmp != counter)
00339 emit_move_insn (copy_rtx (counter), tmp);
00340
00341 emit_label (end_of_code_label);
00342
00343
00344
00345
00346
00347
00348 tmp = expand_simple_binop (mode, PLUS, copy_rtx (all), const1_rtx,
00349 all, 0, OPTAB_WIDEN);
00350
00351 if (tmp != all)
00352 emit_move_insn (copy_rtx (all), tmp);
00353 sequence = get_insns ();
00354 end_sequence ();
00355 return sequence;
00356 }
00357
00358
00359
00360
00361
00362 static void
00363 rtl_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
00364 {
00365 edge e = split_block (BLOCK_FOR_INSN ((rtx)value->insn),
00366 PREV_INSN ((rtx)value->insn));
00367 rtx sequence = rtl_gen_one_value_profiler_no_edge_manipulation (value,
00368 tag, base);
00369 rebuild_jump_labels (sequence);
00370 safe_insert_insn_on_edge (sequence, e);
00371 }
00372
00373
00374
00375
00376
00377
00378 static void
00379 rtl_gen_const_delta_profiler (histogram_value value, unsigned tag, unsigned base)
00380 {
00381 histogram_value one_value_delta;
00382 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
00383 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
00384 rtx stored_value_ref, stored_value, tmp, uval;
00385 rtx sequence;
00386 edge e = split_block (BLOCK_FOR_INSN ((rtx)value->insn),
00387 PREV_INSN ((rtx)value->insn));
00388
00389 start_sequence ();
00390
00391 if (value->seq)
00392 emit_insn (value->seq);
00393
00394 stored_value_ref = rtl_coverage_counter_ref (tag, base);
00395 stored_value = validize_mem (stored_value_ref);
00396
00397 uval = gen_reg_rtx (mode);
00398 convert_move (uval, copy_rtx (value->value), 0);
00399 tmp = expand_simple_binop (mode, MINUS,
00400 copy_rtx (uval), copy_rtx (stored_value),
00401 NULL_RTX, 0, OPTAB_WIDEN);
00402
00403 one_value_delta = ggc_alloc (sizeof (*one_value_delta));
00404 one_value_delta->value = tmp;
00405 one_value_delta->mode = mode;
00406 one_value_delta->seq = NULL_RTX;
00407 one_value_delta->insn = value->insn;
00408 one_value_delta->type = HIST_TYPE_SINGLE_VALUE;
00409 emit_insn (rtl_gen_one_value_profiler_no_edge_manipulation (one_value_delta,
00410 tag, base + 1));
00411 emit_move_insn (copy_rtx (stored_value), uval);
00412 sequence = get_insns ();
00413 end_sequence ();
00414 rebuild_jump_labels (sequence);
00415 safe_insert_insn_on_edge (sequence, e);
00416 }
00417
00418
00419
00420 static FILE *rtl_profile_dump_file (void) {
00421 return dump_file;
00422 }
00423
00424 struct profile_hooks rtl_profile_hooks =
00425 {
00426 rtl_init_edge_profiler,
00427 rtl_gen_edge_profiler,
00428 rtl_gen_interval_profiler,
00429 rtl_gen_pow2_profiler,
00430 rtl_gen_one_value_profiler,
00431 rtl_gen_const_delta_profiler,
00432 rtl_profile_dump_file
00433 };