1 /* Transformations based on profile information for values.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007 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 3, 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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
26 #include "hard-reg-set.h"
27 #include "basic-block.h"
28 #include "value-prof.h"
31 #include "insn-config.h"
36 #include "tree-flow.h"
37 #include "tree-flow-inline.h"
38 #include "diagnostic.h"
44 #include "tree-pass.h"
46 #include "pointer-set.h"
48 static struct value_prof_hooks *value_prof_hooks;
50 /* In this file value profile based optimizations are placed. Currently the
51 following optimizations are implemented (for more detailed descriptions
52 see comments at value_profile_transformations):
54 1) Division/modulo specialization. Provided that we can determine that the
55 operands of the division have some special properties, we may use it to
56 produce more effective code.
57 2) Speculative prefetching. If we are able to determine that the difference
58 between addresses accessed by a memory reference is usually constant, we
59 may add the prefetch instructions.
60 FIXME: This transformation was removed together with RTL based value
63 3) Indirect/virtual call specialization. If we can determine most
64 common function callee in indirect/virtual call. We can use this
65 information to improve code effectiveness (especially info for
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);
88 static bool tree_stringops_transform (block_stmt_iterator *);
89 static bool tree_ic_transform (tree);
91 /* Allocate histogram value. */
93 static histogram_value
94 gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
95 enum hist_type type, tree stmt, tree value)
97 histogram_value hist = (histogram_value) xcalloc (1, sizeof (*hist));
98 hist->hvalue.value = value;
99 hist->hvalue.stmt = stmt;
104 /* Hash value for histogram. */
107 histogram_hash (const void *x)
109 return htab_hash_pointer (((const_histogram_value)x)->hvalue.stmt);
112 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
115 histogram_eq (const void *x, const void *y)
117 return ((const_histogram_value) x)->hvalue.stmt == (const_tree)y;
120 /* Set histogram for STMT. */
123 set_histogram_value (struct function *fun, tree stmt, histogram_value hist)
126 if (!hist && !VALUE_HISTOGRAMS (fun))
128 if (!VALUE_HISTOGRAMS (fun))
129 VALUE_HISTOGRAMS (fun) = htab_create (1, histogram_hash,
131 loc = htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun), stmt,
132 htab_hash_pointer (stmt),
133 hist ? INSERT : NO_INSERT);
137 htab_clear_slot (VALUE_HISTOGRAMS (fun), loc);
143 /* Get histogram list for STMT. */
146 gimple_histogram_value (struct function *fun, tree stmt)
148 if (!VALUE_HISTOGRAMS (fun))
150 return htab_find_with_hash (VALUE_HISTOGRAMS (fun), stmt,
151 htab_hash_pointer (stmt));
154 /* Add histogram for STMT. */
157 gimple_add_histogram_value (struct function *fun, tree stmt, histogram_value hist)
159 hist->hvalue.next = gimple_histogram_value (fun, stmt);
160 set_histogram_value (fun, stmt, hist);
163 /* Remove histogram HIST from STMT's histogram list. */
166 gimple_remove_histogram_value (struct function *fun, tree stmt, histogram_value hist)
168 histogram_value hist2 = gimple_histogram_value (fun, stmt);
171 set_histogram_value (fun, stmt, hist->hvalue.next);
175 while (hist2->hvalue.next != hist)
176 hist2 = hist2->hvalue.next;
177 hist2->hvalue.next = hist->hvalue.next;
179 free (hist->hvalue.counters);
180 #ifdef ENABLE_CHECKING
181 memset (hist, 0xab, sizeof (*hist));
186 /* Lookup histogram of type TYPE in the STMT. */
189 gimple_histogram_value_of_type (struct function *fun, tree stmt, enum hist_type type)
191 histogram_value hist;
192 for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
193 if (hist->type == type)
198 /* Dump information about HIST to DUMP_FILE. */
201 dump_histogram_value (FILE *dump_file, histogram_value hist)
205 case HIST_TYPE_INTERVAL:
206 fprintf (dump_file, "Interval counter range %d -- %d",
207 hist->hdata.intvl.int_start,
208 (hist->hdata.intvl.int_start
209 + hist->hdata.intvl.steps - 1));
210 if (hist->hvalue.counters)
213 fprintf(dump_file, " [");
214 for (i = 0; i < hist->hdata.intvl.steps; i++)
215 fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
216 hist->hdata.intvl.int_start + i,
217 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
218 fprintf (dump_file, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC,
219 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
221 fprintf (dump_file, ".\n");
225 fprintf (dump_file, "Pow2 counter ");
226 if (hist->hvalue.counters)
228 fprintf (dump_file, "pow2:"HOST_WIDEST_INT_PRINT_DEC
229 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC,
230 (HOST_WIDEST_INT) hist->hvalue.counters[0],
231 (HOST_WIDEST_INT) hist->hvalue.counters[1]);
233 fprintf (dump_file, ".\n");
236 case HIST_TYPE_SINGLE_VALUE:
237 fprintf (dump_file, "Single value ");
238 if (hist->hvalue.counters)
240 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
241 " match:"HOST_WIDEST_INT_PRINT_DEC
242 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
243 (HOST_WIDEST_INT) hist->hvalue.counters[0],
244 (HOST_WIDEST_INT) hist->hvalue.counters[1],
245 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
247 fprintf (dump_file, ".\n");
250 case HIST_TYPE_AVERAGE:
251 fprintf (dump_file, "Average value ");
252 if (hist->hvalue.counters)
254 fprintf (dump_file, "sum:"HOST_WIDEST_INT_PRINT_DEC
255 " times:"HOST_WIDEST_INT_PRINT_DEC,
256 (HOST_WIDEST_INT) hist->hvalue.counters[0],
257 (HOST_WIDEST_INT) hist->hvalue.counters[1]);
259 fprintf (dump_file, ".\n");
263 fprintf (dump_file, "IOR value ");
264 if (hist->hvalue.counters)
266 fprintf (dump_file, "ior:"HOST_WIDEST_INT_PRINT_DEC,
267 (HOST_WIDEST_INT) hist->hvalue.counters[0]);
269 fprintf (dump_file, ".\n");
272 case HIST_TYPE_CONST_DELTA:
273 fprintf (dump_file, "Constant delta ");
274 if (hist->hvalue.counters)
276 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
277 " match:"HOST_WIDEST_INT_PRINT_DEC
278 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
279 (HOST_WIDEST_INT) hist->hvalue.counters[0],
280 (HOST_WIDEST_INT) hist->hvalue.counters[1],
281 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
283 fprintf (dump_file, ".\n");
285 case HIST_TYPE_INDIR_CALL:
286 fprintf (dump_file, "Indirect call ");
287 if (hist->hvalue.counters)
289 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
290 " match:"HOST_WIDEST_INT_PRINT_DEC
291 " all:"HOST_WIDEST_INT_PRINT_DEC,
292 (HOST_WIDEST_INT) hist->hvalue.counters[0],
293 (HOST_WIDEST_INT) hist->hvalue.counters[1],
294 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
296 fprintf (dump_file, ".\n");
301 /* Dump all histograms attached to STMT to DUMP_FILE. */
304 dump_histograms_for_stmt (struct function *fun, FILE *dump_file, tree stmt)
306 histogram_value hist;
307 for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
308 dump_histogram_value (dump_file, hist);
311 /* Remove all histograms associated with STMT. */
314 gimple_remove_stmt_histograms (struct function *fun, tree stmt)
317 while ((val = gimple_histogram_value (fun, stmt)) != NULL)
318 gimple_remove_histogram_value (fun, stmt, val);
321 /* Duplicate all histograms associates with OSTMT to STMT. */
324 gimple_duplicate_stmt_histograms (struct function *fun, tree stmt,
325 struct function *ofun, tree ostmt)
328 for (val = gimple_histogram_value (ofun, ostmt); val != NULL; val = val->hvalue.next)
330 histogram_value new = gimple_alloc_histogram_value (fun, val->type, NULL, NULL);
331 memcpy (new, val, sizeof (*val));
332 new->hvalue.stmt = stmt;
333 new->hvalue.counters = xmalloc (sizeof (*new->hvalue.counters) * new->n_counters);
334 memcpy (new->hvalue.counters, val->hvalue.counters, sizeof (*new->hvalue.counters) * new->n_counters);
335 gimple_add_histogram_value (fun, stmt, new);
339 static bool error_found = false;
341 /* Helper function for verify_histograms. For each histogram reachable via htab
342 walk verify that it was reached via statement walk. */
345 visit_hist (void **slot, void *data)
347 struct pointer_set_t *visited = (struct pointer_set_t *) data;
348 histogram_value hist = *(histogram_value *) slot;
349 if (!pointer_set_contains (visited, hist))
351 error ("Dead histogram");
352 dump_histogram_value (stderr, hist);
353 debug_generic_stmt (hist->hvalue.stmt);
359 /* Verify sanity of the histograms. */
362 verify_histograms (void)
365 block_stmt_iterator bsi;
366 histogram_value hist;
367 struct pointer_set_t *visited_hists;
370 visited_hists = pointer_set_create ();
372 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
374 tree stmt = bsi_stmt (bsi);
376 for (hist = gimple_histogram_value (cfun, stmt); hist; hist = hist->hvalue.next)
378 if (hist->hvalue.stmt != stmt)
380 error ("Histogram value statement does not correspond to statement"
381 " it is associated with");
382 debug_generic_stmt (stmt);
383 dump_histogram_value (stderr, hist);
386 pointer_set_insert (visited_hists, hist);
389 if (VALUE_HISTOGRAMS (cfun))
390 htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
391 pointer_set_destroy (visited_hists);
393 internal_error ("verify_histograms failed");
396 /* Helper function for verify_histograms. For each histogram reachable via htab
397 walk verify that it was reached via statement walk. */
400 free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
402 histogram_value hist = *(histogram_value *) slot;
403 free (hist->hvalue.counters);
404 #ifdef ENABLE_CHECKING
405 memset (hist, 0xab, sizeof (*hist));
412 free_histograms (void)
414 if (VALUE_HISTOGRAMS (cfun))
416 htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
417 htab_delete (VALUE_HISTOGRAMS (cfun));
418 VALUE_HISTOGRAMS (cfun) = NULL;
422 /* The overall number of invocations of the counter should match execution count
423 of basic block. Report it as error rather than internal error as it might
424 mean that user has misused the profile somehow. */
426 check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
431 locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
433 : &DECL_SOURCE_LOCATION (current_function_decl));
434 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
435 locus, name, (int)all, (int)bb_count);
441 /* Tree based transformations. */
443 tree_value_profile_transformations (void)
446 block_stmt_iterator bsi;
447 bool changed = false;
451 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
453 tree stmt = bsi_stmt (bsi);
454 histogram_value th = gimple_histogram_value (cfun, stmt);
460 fprintf (dump_file, "Trying transformations on stmt ");
461 print_generic_stmt (dump_file, stmt, TDF_SLIM);
462 dump_histograms_for_stmt (cfun, dump_file, stmt);
465 /* Transformations: */
466 /* The order of things in this conditional controls which
467 transformation is used when more than one is applicable. */
468 /* It is expected that any code added by the transformations
469 will be added before the current statement, and that the
470 current statement remain valid (although possibly
471 modified) upon return. */
472 if (flag_value_profile_transformations
473 && (tree_mod_subtract_transform (stmt)
474 || tree_divmod_fixed_value_transform (stmt)
475 || tree_mod_pow2_value_transform (stmt)
476 || tree_stringops_transform (&bsi)
477 || tree_ic_transform (stmt)))
479 stmt = bsi_stmt (bsi);
481 /* Original statement may no longer be in the same block. */
482 if (bb != bb_for_stmt (stmt))
484 bb = bb_for_stmt (stmt);
485 bsi = bsi_for_stmt (stmt);
499 /* Generate code for transformation 1 (with OPERATION, operands OP1
500 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
501 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
502 within roundoff error). This generates the result into a temp and returns
503 the temp; it does not replace or alter the original STMT. */
505 tree_divmod_fixed_value (tree stmt, tree operation,
506 tree op1, tree op2, tree value, int prob, gcov_type count,
509 tree stmt1, stmt2, stmt3;
510 tree tmp1, tmp2, tmpv;
511 tree label_decl1 = create_artificial_label ();
512 tree label_decl2 = create_artificial_label ();
514 tree bb1end, bb2end, bb3end;
515 basic_block bb, bb2, bb3, bb4;
516 tree optype = TREE_TYPE (operation);
517 edge e12, e13, e23, e24, e34;
518 block_stmt_iterator bsi;
520 bb = bb_for_stmt (stmt);
521 bsi = bsi_for_stmt (stmt);
523 tmpv = create_tmp_var (optype, "PROF");
524 tmp1 = create_tmp_var (optype, "PROF");
525 stmt1 = build_gimple_modify_stmt (tmpv, fold_convert (optype, value));
526 stmt2 = build_gimple_modify_stmt (tmp1, op2);
527 stmt3 = build3 (COND_EXPR, void_type_node,
528 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
529 NULL_TREE, NULL_TREE);
530 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
531 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
532 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
535 tmp2 = create_tmp_var (optype, "PROF");
536 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
537 stmt1 = build_gimple_modify_stmt (tmp2,
538 build2 (TREE_CODE (operation), optype,
540 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
541 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
544 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
545 stmt1 = build_gimple_modify_stmt (tmp2,
546 build2 (TREE_CODE (operation), optype,
548 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
549 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
553 /* Edge e23 connects bb2 to bb3, etc. */
554 e12 = split_block (bb, bb1end);
557 e23 = split_block (bb2, bb2end);
559 bb3->count = all - count;
560 e34 = split_block (bb3, bb3end);
564 e12->flags &= ~EDGE_FALLTHRU;
565 e12->flags |= EDGE_FALSE_VALUE;
566 e12->probability = prob;
569 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
570 e13->probability = REG_BR_PROB_BASE - prob;
571 e13->count = all - count;
575 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
576 e24->probability = REG_BR_PROB_BASE;
579 e34->probability = REG_BR_PROB_BASE;
580 e34->count = all - count;
585 /* Do transform 1) on INSN if applicable. */
587 tree_divmod_fixed_value_transform (tree stmt)
589 histogram_value histogram;
591 gcov_type val, count, all;
592 tree modify, op, op1, op2, result, value, tree_val;
596 if (TREE_CODE (stmt) == RETURN_EXPR
597 && TREE_OPERAND (stmt, 0)
598 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
599 modify = TREE_OPERAND (stmt, 0);
600 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
602 op = GIMPLE_STMT_OPERAND (modify, 1);
603 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
605 code = TREE_CODE (op);
607 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
610 op1 = TREE_OPERAND (op, 0);
611 op2 = TREE_OPERAND (op, 1);
613 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
617 value = histogram->hvalue.value;
618 val = histogram->hvalue.counters[0];
619 count = histogram->hvalue.counters[1];
620 all = histogram->hvalue.counters[2];
621 gimple_remove_histogram_value (cfun, stmt, histogram);
623 /* We require that count is at least half of all; this means
624 that for the transformation to fire the value must be constant
625 at least 50% of time (and 75% gives the guarantee of usage). */
626 if (simple_cst_equal (op2, value) != 1 || 2 * count < all
627 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
630 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
633 /* Compute probability of taking the optimal path. */
634 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
636 tree_val = build_int_cst_wide (get_gcov_type (),
637 (unsigned HOST_WIDE_INT) val,
638 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
639 result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
643 fprintf (dump_file, "Div/mod by constant ");
644 print_generic_expr (dump_file, value, TDF_SLIM);
645 fprintf (dump_file, "=");
646 print_generic_expr (dump_file, tree_val, TDF_SLIM);
647 fprintf (dump_file, " transformation on insn ");
648 print_generic_stmt (dump_file, stmt, TDF_SLIM);
651 GIMPLE_STMT_OPERAND (modify, 1) = result;
656 /* Generate code for transformation 2 (with OPERATION, operands OP1
657 and OP2, parent modify-expr STMT and probability of taking the optimal
658 path PROB, which is equivalent to COUNT/ALL within roundoff error).
659 This generates the result into a temp and returns
660 the temp; it does not replace or alter the original STMT. */
662 tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
663 gcov_type count, gcov_type all)
665 tree stmt1, stmt2, stmt3, stmt4;
667 tree label_decl1 = create_artificial_label ();
668 tree label_decl2 = create_artificial_label ();
670 tree bb1end, bb2end, bb3end;
671 basic_block bb, bb2, bb3, bb4;
672 tree optype = TREE_TYPE (operation);
673 edge e12, e13, e23, e24, e34;
674 block_stmt_iterator bsi;
675 tree result = create_tmp_var (optype, "PROF");
677 bb = bb_for_stmt (stmt);
678 bsi = bsi_for_stmt (stmt);
680 tmp2 = create_tmp_var (optype, "PROF");
681 tmp3 = create_tmp_var (optype, "PROF");
682 stmt2 = build_gimple_modify_stmt (tmp2,
683 build2 (PLUS_EXPR, optype, op2,
684 build_int_cst (optype, -1)));
685 stmt3 = build_gimple_modify_stmt (tmp3,
686 build2 (BIT_AND_EXPR, optype, tmp2, op2));
687 stmt4 = build3 (COND_EXPR, void_type_node,
688 build2 (NE_EXPR, boolean_type_node,
689 tmp3, build_int_cst (optype, 0)),
690 NULL_TREE, NULL_TREE);
691 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
692 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
693 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
696 /* tmp2 == op2-1 inherited from previous block */
697 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
698 stmt1 = build_gimple_modify_stmt (result,
699 build2 (BIT_AND_EXPR, optype, op1, tmp2));
700 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
701 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
704 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
705 stmt1 = build_gimple_modify_stmt (result,
706 build2 (TREE_CODE (operation), optype,
708 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
709 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
713 /* Edge e23 connects bb2 to bb3, etc. */
714 e12 = split_block (bb, bb1end);
717 e23 = split_block (bb2, bb2end);
719 bb3->count = all - count;
720 e34 = split_block (bb3, bb3end);
724 e12->flags &= ~EDGE_FALLTHRU;
725 e12->flags |= EDGE_FALSE_VALUE;
726 e12->probability = prob;
729 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
730 e13->probability = REG_BR_PROB_BASE - prob;
731 e13->count = all - count;
735 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
736 e24->probability = REG_BR_PROB_BASE;
739 e34->probability = REG_BR_PROB_BASE;
740 e34->count = all - count;
745 /* Do transform 2) on INSN if applicable. */
747 tree_mod_pow2_value_transform (tree stmt)
749 histogram_value histogram;
751 gcov_type count, wrong_values, all;
752 tree modify, op, op1, op2, result, value;
756 if (TREE_CODE (stmt) == RETURN_EXPR
757 && TREE_OPERAND (stmt, 0)
758 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
759 modify = TREE_OPERAND (stmt, 0);
760 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
762 op = GIMPLE_STMT_OPERAND (modify, 1);
763 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
765 code = TREE_CODE (op);
767 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
770 op1 = TREE_OPERAND (op, 0);
771 op2 = TREE_OPERAND (op, 1);
773 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_POW2);
777 value = histogram->hvalue.value;
778 wrong_values = histogram->hvalue.counters[0];
779 count = histogram->hvalue.counters[1];
781 gimple_remove_histogram_value (cfun, stmt, histogram);
783 /* We require that we hit a power of 2 at least half of all evaluations. */
784 if (simple_cst_equal (op2, value) != 1 || count < wrong_values
785 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
790 fprintf (dump_file, "Mod power of 2 transformation on insn ");
791 print_generic_stmt (dump_file, stmt, TDF_SLIM);
794 /* Compute probability of taking the optimal path. */
795 all = count + wrong_values;
797 if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
800 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
802 result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
804 GIMPLE_STMT_OPERAND (modify, 1) = result;
809 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
810 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
811 support. Currently only NCOUNTS==0 or 1 is supported and this is
812 built into this interface. The probabilities of taking the optimal
813 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
814 COUNT2/ALL respectively within roundoff error). This generates the
815 result into a temp and returns the temp; it does not replace or alter
816 the original STMT. */
817 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
820 tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
821 int prob1, int prob2, int ncounts,
822 gcov_type count1, gcov_type count2, gcov_type all)
824 tree stmt1, stmt2, stmt3;
826 tree label_decl1 = create_artificial_label ();
827 tree label_decl2 = create_artificial_label ();
828 tree label_decl3 = create_artificial_label ();
829 tree label1, label2, label3;
830 tree bb1end, bb2end = NULL_TREE, bb3end;
831 basic_block bb, bb2, bb3, bb4;
832 tree optype = TREE_TYPE (operation);
833 edge e12, e23 = 0, e24, e34, e14;
834 block_stmt_iterator bsi;
835 tree result = create_tmp_var (optype, "PROF");
837 bb = bb_for_stmt (stmt);
838 bsi = bsi_for_stmt (stmt);
840 tmp1 = create_tmp_var (optype, "PROF");
841 stmt1 = build_gimple_modify_stmt (result, op1);
842 stmt2 = build_gimple_modify_stmt (tmp1, op2);
843 stmt3 = build3 (COND_EXPR, void_type_node,
844 build2 (LT_EXPR, boolean_type_node, result, tmp1),
845 NULL_TREE, NULL_TREE);
846 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
847 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
848 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
851 if (ncounts) /* Assumed to be 0 or 1 */
853 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
854 stmt1 = build_gimple_modify_stmt (result,
855 build2 (MINUS_EXPR, optype,
857 stmt2 = build3 (COND_EXPR, void_type_node,
858 build2 (LT_EXPR, boolean_type_node, result, tmp1),
859 NULL_TREE, NULL_TREE);
860 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
861 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
862 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
867 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
868 stmt1 = build_gimple_modify_stmt (result,
869 build2 (TREE_CODE (operation), optype,
871 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
872 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
875 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
876 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
879 /* Edge e23 connects bb2 to bb3, etc. */
880 /* However block 3 is optional; if it is not there, references
881 to 3 really refer to block 2. */
882 e12 = split_block (bb, bb1end);
884 bb2->count = all - count1;
886 if (ncounts) /* Assumed to be 0 or 1. */
888 e23 = split_block (bb2, bb2end);
890 bb3->count = all - count1 - count2;
893 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
897 e12->flags &= ~EDGE_FALLTHRU;
898 e12->flags |= EDGE_FALSE_VALUE;
899 e12->probability = REG_BR_PROB_BASE - prob1;
900 e12->count = all - count1;
902 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
903 e14->probability = prob1;
906 if (ncounts) /* Assumed to be 0 or 1. */
908 e23->flags &= ~EDGE_FALLTHRU;
909 e23->flags |= EDGE_FALSE_VALUE;
910 e23->count = all - count1 - count2;
911 e23->probability = REG_BR_PROB_BASE - prob2;
913 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
914 e24->probability = prob2;
918 e34->probability = REG_BR_PROB_BASE;
919 e34->count = all - count1 - count2;
924 /* Do transforms 3) and 4) on INSN if applicable. */
926 tree_mod_subtract_transform (tree stmt)
928 histogram_value histogram;
930 gcov_type count, wrong_values, all;
931 tree modify, op, op1, op2, result, value;
933 unsigned int i, steps;
934 gcov_type count1, count2;
937 if (TREE_CODE (stmt) == RETURN_EXPR
938 && TREE_OPERAND (stmt, 0)
939 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
940 modify = TREE_OPERAND (stmt, 0);
941 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
943 op = GIMPLE_STMT_OPERAND (modify, 1);
944 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
946 code = TREE_CODE (op);
948 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
951 op1 = TREE_OPERAND (op, 0);
952 op2 = TREE_OPERAND (op, 1);
954 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INTERVAL);
958 value = histogram->hvalue.value;
961 for (i = 0; i < histogram->hdata.intvl.steps; i++)
962 all += histogram->hvalue.counters[i];
964 wrong_values += histogram->hvalue.counters[i];
965 wrong_values += histogram->hvalue.counters[i+1];
966 steps = histogram->hdata.intvl.steps;
968 count1 = histogram->hvalue.counters[0];
969 count2 = histogram->hvalue.counters[1];
971 /* Compute probability of taking the optimal path. */
972 if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
974 gimple_remove_histogram_value (cfun, stmt, histogram);
978 /* We require that we use just subtractions in at least 50% of all
981 for (i = 0; i < histogram->hdata.intvl.steps; i++)
983 count += histogram->hvalue.counters[i];
984 if (count * 2 >= all)
988 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
991 gimple_remove_histogram_value (cfun, stmt, histogram);
994 fprintf (dump_file, "Mod subtract transformation on insn ");
995 print_generic_stmt (dump_file, stmt, TDF_SLIM);
998 /* Compute probability of taking the optimal path(s). */
999 prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
1000 prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
1002 /* In practice, "steps" is always 2. This interface reflects this,
1003 and will need to be changed if "steps" can change. */
1004 result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
1005 count1, count2, all);
1007 GIMPLE_STMT_OPERAND (modify, 1) = result;
1012 static struct cgraph_node** pid_map = NULL;
1014 /* Initialize map of pids (pid -> cgraph node) */
1019 struct cgraph_node *n;
1021 if (pid_map != NULL)
1025 = (struct cgraph_node**) xmalloc (sizeof (struct cgraph_node*) * cgraph_max_pid);
1027 for (n = cgraph_nodes; n; n = n->next)
1030 pid_map [n->pid] = n;
1034 /* Return cgraph node for function with pid */
1036 static inline struct cgraph_node*
1037 find_func_by_pid (int pid)
1041 return pid_map [pid];
1044 /* Do transformation
1046 if (actual_callee_addres == addres_of_most_common_function/method)
1053 tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
1054 int prob, gcov_type count, gcov_type all)
1056 tree stmt1, stmt2, stmt3;
1057 tree tmp1, tmpv, tmp;
1058 tree label_decl1 = create_artificial_label ();
1059 tree label_decl2 = create_artificial_label ();
1060 tree label1, label2;
1061 tree bb1end, bb2end, bb3end;
1063 basic_block bb, bb2, bb3, bb4;
1064 tree optype = build_pointer_type (void_type_node);
1065 edge e12, e13, e23, e24, e34;
1066 block_stmt_iterator bsi;
1069 bb = bb_for_stmt (stmt);
1070 bsi = bsi_for_stmt (stmt);
1072 tmpv = create_tmp_var (optype, "PROF");
1073 tmp1 = create_tmp_var (optype, "PROF");
1074 stmt1 = build_gimple_modify_stmt (tmpv,
1075 unshare_expr (CALL_EXPR_FN (call)));
1076 tmp = fold_convert (optype, build_addr (direct_call->decl,
1077 current_function_decl));
1078 stmt2 = build_gimple_modify_stmt (tmp1, tmp);
1079 stmt3 = build3 (COND_EXPR, void_type_node,
1080 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
1081 NULL_TREE, NULL_TREE);
1082 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1083 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
1084 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
1087 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
1088 stmt1 = unshare_expr (stmt);
1089 new_call = get_call_expr_in (stmt1);
1090 CALL_EXPR_FN (new_call) = build_addr (direct_call->decl,
1091 current_function_decl);
1092 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
1093 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1096 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
1097 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
1101 /* Edge e23 connects bb2 to bb3, etc. */
1102 e12 = split_block (bb, bb1end);
1105 e23 = split_block (bb2, bb2end);
1107 bb3->count = all - count;
1108 e34 = split_block (bb3, bb3end);
1112 e12->flags &= ~EDGE_FALLTHRU;
1113 e12->flags |= EDGE_FALSE_VALUE;
1114 e12->probability = prob;
1117 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1118 e13->probability = REG_BR_PROB_BASE - prob;
1119 e13->count = all - count;
1123 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1124 e24->probability = REG_BR_PROB_BASE;
1126 e34->probability = REG_BR_PROB_BASE;
1127 e34->count = all - count;
1130 region = lookup_stmt_eh_region (stmt);
1131 if (region >=0 && tree_could_throw_p (stmt1))
1133 add_stmt_to_eh_region (stmt1, region);
1134 make_eh_edges (stmt1);
1137 if (region >=0 && tree_could_throw_p (stmt))
1139 tree_purge_dead_eh_edges (bb4);
1140 make_eh_edges (stmt);
1147 For every checked indirect/virtual call determine if most common pid of
1148 function/class method has probability more than 50%. If yes modify code of
1153 tree_ic_transform (tree stmt)
1155 histogram_value histogram;
1156 gcov_type val, count, all;
1158 tree call, callee, modify;
1159 struct cgraph_node *direct_call;
1161 call = get_call_expr_in (stmt);
1163 if (!call || TREE_CODE (call) != CALL_EXPR)
1166 callee = CALL_EXPR_FN (call);
1168 if (TREE_CODE (callee) == ADDR_EXPR)
1171 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
1175 val = histogram->hvalue.counters [0];
1176 count = histogram->hvalue.counters [1];
1177 all = histogram->hvalue.counters [2];
1178 gimple_remove_histogram_value (cfun, stmt, histogram);
1180 if (4 * count <= 3 * all)
1183 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1184 direct_call = find_func_by_pid ((int)val);
1186 if (direct_call == NULL)
1189 modify = tree_ic (stmt, call, direct_call, prob, count, all);
1193 fprintf (dump_file, "Indirect call -> direct call ");
1194 print_generic_expr (dump_file, call, TDF_SLIM);
1195 fprintf (dump_file, "=> ");
1196 print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
1197 fprintf (dump_file, " transformation on insn ");
1198 print_generic_stmt (dump_file, stmt, TDF_SLIM);
1199 fprintf (dump_file, " to ");
1200 print_generic_stmt (dump_file, modify, TDF_SLIM);
1201 fprintf (dump_file, "hist->count %llu hist->all %llu\n", count, all);
1207 /* Return true if the stringop CALL with FNDECL shall be profiled. */
1209 interesting_stringop_to_profile_p (tree fndecl, tree call)
1211 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
1213 if (fcode != BUILT_IN_MEMCPY && fcode != BUILT_IN_MEMPCPY
1214 && fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_BZERO)
1219 case BUILT_IN_MEMCPY:
1220 case BUILT_IN_MEMPCPY:
1221 return validate_arglist (call,
1222 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
1224 case BUILT_IN_MEMSET:
1225 return validate_arglist (call,
1226 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
1228 case BUILT_IN_BZERO:
1229 return validate_arglist (call, POINTER_TYPE, INTEGER_TYPE,
1236 /* Convert stringop (..., size)
1239 stringop (...., VALUE);
1241 stringop (...., size);
1242 assuming constant propagation of VALUE will happen later.
1245 tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
1248 tree stmt1, stmt2, stmt3;
1250 tree label_decl1 = create_artificial_label ();
1251 tree label_decl2 = create_artificial_label ();
1252 tree label1, label2;
1253 tree bb1end, bb2end;
1254 basic_block bb, bb2, bb3, bb4;
1255 edge e12, e13, e23, e24, e34;
1256 block_stmt_iterator bsi;
1257 tree call = get_call_expr_in (stmt);
1258 tree blck_size = CALL_EXPR_ARG (call, 2);
1259 tree optype = TREE_TYPE (blck_size);
1262 bb = bb_for_stmt (stmt);
1263 bsi = bsi_for_stmt (stmt);
1265 if (bsi_end_p (bsi))
1268 for (ei = ei_start (bb->succs); (e34 = ei_safe_edge (ei)); )
1269 if (!e34->flags & EDGE_ABNORMAL)
1274 e34 = split_block (bb, stmt);
1275 bsi = bsi_for_stmt (stmt);
1279 tmpv = create_tmp_var (optype, "PROF");
1280 tmp1 = create_tmp_var (optype, "PROF");
1281 stmt1 = build_gimple_modify_stmt (tmpv, fold_convert (optype, value));
1282 stmt2 = build_gimple_modify_stmt (tmp1, blck_size);
1283 stmt3 = build3 (COND_EXPR, void_type_node,
1284 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
1285 NULL_TREE, NULL_TREE);
1286 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1287 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
1288 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
1291 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
1292 stmt1 = unshare_expr (stmt);
1293 call = get_call_expr_in (stmt1);
1294 CALL_EXPR_ARG (call, 2) = value;
1295 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
1296 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1297 region = lookup_stmt_eh_region (stmt);
1299 add_stmt_to_eh_region (stmt1, region);
1301 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
1302 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
1305 /* Edge e23 connects bb2 to bb3, etc. */
1306 e12 = split_block (bb, bb1end);
1309 e23 = split_block (bb2, bb2end);
1311 bb3->count = all - count;
1313 e12->flags &= ~EDGE_FALLTHRU;
1314 e12->flags |= EDGE_FALSE_VALUE;
1315 e12->probability = prob;
1318 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1319 e13->probability = REG_BR_PROB_BASE - prob;
1320 e13->count = all - count;
1324 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1325 e24->probability = REG_BR_PROB_BASE;
1328 e34->probability = REG_BR_PROB_BASE;
1329 e34->count = all - count;
1332 /* Find values inside STMT for that we want to measure histograms for
1333 division/modulo optimization. */
1335 tree_stringops_transform (block_stmt_iterator *bsi)
1337 tree stmt = bsi_stmt (*bsi);
1338 tree call = get_call_expr_in (stmt);
1341 enum built_in_function fcode;
1342 histogram_value histogram;
1343 gcov_type count, all, val;
1346 unsigned int dest_align, src_align;
1352 fndecl = get_callee_fndecl (call);
1355 fcode = DECL_FUNCTION_CODE (fndecl);
1356 if (!interesting_stringop_to_profile_p (fndecl, call))
1359 if (fcode == BUILT_IN_BZERO)
1360 blck_size = CALL_EXPR_ARG (call, 1);
1362 blck_size = CALL_EXPR_ARG (call, 2);
1363 if (TREE_CODE (blck_size) == INTEGER_CST)
1366 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
1369 value = histogram->hvalue.value;
1370 val = histogram->hvalue.counters[0];
1371 count = histogram->hvalue.counters[1];
1372 all = histogram->hvalue.counters[2];
1373 gimple_remove_histogram_value (cfun, stmt, histogram);
1374 /* We require that count is at least half of all; this means
1375 that for the transformation to fire the value must be constant
1376 at least 80% of time. */
1377 if ((6 * count / 5) < all || !maybe_hot_bb_p (bb_for_stmt (stmt)))
1379 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
1381 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1382 dest = CALL_EXPR_ARG (call, 0);
1383 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1386 case BUILT_IN_MEMCPY:
1387 case BUILT_IN_MEMPCPY:
1388 src = CALL_EXPR_ARG (call, 1);
1389 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1390 if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
1393 case BUILT_IN_MEMSET:
1394 if (!can_store_by_pieces (val, builtin_memset_read_str,
1395 CALL_EXPR_ARG (call, 1),
1399 case BUILT_IN_BZERO:
1400 if (!can_store_by_pieces (val, builtin_memset_read_str,
1408 tree_val = build_int_cst_wide (get_gcov_type (),
1409 (unsigned HOST_WIDE_INT) val,
1410 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
1413 fprintf (dump_file, "Single value %i stringop transformation on ",
1415 print_generic_stmt (dump_file, stmt, TDF_SLIM);
1417 tree_stringop_fixed_value (stmt, tree_val, prob, count, all);
1423 stringop_block_profile (tree stmt, unsigned int *expected_align,
1424 HOST_WIDE_INT *expected_size)
1426 histogram_value histogram;
1427 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_AVERAGE);
1429 *expected_size = -1;
1430 else if (!histogram->hvalue.counters[1])
1432 *expected_size = -1;
1433 gimple_remove_histogram_value (cfun, stmt, histogram);
1438 size = ((histogram->hvalue.counters[0]
1439 + histogram->hvalue.counters[1] / 2)
1440 / histogram->hvalue.counters[1]);
1441 /* Even if we can hold bigger value in SIZE, INT_MAX
1442 is safe "infinity" for code generation strategies. */
1445 *expected_size = size;
1446 gimple_remove_histogram_value (cfun, stmt, histogram);
1448 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_IOR);
1450 *expected_align = 0;
1451 else if (!histogram->hvalue.counters[0])
1453 gimple_remove_histogram_value (cfun, stmt, histogram);
1454 *expected_align = 0;
1461 count = histogram->hvalue.counters[0];
1463 while (!(count & alignment)
1464 && (alignment * 2 * BITS_PER_UNIT))
1466 *expected_align = alignment * BITS_PER_UNIT;
1467 gimple_remove_histogram_value (cfun, stmt, histogram);
1471 struct value_prof_hooks {
1472 /* Find list of values for which we want to measure histograms. */
1473 void (*find_values_to_profile) (histogram_values *);
1475 /* Identify and exploit properties of values that are hard to analyze
1476 statically. See value-prof.c for more detail. */
1477 bool (*value_profile_transformations) (void);
1480 /* Find values inside STMT for that we want to measure histograms for
1481 division/modulo optimization. */
1483 tree_divmod_values_to_profile (tree stmt, histogram_values *values)
1485 tree assign, lhs, rhs, divisor, op0, type;
1486 histogram_value hist;
1488 if (TREE_CODE (stmt) == RETURN_EXPR)
1489 assign = TREE_OPERAND (stmt, 0);
1494 || TREE_CODE (assign) != GIMPLE_MODIFY_STMT)
1496 lhs = GIMPLE_STMT_OPERAND (assign, 0);
1497 type = TREE_TYPE (lhs);
1498 if (!INTEGRAL_TYPE_P (type))
1501 rhs = GIMPLE_STMT_OPERAND (assign, 1);
1502 switch (TREE_CODE (rhs))
1504 case TRUNC_DIV_EXPR:
1505 case TRUNC_MOD_EXPR:
1506 divisor = TREE_OPERAND (rhs, 1);
1507 op0 = TREE_OPERAND (rhs, 0);
1509 VEC_reserve (histogram_value, heap, *values, 3);
1511 if (is_gimple_reg (divisor))
1512 /* Check for the case where the divisor is the same value most
1514 VEC_quick_push (histogram_value, *values,
1515 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1518 /* For mod, check whether it is not often a noop (or replaceable by
1519 a few subtractions). */
1520 if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
1521 && TYPE_UNSIGNED (type))
1524 /* Check for a special case where the divisor is power of 2. */
1525 VEC_quick_push (histogram_value, *values,
1526 gimple_alloc_histogram_value (cfun, HIST_TYPE_POW2,
1529 val = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
1530 hist = gimple_alloc_histogram_value (cfun, HIST_TYPE_INTERVAL,
1532 hist->hdata.intvl.int_start = 0;
1533 hist->hdata.intvl.steps = 2;
1534 VEC_quick_push (histogram_value, *values, hist);
1543 /* Find calls inside STMT for that we want to measure histograms for
1544 indirect/virtual call optimization. */
1547 tree_indirect_call_to_profile (tree stmt, histogram_values *values)
1552 call = get_call_expr_in (stmt);
1554 if (!call || TREE_CODE (call) != CALL_EXPR)
1557 callee = CALL_EXPR_FN (call);
1559 if (TREE_CODE (callee) == ADDR_EXPR)
1562 VEC_reserve (histogram_value, heap, *values, 3);
1564 VEC_quick_push (histogram_value, *values,
1565 gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
1571 /* Find values inside STMT for that we want to measure histograms for
1572 string operations. */
1574 tree_stringops_values_to_profile (tree stmt, histogram_values *values)
1576 tree call = get_call_expr_in (stmt);
1580 enum built_in_function fcode;
1584 fndecl = get_callee_fndecl (call);
1587 fcode = DECL_FUNCTION_CODE (fndecl);
1589 if (!interesting_stringop_to_profile_p (fndecl, call))
1592 dest = CALL_EXPR_ARG (call, 0);
1593 if (fcode == BUILT_IN_BZERO)
1594 blck_size = CALL_EXPR_ARG (call, 1);
1596 blck_size = CALL_EXPR_ARG (call, 2);
1598 if (TREE_CODE (blck_size) != INTEGER_CST)
1600 VEC_safe_push (histogram_value, heap, *values,
1601 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1603 VEC_safe_push (histogram_value, heap, *values,
1604 gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE,
1607 if (TREE_CODE (blck_size) != INTEGER_CST)
1608 VEC_safe_push (histogram_value, heap, *values,
1609 gimple_alloc_histogram_value (cfun, HIST_TYPE_IOR,
1613 /* Find values inside STMT for that we want to measure histograms and adds
1614 them to list VALUES. */
1617 tree_values_to_profile (tree stmt, histogram_values *values)
1619 if (flag_value_profile_transformations)
1621 tree_divmod_values_to_profile (stmt, values);
1622 tree_stringops_values_to_profile (stmt, values);
1623 tree_indirect_call_to_profile (stmt, values);
1628 tree_find_values_to_profile (histogram_values *values)
1631 block_stmt_iterator bsi;
1633 histogram_value hist = NULL;
1637 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
1638 tree_values_to_profile (bsi_stmt (bsi), values);
1640 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
1644 case HIST_TYPE_INTERVAL:
1645 hist->n_counters = hist->hdata.intvl.steps + 2;
1648 case HIST_TYPE_POW2:
1649 hist->n_counters = 2;
1652 case HIST_TYPE_SINGLE_VALUE:
1653 hist->n_counters = 3;
1656 case HIST_TYPE_CONST_DELTA:
1657 hist->n_counters = 4;
1660 case HIST_TYPE_INDIR_CALL:
1661 hist->n_counters = 3;
1664 case HIST_TYPE_AVERAGE:
1665 hist->n_counters = 2;
1669 hist->n_counters = 1;
1677 fprintf (dump_file, "Stmt ");
1678 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
1679 dump_histogram_value (dump_file, hist);
1684 static struct value_prof_hooks tree_value_prof_hooks = {
1685 tree_find_values_to_profile,
1686 tree_value_profile_transformations
1690 tree_register_value_prof_hooks (void)
1692 gcc_assert (current_ir_type () == IR_GIMPLE);
1693 value_prof_hooks = &tree_value_prof_hooks;
1696 /* IR-independent entry points. */
1698 find_values_to_profile (histogram_values *values)
1700 (value_prof_hooks->find_values_to_profile) (values);
1704 value_profile_transformations (void)
1706 return (value_prof_hooks->value_profile_transformations) ();