Imported GNU Classpath 0.90
[official-gcc.git] / gcc / value-prof.c
blobf08979020e9d958a138fa155e88e3f44c80e0a72
1 /* Transformations based on profile information for values.
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 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 2, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "expr.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "value-prof.h"
30 #include "output.h"
31 #include "flags.h"
32 #include "insn-config.h"
33 #include "recog.h"
34 #include "optabs.h"
35 #include "regs.h"
36 #include "ggc.h"
37 #include "tree-flow.h"
38 #include "tree-flow-inline.h"
39 #include "diagnostic.h"
40 #include "coverage.h"
41 #include "tree.h"
42 #include "gcov-io.h"
43 #include "timevar.h"
44 #include "tree-pass.h"
45 #include "toplev.h"
47 static struct value_prof_hooks *value_prof_hooks;
49 /* This is the vector of histograms. Created in find_values_to_profile.
50 During profile generation, freed by instrument_values.
51 During profile use, freed by value_profile_transformations. */
53 static histogram_values static_values = NULL;
55 /* In this file value profile based optimizations are placed. Currently the
56 following optimizations are implemented (for more detailed descriptions
57 see comments at value_profile_transformations):
59 1) Division/modulo specialization. Provided that we can determine that the
60 operands of the division have some special properties, we may use it to
61 produce more effective code.
62 2) Speculative prefetching. If we are able to determine that the difference
63 between addresses accessed by a memory reference is usually constant, we
64 may add the prefetch instructions.
65 FIXME: This transformation was removed together with RTL based value
66 profiling.
68 Every such optimization should add its requirements for profiled values to
69 insn_values_to_profile function. This function is called from branch_prob
70 in profile.c and the requested values are instrumented by it in the first
71 compilation with -fprofile-arcs. The optimization may then read the
72 gathered data in the second compilation with -fbranch-probabilities.
74 The measured data is pointed to from the histograms
75 field of the statement annotation of the instrumented insns. It is
76 kept as a linked list of struct histogram_value_t's, which contain the
77 same information as above. */
80 static tree tree_divmod_fixed_value (tree, tree, tree, tree,
81 tree, int, gcov_type, gcov_type);
82 static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
83 static tree tree_mod_subtract (tree, tree, tree, tree, int, int, int,
84 gcov_type, gcov_type, gcov_type);
85 static bool tree_divmod_fixed_value_transform (tree);
86 static bool tree_mod_pow2_value_transform (tree);
87 static bool tree_mod_subtract_transform (tree);
89 /* The overall number of invocations of the counter should match execution count
90 of basic block. Report it as error rather than internal error as it might
91 mean that user has misused the profile somehow. */
92 static bool
93 check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
95 if (all != bb_count)
97 location_t * locus;
98 locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
99 ? EXPR_LOCUS (stmt)
100 : &DECL_SOURCE_LOCATION (current_function_decl));
101 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
102 locus, name, (int)all, (int)bb_count);
103 return true;
105 return false;
108 /* Tree based transformations. */
109 static bool
110 tree_value_profile_transformations (void)
112 basic_block bb;
113 block_stmt_iterator bsi;
114 bool changed = false;
116 FOR_EACH_BB (bb)
118 /* Ignore cold areas -- we are enlarging the code. */
119 if (!maybe_hot_bb_p (bb))
120 continue;
122 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
124 tree stmt = bsi_stmt (bsi);
125 stmt_ann_t ann = get_stmt_ann (stmt);
126 histogram_value th = ann->histograms;
127 if (!th)
128 continue;
130 if (dump_file)
132 fprintf (dump_file, "Trying transformations on insn ");
133 print_generic_stmt (dump_file, stmt, TDF_SLIM);
136 /* Transformations: */
137 /* The order of things in this conditional controls which
138 transformation is used when more than one is applicable. */
139 /* It is expected that any code added by the transformations
140 will be added before the current statement, and that the
141 current statement remain valid (although possibly
142 modified) upon return. */
143 if (flag_value_profile_transformations
144 && (tree_mod_subtract_transform (stmt)
145 || tree_divmod_fixed_value_transform (stmt)
146 || tree_mod_pow2_value_transform (stmt)))
148 changed = true;
149 /* Original statement may no longer be in the same block. */
150 bb = bb_for_stmt (stmt);
153 /* Free extra storage from compute_value_histograms. */
154 while (th)
156 free (th->hvalue.counters);
157 th = th->hvalue.next;
159 ann->histograms = 0;
163 if (changed)
165 counts_to_freqs ();
168 return changed;
171 /* Generate code for transformation 1 (with OPERATION, operands OP1
172 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
173 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
174 within roundoff error). This generates the result into a temp and returns
175 the temp; it does not replace or alter the original STMT. */
176 static tree
177 tree_divmod_fixed_value (tree stmt, tree operation,
178 tree op1, tree op2, tree value, int prob, gcov_type count,
179 gcov_type all)
181 tree stmt1, stmt2, stmt3;
182 tree tmp1, tmp2, tmpv;
183 tree label_decl1 = create_artificial_label ();
184 tree label_decl2 = create_artificial_label ();
185 tree label_decl3 = create_artificial_label ();
186 tree label1, label2, label3;
187 tree bb1end, bb2end, bb3end;
188 basic_block bb, bb2, bb3, bb4;
189 tree optype = TREE_TYPE (operation);
190 edge e12, e13, e23, e24, e34;
191 block_stmt_iterator bsi;
193 bb = bb_for_stmt (stmt);
194 bsi = bsi_for_stmt (stmt);
196 tmpv = create_tmp_var (optype, "PROF");
197 tmp1 = create_tmp_var (optype, "PROF");
198 stmt1 = build2 (MODIFY_EXPR, optype, tmpv, fold_convert (optype, value));
199 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
200 stmt3 = build3 (COND_EXPR, void_type_node,
201 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
202 build1 (GOTO_EXPR, void_type_node, label_decl2),
203 build1 (GOTO_EXPR, void_type_node, label_decl1));
204 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
205 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
206 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
207 bb1end = stmt3;
209 tmp2 = create_tmp_var (optype, "PROF");
210 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
211 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
212 build2 (TREE_CODE (operation), optype, op1, tmpv));
213 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
214 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
215 bb2end = stmt1;
217 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
218 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
219 build2 (TREE_CODE (operation), optype, op1, op2));
220 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
221 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
222 bb3end = stmt1;
224 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
225 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
227 /* Fix CFG. */
228 /* Edge e23 connects bb2 to bb3, etc. */
229 e12 = split_block (bb, bb1end);
230 bb2 = e12->dest;
231 bb2->count = count;
232 e23 = split_block (bb2, bb2end);
233 bb3 = e23->dest;
234 bb3->count = all - count;
235 e34 = split_block (bb3, bb3end);
236 bb4 = e34->dest;
237 bb4->count = all;
239 e12->flags &= ~EDGE_FALLTHRU;
240 e12->flags |= EDGE_FALSE_VALUE;
241 e12->probability = prob;
242 e12->count = count;
244 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
245 e13->probability = REG_BR_PROB_BASE - prob;
246 e13->count = all - count;
248 remove_edge (e23);
250 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
251 e24->probability = REG_BR_PROB_BASE;
252 e24->count = count;
254 e34->probability = REG_BR_PROB_BASE;
255 e34->count = all - count;
257 return tmp2;
260 /* Do transform 1) on INSN if applicable. */
261 static bool
262 tree_divmod_fixed_value_transform (tree stmt)
264 stmt_ann_t ann = get_stmt_ann (stmt);
265 histogram_value histogram;
266 enum tree_code code;
267 gcov_type val, count, all;
268 tree modify, op, op1, op2, result, value, tree_val;
269 int prob;
271 modify = stmt;
272 if (TREE_CODE (stmt) == RETURN_EXPR
273 && TREE_OPERAND (stmt, 0)
274 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
275 modify = TREE_OPERAND (stmt, 0);
276 if (TREE_CODE (modify) != MODIFY_EXPR)
277 return false;
278 op = TREE_OPERAND (modify, 1);
279 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
280 return false;
281 code = TREE_CODE (op);
283 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
284 return false;
286 op1 = TREE_OPERAND (op, 0);
287 op2 = TREE_OPERAND (op, 1);
288 if (!ann->histograms)
289 return false;
291 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
292 if (histogram->type == HIST_TYPE_SINGLE_VALUE)
293 break;
295 if (!histogram)
296 return false;
298 value = histogram->hvalue.value;
299 val = histogram->hvalue.counters[0];
300 count = histogram->hvalue.counters[1];
301 all = histogram->hvalue.counters[2];
303 /* We require that count is at least half of all; this means
304 that for the transformation to fire the value must be constant
305 at least 50% of time (and 75% gives the guarantee of usage). */
306 if (simple_cst_equal (op2, value) != 1 || 2 * count < all)
307 return false;
309 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
310 return false;
312 /* Compute probability of taking the optimal path. */
313 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
315 tree_val = build_int_cst_wide (get_gcov_type (),
316 (unsigned HOST_WIDE_INT) val,
317 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
318 result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
320 if (dump_file)
322 fprintf (dump_file, "Div/mod by constant ");
323 print_generic_expr (dump_file, value, TDF_SLIM);
324 fprintf (dump_file, "=");
325 print_generic_expr (dump_file, tree_val, TDF_SLIM);
326 fprintf (dump_file, " transformation on insn ");
327 print_generic_stmt (dump_file, stmt, TDF_SLIM);
330 TREE_OPERAND (modify, 1) = result;
332 return true;
335 /* Generate code for transformation 2 (with OPERATION, operands OP1
336 and OP2, parent modify-expr STMT and probability of taking the optimal
337 path PROB, which is equivalent to COUNT/ALL within roundoff error).
338 This generates the result into a temp and returns
339 the temp; it does not replace or alter the original STMT. */
340 static tree
341 tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
342 gcov_type count, gcov_type all)
344 tree stmt1, stmt2, stmt3, stmt4;
345 tree tmp1, tmp2, tmp3;
346 tree label_decl1 = create_artificial_label ();
347 tree label_decl2 = create_artificial_label ();
348 tree label_decl3 = create_artificial_label ();
349 tree label1, label2, label3;
350 tree bb1end, bb2end, bb3end;
351 basic_block bb, bb2, bb3, bb4;
352 tree optype = TREE_TYPE (operation);
353 edge e12, e13, e23, e24, e34;
354 block_stmt_iterator bsi;
355 tree result = create_tmp_var (optype, "PROF");
357 bb = bb_for_stmt (stmt);
358 bsi = bsi_for_stmt (stmt);
360 tmp1 = create_tmp_var (optype, "PROF");
361 tmp2 = create_tmp_var (optype, "PROF");
362 tmp3 = create_tmp_var (optype, "PROF");
363 stmt1 = build2 (MODIFY_EXPR, optype, tmp1, fold_convert (optype, op2));
364 stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
365 build2 (PLUS_EXPR, optype, op2, integer_minus_one_node));
366 stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
367 build2 (BIT_AND_EXPR, optype, tmp2, tmp1));
368 stmt4 = build3 (COND_EXPR, void_type_node,
369 build2 (NE_EXPR, boolean_type_node, tmp3, integer_zero_node),
370 build1 (GOTO_EXPR, void_type_node, label_decl2),
371 build1 (GOTO_EXPR, void_type_node, label_decl1));
372 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
373 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
374 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
375 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
376 bb1end = stmt4;
378 /* tmp2 == op2-1 inherited from previous block */
379 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
380 stmt1 = build2 (MODIFY_EXPR, optype, result,
381 build2 (BIT_AND_EXPR, optype, op1, tmp2));
382 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
383 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
384 bb2end = stmt1;
386 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
387 stmt1 = build2 (MODIFY_EXPR, optype, result,
388 build2 (TREE_CODE (operation), optype, op1, op2));
389 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
390 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
391 bb3end = stmt1;
393 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
394 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
396 /* Fix CFG. */
397 /* Edge e23 connects bb2 to bb3, etc. */
398 e12 = split_block (bb, bb1end);
399 bb2 = e12->dest;
400 bb2->count = count;
401 e23 = split_block (bb2, bb2end);
402 bb3 = e23->dest;
403 bb3->count = all - count;
404 e34 = split_block (bb3, bb3end);
405 bb4 = e34->dest;
406 bb4->count = all;
408 e12->flags &= ~EDGE_FALLTHRU;
409 e12->flags |= EDGE_FALSE_VALUE;
410 e12->probability = prob;
411 e12->count = count;
413 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
414 e13->probability = REG_BR_PROB_BASE - prob;
415 e13->count = all - count;
417 remove_edge (e23);
419 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
420 e24->probability = REG_BR_PROB_BASE;
421 e24->count = count;
423 e34->probability = REG_BR_PROB_BASE;
424 e34->count = all - count;
426 return result;
429 /* Do transform 2) on INSN if applicable. */
430 static bool
431 tree_mod_pow2_value_transform (tree stmt)
433 stmt_ann_t ann = get_stmt_ann (stmt);
434 histogram_value histogram;
435 enum tree_code code;
436 gcov_type count, wrong_values, all;
437 tree modify, op, op1, op2, result, value;
438 int prob;
440 modify = stmt;
441 if (TREE_CODE (stmt) == RETURN_EXPR
442 && TREE_OPERAND (stmt, 0)
443 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
444 modify = TREE_OPERAND (stmt, 0);
445 if (TREE_CODE (modify) != MODIFY_EXPR)
446 return false;
447 op = TREE_OPERAND (modify, 1);
448 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
449 return false;
450 code = TREE_CODE (op);
452 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
453 return false;
455 op1 = TREE_OPERAND (op, 0);
456 op2 = TREE_OPERAND (op, 1);
457 if (!ann->histograms)
458 return false;
460 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
461 if (histogram->type == HIST_TYPE_POW2)
462 break;
464 if (!histogram)
465 return false;
467 value = histogram->hvalue.value;
468 wrong_values = histogram->hvalue.counters[0];
469 count = histogram->hvalue.counters[1];
471 /* We require that we hit a power of 2 at least half of all evaluations. */
472 if (simple_cst_equal (op2, value) != 1 || count < wrong_values)
473 return false;
475 if (dump_file)
477 fprintf (dump_file, "Mod power of 2 transformation on insn ");
478 print_generic_stmt (dump_file, stmt, TDF_SLIM);
481 /* Compute probability of taking the optimal path. */
482 all = count + wrong_values;
483 if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
484 return false;
486 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
488 result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
490 TREE_OPERAND (modify, 1) = result;
492 return true;
495 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
496 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
497 support. Currently only NCOUNTS==0 or 1 is supported and this is
498 built into this interface. The probabilities of taking the optimal
499 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
500 COUNT2/ALL respectively within roundoff error). This generates the
501 result into a temp and returns the temp; it does not replace or alter
502 the original STMT. */
503 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
505 static tree
506 tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
507 int prob1, int prob2, int ncounts,
508 gcov_type count1, gcov_type count2, gcov_type all)
510 tree stmt1, stmt2, stmt3;
511 tree tmp1;
512 tree label_decl1 = create_artificial_label ();
513 tree label_decl2 = create_artificial_label ();
514 tree label_decl3 = create_artificial_label ();
515 tree label1, label2, label3;
516 tree bb1end, bb2end = NULL_TREE, bb3end;
517 basic_block bb, bb2, bb3, bb4;
518 tree optype = TREE_TYPE (operation);
519 edge e12, e23 = 0, e24, e34, e14;
520 block_stmt_iterator bsi;
521 tree result = create_tmp_var (optype, "PROF");
523 bb = bb_for_stmt (stmt);
524 bsi = bsi_for_stmt (stmt);
526 tmp1 = create_tmp_var (optype, "PROF");
527 stmt1 = build2 (MODIFY_EXPR, optype, result, op1);
528 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
529 stmt3 = build3 (COND_EXPR, void_type_node,
530 build2 (LT_EXPR, boolean_type_node, result, tmp1),
531 build1 (GOTO_EXPR, void_type_node, label_decl3),
532 build1 (GOTO_EXPR, void_type_node,
533 ncounts ? label_decl1 : label_decl2));
534 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
535 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
536 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
537 bb1end = stmt3;
539 if (ncounts) /* Assumed to be 0 or 1 */
541 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
542 stmt1 = build2 (MODIFY_EXPR, optype, result,
543 build2 (MINUS_EXPR, optype, result, tmp1));
544 stmt2 = build3 (COND_EXPR, void_type_node,
545 build2 (LT_EXPR, boolean_type_node, result, tmp1),
546 build1 (GOTO_EXPR, void_type_node, label_decl3),
547 build1 (GOTO_EXPR, void_type_node, label_decl2));
548 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
549 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
550 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
551 bb2end = stmt2;
554 /* Fallback case. */
555 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
556 stmt1 = build2 (MODIFY_EXPR, optype, result,
557 build2 (TREE_CODE (operation), optype, result, tmp1));
558 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
559 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
560 bb3end = stmt1;
562 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
563 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
565 /* Fix CFG. */
566 /* Edge e23 connects bb2 to bb3, etc. */
567 /* However block 3 is optional; if it is not there, references
568 to 3 really refer to block 2. */
569 e12 = split_block (bb, bb1end);
570 bb2 = e12->dest;
571 bb2->count = all - count1;
573 if (ncounts) /* Assumed to be 0 or 1. */
575 e23 = split_block (bb2, bb2end);
576 bb3 = e23->dest;
577 bb3->count = all - count1 - count2;
580 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
581 bb4 = e34->dest;
582 bb4->count = all;
584 e12->flags &= ~EDGE_FALLTHRU;
585 e12->flags |= EDGE_FALSE_VALUE;
586 e12->probability = REG_BR_PROB_BASE - prob1;
587 e12->count = all - count1;
589 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
590 e14->probability = prob1;
591 e14->count = count1;
593 if (ncounts) /* Assumed to be 0 or 1. */
595 e23->flags &= ~EDGE_FALLTHRU;
596 e23->flags |= EDGE_FALSE_VALUE;
597 e23->count = all - count1 - count2;
598 e23->probability = REG_BR_PROB_BASE - prob2;
600 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
601 e24->probability = prob2;
602 e24->count = count2;
605 e34->probability = REG_BR_PROB_BASE;
606 e34->count = all - count1 - count2;
608 return result;
611 /* Do transforms 3) and 4) on INSN if applicable. */
612 static bool
613 tree_mod_subtract_transform (tree stmt)
615 stmt_ann_t ann = get_stmt_ann (stmt);
616 histogram_value histogram;
617 enum tree_code code;
618 gcov_type count, wrong_values, all;
619 tree modify, op, op1, op2, result, value;
620 int prob1, prob2;
621 unsigned int i;
623 modify = stmt;
624 if (TREE_CODE (stmt) == RETURN_EXPR
625 && TREE_OPERAND (stmt, 0)
626 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
627 modify = TREE_OPERAND (stmt, 0);
628 if (TREE_CODE (modify) != MODIFY_EXPR)
629 return false;
630 op = TREE_OPERAND (modify, 1);
631 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
632 return false;
633 code = TREE_CODE (op);
635 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
636 return false;
638 op1 = TREE_OPERAND (op, 0);
639 op2 = TREE_OPERAND (op, 1);
640 if (!ann->histograms)
641 return false;
643 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
644 if (histogram->type == HIST_TYPE_INTERVAL)
645 break;
647 if (!histogram)
648 return false;
650 value = histogram->hvalue.value;
651 all = 0;
652 wrong_values = 0;
653 for (i = 0; i < histogram->hdata.intvl.steps; i++)
654 all += histogram->hvalue.counters[i];
656 wrong_values += histogram->hvalue.counters[i];
657 wrong_values += histogram->hvalue.counters[i+1];
658 all += wrong_values;
660 /* Compute probability of taking the optimal path. */
661 if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
662 return false;
664 /* We require that we use just subtractions in at least 50% of all
665 evaluations. */
666 count = 0;
667 for (i = 0; i < histogram->hdata.intvl.steps; i++)
669 count += histogram->hvalue.counters[i];
670 if (count * 2 >= all)
671 break;
673 if (i == histogram->hdata.intvl.steps)
674 return false;
676 if (dump_file)
678 fprintf (dump_file, "Mod subtract transformation on insn ");
679 print_generic_stmt (dump_file, stmt, TDF_SLIM);
682 /* Compute probability of taking the optimal path(s). */
683 prob1 = (histogram->hvalue.counters[0] * REG_BR_PROB_BASE + all / 2) / all;
684 prob2 = (histogram->hvalue.counters[1] * REG_BR_PROB_BASE + all / 2) / all;
686 /* In practice, "steps" is always 2. This interface reflects this,
687 and will need to be changed if "steps" can change. */
688 result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
689 histogram->hvalue.counters[0],
690 histogram->hvalue.counters[1], all);
692 TREE_OPERAND (modify, 1) = result;
694 return true;
697 struct value_prof_hooks {
698 /* Find list of values for which we want to measure histograms. */
699 void (*find_values_to_profile) (histogram_values *);
701 /* Identify and exploit properties of values that are hard to analyze
702 statically. See value-prof.c for more detail. */
703 bool (*value_profile_transformations) (void);
706 /* Find values inside STMT for that we want to measure histograms for
707 division/modulo optimization. */
708 static void
709 tree_divmod_values_to_profile (tree stmt, histogram_values *values)
711 tree assign, lhs, rhs, divisor, op0, type;
712 histogram_value hist;
714 if (TREE_CODE (stmt) == RETURN_EXPR)
715 assign = TREE_OPERAND (stmt, 0);
716 else
717 assign = stmt;
719 if (!assign
720 || TREE_CODE (assign) != MODIFY_EXPR)
721 return;
722 lhs = TREE_OPERAND (assign, 0);
723 type = TREE_TYPE (lhs);
724 if (!INTEGRAL_TYPE_P (type))
725 return;
727 rhs = TREE_OPERAND (assign, 1);
728 switch (TREE_CODE (rhs))
730 case TRUNC_DIV_EXPR:
731 case TRUNC_MOD_EXPR:
732 divisor = TREE_OPERAND (rhs, 1);
733 op0 = TREE_OPERAND (rhs, 0);
735 VEC_reserve (histogram_value, heap, *values, 3);
737 if (is_gimple_reg (divisor))
739 /* Check for the case where the divisor is the same value most
740 of the time. */
741 hist = ggc_alloc (sizeof (*hist));
742 hist->hvalue.value = divisor;
743 hist->hvalue.stmt = stmt;
744 hist->type = HIST_TYPE_SINGLE_VALUE;
745 VEC_quick_push (histogram_value, *values, hist);
748 /* For mod, check whether it is not often a noop (or replaceable by
749 a few subtractions). */
750 if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
751 && TYPE_UNSIGNED (type))
753 /* Check for a special case where the divisor is power of 2. */
754 hist = ggc_alloc (sizeof (*hist));
755 hist->hvalue.value = divisor;
756 hist->hvalue.stmt = stmt;
757 hist->type = HIST_TYPE_POW2;
758 VEC_quick_push (histogram_value, *values, hist);
760 hist = ggc_alloc (sizeof (*hist));
761 hist->hvalue.stmt = stmt;
762 hist->hvalue.value
763 = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
764 hist->type = HIST_TYPE_INTERVAL;
765 hist->hdata.intvl.int_start = 0;
766 hist->hdata.intvl.steps = 2;
767 VEC_quick_push (histogram_value, *values, hist);
769 return;
771 default:
772 return;
776 /* Find values inside STMT for that we want to measure histograms and adds
777 them to list VALUES. */
779 static void
780 tree_values_to_profile (tree stmt, histogram_values *values)
782 if (flag_value_profile_transformations)
783 tree_divmod_values_to_profile (stmt, values);
786 static void
787 tree_find_values_to_profile (histogram_values *values)
789 basic_block bb;
790 block_stmt_iterator bsi;
791 unsigned i;
792 histogram_value hist;
794 *values = NULL;
795 FOR_EACH_BB (bb)
796 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
797 tree_values_to_profile (bsi_stmt (bsi), values);
798 static_values = *values;
800 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
802 switch (hist->type)
804 case HIST_TYPE_INTERVAL:
805 if (dump_file)
807 fprintf (dump_file, "Interval counter for tree ");
808 print_generic_expr (dump_file, hist->hvalue.stmt,
809 TDF_SLIM);
810 fprintf (dump_file, ", range %d -- %d.\n",
811 hist->hdata.intvl.int_start,
812 (hist->hdata.intvl.int_start
813 + hist->hdata.intvl.steps - 1));
815 hist->n_counters = hist->hdata.intvl.steps + 2;
816 break;
818 case HIST_TYPE_POW2:
819 if (dump_file)
821 fprintf (dump_file, "Pow2 counter for tree ");
822 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
823 fprintf (dump_file, ".\n");
825 hist->n_counters = 2;
826 break;
828 case HIST_TYPE_SINGLE_VALUE:
829 if (dump_file)
831 fprintf (dump_file, "Single value counter for tree ");
832 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
833 fprintf (dump_file, ".\n");
835 hist->n_counters = 3;
836 break;
838 case HIST_TYPE_CONST_DELTA:
839 if (dump_file)
841 fprintf (dump_file, "Constant delta counter for tree ");
842 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
843 fprintf (dump_file, ".\n");
845 hist->n_counters = 4;
846 break;
848 default:
849 gcc_unreachable ();
854 static struct value_prof_hooks tree_value_prof_hooks = {
855 tree_find_values_to_profile,
856 tree_value_profile_transformations
859 void
860 tree_register_value_prof_hooks (void)
862 value_prof_hooks = &tree_value_prof_hooks;
863 gcc_assert (ir_type ());
866 /* IR-independent entry points. */
867 void
868 find_values_to_profile (histogram_values *values)
870 (value_prof_hooks->find_values_to_profile) (values);
873 bool
874 value_profile_transformations (void)
876 bool retval = (value_prof_hooks->value_profile_transformations) ();
877 VEC_free (histogram_value, heap, static_values);
878 return retval;