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
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
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
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "value-prof.h"
32 #include "insn-config.h"
37 #include "tree-flow.h"
38 #include "tree-flow-inline.h"
39 #include "diagnostic.h"
44 #include "tree-pass.h"
46 static struct value_prof_hooks *value_prof_hooks;
48 /* This is the vector of histograms. Created in find_values_to_profile.
49 During profile generation, freed by instrument_values.
50 During profile use, freed by value_profile_transformations. */
52 static histogram_values static_values = NULL;
54 /* In this file value profile based optimizations are placed. Currently the
55 following optimizations are implemented (for more detailed descriptions
56 see comments at value_profile_transformations):
58 1) Division/modulo specialization. Provided that we can determine that the
59 operands of the division have some special properties, we may use it to
60 produce more effective code.
61 2) Speculative prefetching. If we are able to determine that the difference
62 between addresses accessed by a memory reference is usually constant, we
63 may add the prefetch instructions.
64 FIXME: This transformation was removed together with RTL based value
67 Every such optimization should add its requirements for profiled values to
68 insn_values_to_profile function. This function is called from branch_prob
69 in profile.c and the requested values are instrumented by it in the first
70 compilation with -fprofile-arcs. The optimization may then read the
71 gathered data in the second compilation with -fbranch-probabilities.
73 The measured data is pointed to from the histograms
74 field of the statement annotation of the instrumented insns. It is
75 kept as a linked list of struct histogram_value_t's, which contain the
76 same information as above. */
79 static tree tree_divmod_fixed_value (tree, tree, tree, tree,
80 tree, int, gcov_type, gcov_type);
81 static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
82 static tree tree_mod_subtract (tree, tree, tree, tree, int, int, int,
83 gcov_type, gcov_type, gcov_type);
84 static bool tree_divmod_fixed_value_transform (tree);
85 static bool tree_mod_pow2_value_transform (tree);
86 static bool tree_mod_subtract_transform (tree);
88 /* Tree based transformations. */
90 tree_value_profile_transformations (void)
93 block_stmt_iterator bsi;
98 /* Ignore cold areas -- we are enlarging the code. */
99 if (!maybe_hot_bb_p (bb))
102 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
104 tree stmt = bsi_stmt (bsi);
105 stmt_ann_t ann = get_stmt_ann (stmt);
106 histogram_value th = ann->histograms;
112 fprintf (dump_file, "Trying transformations on insn ");
113 print_generic_stmt (dump_file, stmt, TDF_SLIM);
116 /* Transformations: */
117 /* The order of things in this conditional controls which
118 transformation is used when more than one is applicable. */
119 /* It is expected that any code added by the transformations
120 will be added before the current statement, and that the
121 current statement remain valid (although possibly
122 modified) upon return. */
123 if (flag_value_profile_transformations
124 && (tree_mod_subtract_transform (stmt)
125 || tree_divmod_fixed_value_transform (stmt)
126 || tree_mod_pow2_value_transform (stmt)))
129 /* Original statement may no longer be in the same block. */
130 bb = bb_for_stmt (stmt);
133 /* Free extra storage from compute_value_histograms. */
136 free (th->hvalue.counters);
137 th = th->hvalue.next;
151 /* Generate code for transformation 1 (with OPERATION, operands OP1
152 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
153 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
154 within roundoff error). This generates the result into a temp and returns
155 the temp; it does not replace or alter the original STMT. */
157 tree_divmod_fixed_value (tree stmt, tree operation,
158 tree op1, tree op2, tree value, int prob, gcov_type count,
161 tree stmt1, stmt2, stmt3;
162 tree tmp1, tmp2, tmpv;
163 tree label_decl1 = create_artificial_label ();
164 tree label_decl2 = create_artificial_label ();
165 tree label_decl3 = create_artificial_label ();
166 tree label1, label2, label3;
167 tree bb1end, bb2end, bb3end;
168 basic_block bb, bb2, bb3, bb4;
169 tree optype = TREE_TYPE (operation);
170 edge e12, e13, e23, e24, e34;
171 block_stmt_iterator bsi;
173 bb = bb_for_stmt (stmt);
174 bsi = bsi_for_stmt (stmt);
176 tmpv = create_tmp_var (optype, "PROF");
177 tmp1 = create_tmp_var (optype, "PROF");
178 stmt1 = build2 (MODIFY_EXPR, optype, tmpv, fold_convert (optype, value));
179 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
180 stmt3 = build3 (COND_EXPR, void_type_node,
181 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
182 build1 (GOTO_EXPR, void_type_node, label_decl2),
183 build1 (GOTO_EXPR, void_type_node, label_decl1));
184 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
185 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
186 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
189 tmp2 = create_tmp_var (optype, "PROF");
190 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
191 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
192 build2 (TREE_CODE (operation), optype, op1, tmpv));
193 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
194 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
197 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
198 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
199 build2 (TREE_CODE (operation), optype, op1, op2));
200 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
201 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
204 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
205 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
208 /* Edge e23 connects bb2 to bb3, etc. */
209 e12 = split_block (bb, bb1end);
212 e23 = split_block (bb2, bb2end);
214 bb3->count = all - count;
215 e34 = split_block (bb3, bb3end);
219 e12->flags &= ~EDGE_FALLTHRU;
220 e12->flags |= EDGE_FALSE_VALUE;
221 e12->probability = prob;
224 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
225 e13->probability = REG_BR_PROB_BASE - prob;
226 e13->count = all - count;
230 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
231 e24->probability = REG_BR_PROB_BASE;
234 e34->probability = REG_BR_PROB_BASE;
235 e34->count = all - count;
240 /* Do transform 1) on INSN if applicable. */
242 tree_divmod_fixed_value_transform (tree stmt)
244 stmt_ann_t ann = get_stmt_ann (stmt);
245 histogram_value histogram;
247 gcov_type val, count, all;
248 tree modify, op, op1, op2, result, value, tree_val;
252 if (TREE_CODE (stmt) == RETURN_EXPR
253 && TREE_OPERAND (stmt, 0)
254 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
255 modify = TREE_OPERAND (stmt, 0);
256 if (TREE_CODE (modify) != MODIFY_EXPR)
258 op = TREE_OPERAND (modify, 1);
259 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
261 code = TREE_CODE (op);
263 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
266 op1 = TREE_OPERAND (op, 0);
267 op2 = TREE_OPERAND (op, 1);
268 if (!ann->histograms)
271 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
272 if (histogram->type == HIST_TYPE_SINGLE_VALUE)
278 value = histogram->hvalue.value;
279 val = histogram->hvalue.counters[0];
280 count = histogram->hvalue.counters[1];
281 all = histogram->hvalue.counters[2];
283 /* We require that count is at least half of all; this means
284 that for the transformation to fire the value must be constant
285 at least 50% of time (and 75% gives the guarantee of usage). */
286 if (simple_cst_equal (op2, value) != 1 || 2 * count < all)
289 /* Compute probability of taking the optimal path. */
290 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
292 tree_val = build_int_cst_wide (get_gcov_type (),
293 (unsigned HOST_WIDE_INT) val,
294 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
295 result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
299 fprintf (dump_file, "Div/mod by constant ");
300 print_generic_expr (dump_file, value, TDF_SLIM);
301 fprintf (dump_file, "=");
302 print_generic_expr (dump_file, tree_val, TDF_SLIM);
303 fprintf (dump_file, " transformation on insn ");
304 print_generic_stmt (dump_file, stmt, TDF_SLIM);
307 TREE_OPERAND (modify, 1) = result;
312 /* Generate code for transformation 2 (with OPERATION, operands OP1
313 and OP2, parent modify-expr STMT and probability of taking the optimal
314 path PROB, which is equivalent to COUNT/ALL within roundoff error).
315 This generates the result into a temp and returns
316 the temp; it does not replace or alter the original STMT. */
318 tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
319 gcov_type count, gcov_type all)
321 tree stmt1, stmt2, stmt3, stmt4;
322 tree tmp1, tmp2, tmp3;
323 tree label_decl1 = create_artificial_label ();
324 tree label_decl2 = create_artificial_label ();
325 tree label_decl3 = create_artificial_label ();
326 tree label1, label2, label3;
327 tree bb1end, bb2end, bb3end;
328 basic_block bb, bb2, bb3, bb4;
329 tree optype = TREE_TYPE (operation);
330 edge e12, e13, e23, e24, e34;
331 block_stmt_iterator bsi;
332 tree result = create_tmp_var (optype, "PROF");
334 bb = bb_for_stmt (stmt);
335 bsi = bsi_for_stmt (stmt);
337 tmp1 = create_tmp_var (optype, "PROF");
338 tmp2 = create_tmp_var (optype, "PROF");
339 tmp3 = create_tmp_var (optype, "PROF");
340 stmt1 = build2 (MODIFY_EXPR, optype, tmp1, fold_convert (optype, op2));
341 stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
342 build2 (PLUS_EXPR, optype, op2, integer_minus_one_node));
343 stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
344 build2 (BIT_AND_EXPR, optype, tmp2, tmp1));
345 stmt4 = build3 (COND_EXPR, void_type_node,
346 build2 (NE_EXPR, boolean_type_node, tmp3, integer_zero_node),
347 build1 (GOTO_EXPR, void_type_node, label_decl2),
348 build1 (GOTO_EXPR, void_type_node, label_decl1));
349 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
350 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
351 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
352 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
355 /* tmp2 == op2-1 inherited from previous block */
356 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
357 stmt1 = build2 (MODIFY_EXPR, optype, result,
358 build2 (BIT_AND_EXPR, optype, op1, tmp2));
359 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
360 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
363 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
364 stmt1 = build2 (MODIFY_EXPR, optype, result,
365 build2 (TREE_CODE (operation), optype, op1, op2));
366 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
367 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
370 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
371 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
374 /* Edge e23 connects bb2 to bb3, etc. */
375 e12 = split_block (bb, bb1end);
378 e23 = split_block (bb2, bb2end);
380 bb3->count = all - count;
381 e34 = split_block (bb3, bb3end);
385 e12->flags &= ~EDGE_FALLTHRU;
386 e12->flags |= EDGE_FALSE_VALUE;
387 e12->probability = prob;
390 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
391 e13->probability = REG_BR_PROB_BASE - prob;
392 e13->count = all - count;
396 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
397 e24->probability = REG_BR_PROB_BASE;
400 e34->probability = REG_BR_PROB_BASE;
401 e34->count = all - count;
406 /* Do transform 2) on INSN if applicable. */
408 tree_mod_pow2_value_transform (tree stmt)
410 stmt_ann_t ann = get_stmt_ann (stmt);
411 histogram_value histogram;
413 gcov_type count, wrong_values, all;
414 tree modify, op, op1, op2, result, value;
418 if (TREE_CODE (stmt) == RETURN_EXPR
419 && TREE_OPERAND (stmt, 0)
420 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
421 modify = TREE_OPERAND (stmt, 0);
422 if (TREE_CODE (modify) != MODIFY_EXPR)
424 op = TREE_OPERAND (modify, 1);
425 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
427 code = TREE_CODE (op);
429 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
432 op1 = TREE_OPERAND (op, 0);
433 op2 = TREE_OPERAND (op, 1);
434 if (!ann->histograms)
437 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
438 if (histogram->type == HIST_TYPE_POW2)
444 value = histogram->hvalue.value;
445 wrong_values = histogram->hvalue.counters[0];
446 count = histogram->hvalue.counters[1];
448 /* We require that we hit a power of 2 at least half of all evaluations. */
449 if (simple_cst_equal (op2, value) != 1 || count < wrong_values)
454 fprintf (dump_file, "Mod power of 2 transformation on insn ");
455 print_generic_stmt (dump_file, stmt, TDF_SLIM);
458 /* Compute probability of taking the optimal path. */
459 all = count + wrong_values;
460 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
462 result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
464 TREE_OPERAND (modify, 1) = result;
469 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
470 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
471 support. Currently only NCOUNTS==0 or 1 is supported and this is
472 built into this interface. The probabilities of taking the optimal
473 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
474 COUNT2/ALL respectively within roundoff error). This generates the
475 result into a temp and returns the temp; it does not replace or alter
476 the original STMT. */
477 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
480 tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
481 int prob1, int prob2, int ncounts,
482 gcov_type count1, gcov_type count2, gcov_type all)
484 tree stmt1, stmt2, stmt3;
486 tree label_decl1 = create_artificial_label ();
487 tree label_decl2 = create_artificial_label ();
488 tree label_decl3 = create_artificial_label ();
489 tree label1, label2, label3;
490 tree bb1end, bb2end = NULL_TREE, bb3end;
491 basic_block bb, bb2, bb3, bb4;
492 tree optype = TREE_TYPE (operation);
493 edge e12, e23 = 0, e24, e34, e14;
494 block_stmt_iterator bsi;
495 tree result = create_tmp_var (optype, "PROF");
497 bb = bb_for_stmt (stmt);
498 bsi = bsi_for_stmt (stmt);
500 tmp1 = create_tmp_var (optype, "PROF");
501 stmt1 = build2 (MODIFY_EXPR, optype, result, op1);
502 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
503 stmt3 = build3 (COND_EXPR, void_type_node,
504 build2 (LT_EXPR, boolean_type_node, result, tmp1),
505 build1 (GOTO_EXPR, void_type_node, label_decl3),
506 build1 (GOTO_EXPR, void_type_node,
507 ncounts ? label_decl1 : label_decl2));
508 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
509 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
510 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
513 if (ncounts) /* Assumed to be 0 or 1 */
515 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
516 stmt1 = build2 (MODIFY_EXPR, optype, result,
517 build2 (MINUS_EXPR, optype, result, tmp1));
518 stmt2 = build3 (COND_EXPR, void_type_node,
519 build2 (LT_EXPR, boolean_type_node, result, tmp1),
520 build1 (GOTO_EXPR, void_type_node, label_decl3),
521 build1 (GOTO_EXPR, void_type_node, label_decl2));
522 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
523 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
524 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
529 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
530 stmt1 = build2 (MODIFY_EXPR, optype, result,
531 build2 (TREE_CODE (operation), optype, result, tmp1));
532 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
533 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
536 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
537 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
540 /* Edge e23 connects bb2 to bb3, etc. */
541 /* However block 3 is optional; if it is not there, references
542 to 3 really refer to block 2. */
543 e12 = split_block (bb, bb1end);
545 bb2->count = all - count1;
547 if (ncounts) /* Assumed to be 0 or 1. */
549 e23 = split_block (bb2, bb2end);
551 bb3->count = all - count1 - count2;
554 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
558 e12->flags &= ~EDGE_FALLTHRU;
559 e12->flags |= EDGE_FALSE_VALUE;
560 e12->probability = REG_BR_PROB_BASE - prob1;
561 e12->count = all - count1;
563 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
564 e14->probability = prob1;
567 if (ncounts) /* Assumed to be 0 or 1. */
569 e23->flags &= ~EDGE_FALLTHRU;
570 e23->flags |= EDGE_FALSE_VALUE;
571 e23->count = all - count1 - count2;
572 e23->probability = REG_BR_PROB_BASE - prob2;
574 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
575 e24->probability = prob2;
579 e34->probability = REG_BR_PROB_BASE;
580 e34->count = all - count1 - count2;
585 /* Do transforms 3) and 4) on INSN if applicable. */
587 tree_mod_subtract_transform (tree stmt)
589 stmt_ann_t ann = get_stmt_ann (stmt);
590 histogram_value histogram;
592 gcov_type count, wrong_values, all;
593 tree modify, op, op1, op2, result, value;
598 if (TREE_CODE (stmt) == RETURN_EXPR
599 && TREE_OPERAND (stmt, 0)
600 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
601 modify = TREE_OPERAND (stmt, 0);
602 if (TREE_CODE (modify) != MODIFY_EXPR)
604 op = TREE_OPERAND (modify, 1);
605 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
607 code = TREE_CODE (op);
609 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
612 op1 = TREE_OPERAND (op, 0);
613 op2 = TREE_OPERAND (op, 1);
614 if (!ann->histograms)
617 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
618 if (histogram->type == HIST_TYPE_INTERVAL)
624 value = histogram->hvalue.value;
627 for (i = 0; i < histogram->hdata.intvl.steps; i++)
628 all += histogram->hvalue.counters[i];
630 wrong_values += histogram->hvalue.counters[i];
631 wrong_values += histogram->hvalue.counters[i+1];
634 /* We require that we use just subtractions in at least 50% of all
637 for (i = 0; i < histogram->hdata.intvl.steps; i++)
639 count += histogram->hvalue.counters[i];
640 if (count * 2 >= all)
643 if (i == histogram->hdata.intvl.steps)
648 fprintf (dump_file, "Mod subtract transformation on insn ");
649 print_generic_stmt (dump_file, stmt, TDF_SLIM);
652 /* Compute probability of taking the optimal path(s). */
653 prob1 = (histogram->hvalue.counters[0] * REG_BR_PROB_BASE + all / 2) / all;
654 prob2 = (histogram->hvalue.counters[1] * REG_BR_PROB_BASE + all / 2) / all;
656 /* In practice, "steps" is always 2. This interface reflects this,
657 and will need to be changed if "steps" can change. */
658 result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
659 histogram->hvalue.counters[0],
660 histogram->hvalue.counters[1], all);
662 TREE_OPERAND (modify, 1) = result;
667 struct value_prof_hooks {
668 /* Find list of values for which we want to measure histograms. */
669 void (*find_values_to_profile) (histogram_values *);
671 /* Identify and exploit properties of values that are hard to analyze
672 statically. See value-prof.c for more detail. */
673 bool (*value_profile_transformations) (void);
676 /* Find values inside STMT for that we want to measure histograms for
677 division/modulo optimization. */
679 tree_divmod_values_to_profile (tree stmt, histogram_values *values)
681 tree assign, lhs, rhs, divisor, op0, type;
682 histogram_value hist;
684 if (TREE_CODE (stmt) == RETURN_EXPR)
685 assign = TREE_OPERAND (stmt, 0);
690 || TREE_CODE (assign) != MODIFY_EXPR)
692 lhs = TREE_OPERAND (assign, 0);
693 type = TREE_TYPE (lhs);
694 if (!INTEGRAL_TYPE_P (type))
697 rhs = TREE_OPERAND (assign, 1);
698 switch (TREE_CODE (rhs))
702 divisor = TREE_OPERAND (rhs, 1);
703 op0 = TREE_OPERAND (rhs, 0);
705 VEC_reserve (histogram_value, heap, *values, 3);
707 if (is_gimple_reg (divisor))
709 /* Check for the case where the divisor is the same value most
711 hist = ggc_alloc (sizeof (*hist));
712 hist->hvalue.value = divisor;
713 hist->hvalue.stmt = stmt;
714 hist->type = HIST_TYPE_SINGLE_VALUE;
715 VEC_quick_push (histogram_value, *values, hist);
718 /* For mod, check whether it is not often a noop (or replaceable by
719 a few subtractions). */
720 if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
721 && TYPE_UNSIGNED (type))
723 /* Check for a special case where the divisor is power of 2. */
724 hist = ggc_alloc (sizeof (*hist));
725 hist->hvalue.value = divisor;
726 hist->hvalue.stmt = stmt;
727 hist->type = HIST_TYPE_POW2;
728 VEC_quick_push (histogram_value, *values, hist);
730 hist = ggc_alloc (sizeof (*hist));
731 hist->hvalue.stmt = stmt;
733 = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
734 hist->type = HIST_TYPE_INTERVAL;
735 hist->hdata.intvl.int_start = 0;
736 hist->hdata.intvl.steps = 2;
737 VEC_quick_push (histogram_value, *values, hist);
746 /* Find values inside STMT for that we want to measure histograms and adds
747 them to list VALUES. */
750 tree_values_to_profile (tree stmt, histogram_values *values)
752 if (flag_value_profile_transformations)
753 tree_divmod_values_to_profile (stmt, values);
757 tree_find_values_to_profile (histogram_values *values)
760 block_stmt_iterator bsi;
762 histogram_value hist;
766 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
767 tree_values_to_profile (bsi_stmt (bsi), values);
768 static_values = *values;
770 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
774 case HIST_TYPE_INTERVAL:
777 fprintf (dump_file, "Interval counter for tree ");
778 print_generic_expr (dump_file, hist->hvalue.stmt,
780 fprintf (dump_file, ", range %d -- %d.\n",
781 hist->hdata.intvl.int_start,
782 (hist->hdata.intvl.int_start
783 + hist->hdata.intvl.steps - 1));
785 hist->n_counters = hist->hdata.intvl.steps + 2;
791 fprintf (dump_file, "Pow2 counter for tree ");
792 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
793 fprintf (dump_file, ".\n");
795 hist->n_counters = 2;
798 case HIST_TYPE_SINGLE_VALUE:
801 fprintf (dump_file, "Single value counter for tree ");
802 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
803 fprintf (dump_file, ".\n");
805 hist->n_counters = 3;
808 case HIST_TYPE_CONST_DELTA:
811 fprintf (dump_file, "Constant delta counter for tree ");
812 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
813 fprintf (dump_file, ".\n");
815 hist->n_counters = 4;
824 static struct value_prof_hooks tree_value_prof_hooks = {
825 tree_find_values_to_profile,
826 tree_value_profile_transformations
830 tree_register_value_prof_hooks (void)
832 value_prof_hooks = &tree_value_prof_hooks;
833 gcc_assert (ir_type ());
836 /* IR-independent entry points. */
838 find_values_to_profile (histogram_values *values)
840 (value_prof_hooks->find_values_to_profile) (values);
844 value_profile_transformations (void)
846 bool retval = (value_prof_hooks->value_profile_transformations) ();
847 VEC_free (histogram_value, heap, static_values);