2008-05-02 Doug Kwan <dougkwan@google.com>
[official-gcc.git] / gcc / value-prof.c
blob5fafbc1652288ca601958cbdf55b2eb5f7c06c8a
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
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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "rtl.h"
25 #include "expr.h"
26 #include "hard-reg-set.h"
27 #include "basic-block.h"
28 #include "value-prof.h"
29 #include "output.h"
30 #include "flags.h"
31 #include "insn-config.h"
32 #include "recog.h"
33 #include "optabs.h"
34 #include "regs.h"
35 #include "ggc.h"
36 #include "tree-flow.h"
37 #include "tree-flow-inline.h"
38 #include "diagnostic.h"
39 #include "coverage.h"
40 #include "tree.h"
41 #include "gcov-io.h"
42 #include "cgraph.h"
43 #include "timevar.h"
44 #include "tree-pass.h"
45 #include "toplev.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
61 profiling.
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
66 inliner).
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 gimple_divmod_fixed_value (gimple, tree, int, gcov_type, gcov_type);
81 static tree gimple_mod_pow2 (gimple, int, gcov_type, gcov_type);
82 static tree gimple_mod_subtract (gimple, int, int, int, gcov_type, gcov_type,
83 gcov_type);
84 static bool gimple_divmod_fixed_value_transform (gimple);
85 static bool gimple_mod_pow2_value_transform (gimple);
86 static bool gimple_mod_subtract_transform (gimple);
87 static bool gimple_stringops_transform (gimple_stmt_iterator *);
88 static bool gimple_ic_transform (gimple);
90 /* Allocate histogram value. */
92 static histogram_value
93 gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
94 enum hist_type type, gimple stmt, tree value)
96 histogram_value hist = (histogram_value) xcalloc (1, sizeof (*hist));
97 hist->hvalue.value = value;
98 hist->hvalue.stmt = stmt;
99 hist->type = type;
100 return hist;
103 /* Hash value for histogram. */
105 static hashval_t
106 histogram_hash (const void *x)
108 return htab_hash_pointer (((const_histogram_value)x)->hvalue.stmt);
111 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
113 static int
114 histogram_eq (const void *x, const void *y)
116 return ((const_histogram_value) x)->hvalue.stmt == (gimple)y;
119 /* Set histogram for STMT. */
121 static void
122 set_histogram_value (struct function *fun, gimple stmt, histogram_value hist)
124 void **loc;
125 if (!hist && !VALUE_HISTOGRAMS (fun))
126 return;
127 if (!VALUE_HISTOGRAMS (fun))
128 VALUE_HISTOGRAMS (fun) = htab_create (1, histogram_hash,
129 histogram_eq, NULL);
130 loc = htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun), stmt,
131 htab_hash_pointer (stmt),
132 hist ? INSERT : NO_INSERT);
133 if (!hist)
135 if (loc)
136 htab_clear_slot (VALUE_HISTOGRAMS (fun), loc);
137 return;
139 *loc = hist;
142 /* Get histogram list for STMT. */
144 histogram_value
145 gimple_histogram_value (struct function *fun, gimple stmt)
147 if (!VALUE_HISTOGRAMS (fun))
148 return NULL;
149 return htab_find_with_hash (VALUE_HISTOGRAMS (fun), stmt,
150 htab_hash_pointer (stmt));
153 /* Add histogram for STMT. */
155 void
156 gimple_add_histogram_value (struct function *fun, gimple stmt,
157 histogram_value hist)
159 hist->hvalue.next = gimple_histogram_value (fun, stmt);
160 set_histogram_value (fun, stmt, hist);
164 /* Remove histogram HIST from STMT's histogram list. */
166 void
167 gimple_remove_histogram_value (struct function *fun, gimple stmt,
168 histogram_value hist)
170 histogram_value hist2 = gimple_histogram_value (fun, stmt);
171 if (hist == hist2)
173 set_histogram_value (fun, stmt, hist->hvalue.next);
175 else
177 while (hist2->hvalue.next != hist)
178 hist2 = hist2->hvalue.next;
179 hist2->hvalue.next = hist->hvalue.next;
181 free (hist->hvalue.counters);
182 #ifdef ENABLE_CHECKING
183 memset (hist, 0xab, sizeof (*hist));
184 #endif
185 free (hist);
189 /* Lookup histogram of type TYPE in the STMT. */
191 histogram_value
192 gimple_histogram_value_of_type (struct function *fun, gimple stmt,
193 enum hist_type type)
195 histogram_value hist;
196 for (hist = gimple_histogram_value (fun, stmt); hist;
197 hist = hist->hvalue.next)
198 if (hist->type == type)
199 return hist;
200 return NULL;
203 /* Dump information about HIST to DUMP_FILE. */
205 static void
206 dump_histogram_value (FILE *dump_file, histogram_value hist)
208 switch (hist->type)
210 case HIST_TYPE_INTERVAL:
211 fprintf (dump_file, "Interval counter range %d -- %d",
212 hist->hdata.intvl.int_start,
213 (hist->hdata.intvl.int_start
214 + hist->hdata.intvl.steps - 1));
215 if (hist->hvalue.counters)
217 unsigned int i;
218 fprintf(dump_file, " [");
219 for (i = 0; i < hist->hdata.intvl.steps; i++)
220 fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
221 hist->hdata.intvl.int_start + i,
222 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
223 fprintf (dump_file, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC,
224 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
226 fprintf (dump_file, ".\n");
227 break;
229 case HIST_TYPE_POW2:
230 fprintf (dump_file, "Pow2 counter ");
231 if (hist->hvalue.counters)
233 fprintf (dump_file, "pow2:"HOST_WIDEST_INT_PRINT_DEC
234 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC,
235 (HOST_WIDEST_INT) hist->hvalue.counters[0],
236 (HOST_WIDEST_INT) hist->hvalue.counters[1]);
238 fprintf (dump_file, ".\n");
239 break;
241 case HIST_TYPE_SINGLE_VALUE:
242 fprintf (dump_file, "Single value ");
243 if (hist->hvalue.counters)
245 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
246 " match:"HOST_WIDEST_INT_PRINT_DEC
247 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
248 (HOST_WIDEST_INT) hist->hvalue.counters[0],
249 (HOST_WIDEST_INT) hist->hvalue.counters[1],
250 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
252 fprintf (dump_file, ".\n");
253 break;
255 case HIST_TYPE_AVERAGE:
256 fprintf (dump_file, "Average value ");
257 if (hist->hvalue.counters)
259 fprintf (dump_file, "sum:"HOST_WIDEST_INT_PRINT_DEC
260 " times:"HOST_WIDEST_INT_PRINT_DEC,
261 (HOST_WIDEST_INT) hist->hvalue.counters[0],
262 (HOST_WIDEST_INT) hist->hvalue.counters[1]);
264 fprintf (dump_file, ".\n");
265 break;
267 case HIST_TYPE_IOR:
268 fprintf (dump_file, "IOR value ");
269 if (hist->hvalue.counters)
271 fprintf (dump_file, "ior:"HOST_WIDEST_INT_PRINT_DEC,
272 (HOST_WIDEST_INT) hist->hvalue.counters[0]);
274 fprintf (dump_file, ".\n");
275 break;
277 case HIST_TYPE_CONST_DELTA:
278 fprintf (dump_file, "Constant delta ");
279 if (hist->hvalue.counters)
281 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
282 " match:"HOST_WIDEST_INT_PRINT_DEC
283 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
284 (HOST_WIDEST_INT) hist->hvalue.counters[0],
285 (HOST_WIDEST_INT) hist->hvalue.counters[1],
286 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
288 fprintf (dump_file, ".\n");
289 break;
290 case HIST_TYPE_INDIR_CALL:
291 fprintf (dump_file, "Indirect call ");
292 if (hist->hvalue.counters)
294 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
295 " match:"HOST_WIDEST_INT_PRINT_DEC
296 " all:"HOST_WIDEST_INT_PRINT_DEC,
297 (HOST_WIDEST_INT) hist->hvalue.counters[0],
298 (HOST_WIDEST_INT) hist->hvalue.counters[1],
299 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
301 fprintf (dump_file, ".\n");
302 break;
306 /* Dump all histograms attached to STMT to DUMP_FILE. */
308 void
309 dump_histograms_for_stmt (struct function *fun, FILE *dump_file, gimple stmt)
311 histogram_value hist;
312 for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
313 dump_histogram_value (dump_file, hist);
316 /* Remove all histograms associated with STMT. */
318 void
319 gimple_remove_stmt_histograms (struct function *fun, gimple stmt)
321 histogram_value val;
322 while ((val = gimple_histogram_value (fun, stmt)) != NULL)
323 gimple_remove_histogram_value (fun, stmt, val);
326 /* Duplicate all histograms associates with OSTMT to STMT. */
328 void
329 gimple_duplicate_stmt_histograms (struct function *fun, gimple stmt,
330 struct function *ofun, gimple ostmt)
332 histogram_value val;
333 for (val = gimple_histogram_value (ofun, ostmt); val != NULL; val = val->hvalue.next)
335 histogram_value new = gimple_alloc_histogram_value (fun, val->type, NULL, NULL);
336 memcpy (new, val, sizeof (*val));
337 new->hvalue.stmt = stmt;
338 new->hvalue.counters = xmalloc (sizeof (*new->hvalue.counters) * new->n_counters);
339 memcpy (new->hvalue.counters, val->hvalue.counters, sizeof (*new->hvalue.counters) * new->n_counters);
340 gimple_add_histogram_value (fun, stmt, new);
344 static bool error_found = false;
346 /* Helper function for verify_histograms. For each histogram reachable via htab
347 walk verify that it was reached via statement walk. */
349 static int
350 visit_hist (void **slot, void *data)
352 struct pointer_set_t *visited = (struct pointer_set_t *) data;
353 histogram_value hist = *(histogram_value *) slot;
354 if (!pointer_set_contains (visited, hist))
356 error ("Dead histogram");
357 dump_histogram_value (stderr, hist);
358 debug_gimple_stmt (hist->hvalue.stmt);
359 error_found = true;
361 return 1;
365 /* Verify sanity of the histograms. */
367 void
368 verify_histograms (void)
370 basic_block bb;
371 gimple_stmt_iterator gsi;
372 histogram_value hist;
373 struct pointer_set_t *visited_hists;
375 error_found = false;
376 visited_hists = pointer_set_create ();
377 FOR_EACH_BB (bb)
378 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
380 gimple stmt = gsi_stmt (gsi);
382 for (hist = gimple_histogram_value (cfun, stmt); hist;
383 hist = hist->hvalue.next)
385 if (hist->hvalue.stmt != stmt)
387 error ("Histogram value statement does not correspond to "
388 "the statement it is associated with");
389 debug_gimple_stmt (stmt);
390 dump_histogram_value (stderr, hist);
391 error_found = true;
393 pointer_set_insert (visited_hists, hist);
396 if (VALUE_HISTOGRAMS (cfun))
397 htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
398 pointer_set_destroy (visited_hists);
399 if (error_found)
400 internal_error ("verify_histograms failed");
403 /* Helper function for verify_histograms. For each histogram reachable via htab
404 walk verify that it was reached via statement walk. */
406 static int
407 free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
409 histogram_value hist = *(histogram_value *) slot;
410 free (hist->hvalue.counters);
411 #ifdef ENABLE_CHECKING
412 memset (hist, 0xab, sizeof (*hist));
413 #endif
414 free (hist);
415 return 1;
418 void
419 free_histograms (void)
421 if (VALUE_HISTOGRAMS (cfun))
423 htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
424 htab_delete (VALUE_HISTOGRAMS (cfun));
425 VALUE_HISTOGRAMS (cfun) = NULL;
430 /* The overall number of invocations of the counter should match
431 execution count of basic block. Report it as error rather than
432 internal error as it might mean that user has misused the profile
433 somehow. */
435 static bool
436 check_counter (gimple stmt, const char *name, gcov_type all, gcov_type bb_count)
438 if (all != bb_count)
440 location_t locus;
441 locus = (stmt != NULL)
442 ? gimple_location (stmt)
443 : DECL_SOURCE_LOCATION (current_function_decl);
444 error ("%HCorrupted value profile: %s profiler overall count (%d) "
445 "does not match BB count (%d)", &locus, name, (int)all,
446 (int)bb_count);
447 return true;
450 return false;
454 /* GIMPLE based transformations. */
456 static bool
457 gimple_value_profile_transformations (void)
459 basic_block bb;
460 gimple_stmt_iterator gsi;
461 bool changed = false;
463 FOR_EACH_BB (bb)
465 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
467 gimple stmt = gsi_stmt (gsi);
468 histogram_value th = gimple_histogram_value (cfun, stmt);
469 if (!th)
470 continue;
472 if (dump_file)
474 fprintf (dump_file, "Trying transformations on stmt ");
475 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
476 dump_histograms_for_stmt (cfun, dump_file, stmt);
479 /* Transformations: */
480 /* The order of things in this conditional controls which
481 transformation is used when more than one is applicable. */
482 /* It is expected that any code added by the transformations
483 will be added before the current statement, and that the
484 current statement remain valid (although possibly
485 modified) upon return. */
486 if (flag_value_profile_transformations
487 && (gimple_mod_subtract_transform (stmt)
488 || gimple_divmod_fixed_value_transform (stmt)
489 || gimple_mod_pow2_value_transform (stmt)
490 || gimple_stringops_transform (&gsi)
491 || gimple_ic_transform (stmt)))
493 stmt = gsi_stmt (gsi);
494 changed = true;
495 /* Original statement may no longer be in the same block. */
496 if (bb != gimple_bb (stmt))
498 bb = gimple_bb (stmt);
499 gsi = gsi_for_stmt (stmt);
505 if (changed)
507 counts_to_freqs ();
510 return changed;
514 /* Generate code for transformation 1 (with parent gimple assignment
515 STMT and probability of taking the optimal path PROB, which is
516 equivalent to COUNT/ALL within roundoff error). This generates the
517 result into a temp and returns the temp; it does not replace or
518 alter the original STMT. */
520 static tree
521 gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
522 gcov_type all)
524 gimple stmt1, stmt2, stmt3, label1, label2;
525 tree tmp1, tmp2, tmpv;
526 tree label_decl1 = create_artificial_label ();
527 tree label_decl2 = create_artificial_label ();
528 gimple bb1end, bb2end, bb3end;
529 basic_block bb, bb2, bb3, bb4;
530 tree optype, op1, op2;
531 edge e12, e13, e23, e24, e34;
532 gimple_stmt_iterator gsi;
534 gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN
535 && (gimple_subcode (stmt) == TRUNC_DIV_EXPR
536 || gimple_subcode (stmt) == TRUNC_MOD_EXPR));
538 optype = TREE_TYPE (gimple_assign_lhs (stmt));
539 op1 = gimple_assign_rhs1 (stmt);
540 op2 = gimple_assign_rhs2 (stmt);
542 bb = gimple_bb (stmt);
543 gsi = gsi_for_stmt (stmt);
545 tmpv = create_tmp_var (optype, "PROF");
546 tmp1 = create_tmp_var (optype, "PROF");
547 stmt1 = gimple_build_assign (tmpv, fold_convert (optype, value));
548 stmt2 = gimple_build_assign (tmp1, op2);
549 stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
550 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
551 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
552 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
553 bb1end = stmt3;
555 tmp2 = create_tmp_var (optype, "PROF");
556 label1 = gimple_build_label (label_decl1);
557 stmt1 = gimple_build_assign_with_ops (gimple_subcode (stmt), tmp2, op1, tmpv);
558 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
559 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
560 bb2end = stmt1;
562 label2 = gimple_build_label (label_decl2);
563 stmt1 = gimple_build_assign_with_ops (gimple_subcode (stmt), tmp2, op1, op2);
564 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
565 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
566 bb3end = stmt1;
568 /* Fix CFG. */
569 /* Edge e23 connects bb2 to bb3, etc. */
570 e12 = split_block (bb, bb1end);
571 bb2 = e12->dest;
572 bb2->count = count;
573 e23 = split_block (bb2, bb2end);
574 bb3 = e23->dest;
575 bb3->count = all - count;
576 e34 = split_block (bb3, bb3end);
577 bb4 = e34->dest;
578 bb4->count = all;
580 e12->flags &= ~EDGE_FALLTHRU;
581 e12->flags |= EDGE_FALSE_VALUE;
582 e12->probability = prob;
583 e12->count = count;
585 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
586 e13->probability = REG_BR_PROB_BASE - prob;
587 e13->count = all - count;
589 remove_edge (e23);
591 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
592 e24->probability = REG_BR_PROB_BASE;
593 e24->count = count;
595 e34->probability = REG_BR_PROB_BASE;
596 e34->count = all - count;
598 return tmp2;
602 /* Do transform 1) on INSN if applicable. */
604 static bool
605 gimple_divmod_fixed_value_transform (gimple stmt)
607 histogram_value histogram;
608 enum tree_code code;
609 gcov_type val, count, all;
610 tree result, value, tree_val;
611 int prob;
613 if (gimple_code (stmt) != GIMPLE_ASSIGN)
614 return false;
616 if (!INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt))))
617 return false;
619 code = gimple_assign_rhs_code (stmt);
621 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
622 return false;
624 histogram = gimple_histogram_value_of_type (cfun, stmt,
625 HIST_TYPE_SINGLE_VALUE);
626 if (!histogram)
627 return false;
629 value = histogram->hvalue.value;
630 val = histogram->hvalue.counters[0];
631 count = histogram->hvalue.counters[1];
632 all = histogram->hvalue.counters[2];
633 gimple_remove_histogram_value (cfun, stmt, histogram);
635 /* We require that count is at least half of all; this means
636 that for the transformation to fire the value must be constant
637 at least 50% of time (and 75% gives the guarantee of usage). */
638 if (simple_cst_equal (gimple_assign_rhs2 (stmt), value) != 1
639 || 2 * count < all
640 || !maybe_hot_bb_p (gimple_bb (stmt)))
641 return false;
643 if (check_counter (stmt, "value", all, gimple_bb (stmt)->count))
644 return false;
646 /* Compute probability of taking the optimal path. */
647 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
649 tree_val = build_int_cst_wide (get_gcov_type (),
650 (unsigned HOST_WIDE_INT) val,
651 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
652 result = gimple_divmod_fixed_value (stmt, tree_val, prob, count, all);
654 if (dump_file)
656 fprintf (dump_file, "Div/mod by constant ");
657 print_generic_expr (dump_file, value, TDF_SLIM);
658 fprintf (dump_file, "=");
659 print_generic_expr (dump_file, tree_val, TDF_SLIM);
660 fprintf (dump_file, " transformation on insn ");
661 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
664 gimple_assign_set_rhs_from_tree (stmt, result);
666 return true;
669 /* Generate code for transformation 2 (with parent gimple assign STMT and
670 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
671 within roundoff error). This generates the result into a temp and returns
672 the temp; it does not replace or alter the original STMT. */
673 static tree
674 gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
676 gimple stmt1, stmt2, stmt3, stmt4;
677 tree tmp2, tmp3;
678 tree label_decl1 = create_artificial_label ();
679 tree label_decl2 = create_artificial_label ();
680 gimple label1, label2;
681 gimple bb1end, bb2end, bb3end;
682 basic_block bb, bb2, bb3, bb4;
683 tree optype, op1, op2;
684 edge e12, e13, e23, e24, e34;
685 gimple_stmt_iterator gsi;
686 tree result;
688 gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN
689 && gimple_subcode (stmt) == TRUNC_MOD_EXPR);
691 optype = TREE_TYPE (gimple_assign_lhs (stmt));
692 op1 = gimple_assign_rhs1 (stmt);
693 op2 = gimple_assign_rhs2 (stmt);
695 bb = gimple_bb (stmt);
696 gsi = gsi_for_stmt (stmt);
698 result = create_tmp_var (optype, "PROF");
699 tmp2 = create_tmp_var (optype, "PROF");
700 tmp3 = create_tmp_var (optype, "PROF");
701 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2,
702 build_int_cst (optype, -1));
703 stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2);
704 stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0),
705 NULL_TREE, NULL_TREE);
706 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
707 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
708 gsi_insert_before (&gsi, stmt4, GSI_SAME_STMT);
709 bb1end = stmt4;
711 /* tmp2 == op2-1 inherited from previous block */
712 label1 = gimple_build_label (label_decl1);
713 stmt1 = gimple_build_assign_with_ops (BIT_AND_EXPR, result, op1, tmp2);
714 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
715 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
716 bb2end = stmt1;
718 label2 = gimple_build_label (label_decl2);
719 stmt1 = gimple_build_assign_with_ops (gimple_subcode (stmt), result, op1, op2);
720 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
721 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
722 bb3end = stmt1;
724 /* Fix CFG. */
725 /* Edge e23 connects bb2 to bb3, etc. */
726 e12 = split_block (bb, bb1end);
727 bb2 = e12->dest;
728 bb2->count = count;
729 e23 = split_block (bb2, bb2end);
730 bb3 = e23->dest;
731 bb3->count = all - count;
732 e34 = split_block (bb3, bb3end);
733 bb4 = e34->dest;
734 bb4->count = all;
736 e12->flags &= ~EDGE_FALLTHRU;
737 e12->flags |= EDGE_FALSE_VALUE;
738 e12->probability = prob;
739 e12->count = count;
741 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
742 e13->probability = REG_BR_PROB_BASE - prob;
743 e13->count = all - count;
745 remove_edge (e23);
747 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
748 e24->probability = REG_BR_PROB_BASE;
749 e24->count = count;
751 e34->probability = REG_BR_PROB_BASE;
752 e34->count = all - count;
754 return result;
757 /* Do transform 2) on INSN if applicable. */
758 static bool
759 gimple_mod_pow2_value_transform (gimple stmt)
761 histogram_value histogram;
762 enum tree_code code;
763 gcov_type count, wrong_values, all;
764 tree lhs_type, result, value;
765 int prob;
767 if (gimple_code (stmt) != GIMPLE_ASSIGN)
768 return false;
770 lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
771 if (!INTEGRAL_TYPE_P (lhs_type))
772 return false;
774 code = gimple_assign_rhs_code (stmt);
776 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (lhs_type))
777 return false;
779 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_POW2);
780 if (!histogram)
781 return false;
783 value = histogram->hvalue.value;
784 wrong_values = histogram->hvalue.counters[0];
785 count = histogram->hvalue.counters[1];
787 gimple_remove_histogram_value (cfun, stmt, histogram);
789 /* We require that we hit a power of 2 at least half of all evaluations. */
790 if (simple_cst_equal (gimple_assign_rhs2 (stmt), value) != 1
791 || count < wrong_values
792 || !maybe_hot_bb_p (gimple_bb (stmt)))
793 return false;
795 if (dump_file)
797 fprintf (dump_file, "Mod power of 2 transformation on insn ");
798 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
801 /* Compute probability of taking the optimal path. */
802 all = count + wrong_values;
804 if (check_counter (stmt, "pow2", all, gimple_bb (stmt)->count))
805 return false;
807 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
809 result = gimple_mod_pow2 (stmt, prob, count, all);
811 gimple_assign_set_rhs_from_tree (stmt, result);
813 return true;
816 /* Generate code for transformations 3 and 4 (with parent gimple assign STMT, and
817 NCOUNTS the number of cases to support. Currently only NCOUNTS==0 or 1 is
818 supported and this is built into this interface. The probabilities of taking
819 the optimal paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
820 COUNT2/ALL respectively within roundoff error). This generates the
821 result into a temp and returns the temp; it does not replace or alter
822 the original STMT. */
823 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
825 static tree
826 gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts,
827 gcov_type count1, gcov_type count2, gcov_type all)
829 gimple stmt1, stmt2, stmt3;
830 tree tmp1;
831 tree label_decl1 = create_artificial_label ();
832 tree label_decl2 = create_artificial_label ();
833 tree label_decl3 = create_artificial_label ();
834 gimple label1, label2, label3;
835 gimple bb1end, bb2end = NULL, bb3end;
836 basic_block bb, bb2, bb3, bb4;
837 tree optype, op1, op2;
838 edge e12, e23 = 0, e24, e34, e14;
839 gimple_stmt_iterator gsi;
840 tree result;
842 gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN
843 && gimple_subcode (stmt) == TRUNC_MOD_EXPR);
845 optype = TREE_TYPE (gimple_assign_lhs (stmt));
846 op1 = gimple_assign_rhs1 (stmt);
847 op2 = gimple_assign_rhs2 (stmt);
849 bb = gimple_bb (stmt);
850 gsi = gsi_for_stmt (stmt);
852 result = create_tmp_var (optype, "PROF");
853 tmp1 = create_tmp_var (optype, "PROF");
854 stmt1 = gimple_build_assign (result, op1);
855 stmt2 = gimple_build_assign (tmp1, op2);
856 stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
857 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
858 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
859 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
860 bb1end = stmt3;
862 if (ncounts) /* Assumed to be 0 or 1 */
864 label1 = gimple_build_label (label_decl1);
865 stmt1 = gimple_build_assign_with_ops (MINUS_EXPR, result, result, tmp1);
866 stmt2 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
867 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
868 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
869 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
870 bb2end = stmt2;
873 /* Fallback case. */
874 label2 = gimple_build_label (label_decl2);
875 stmt1 = gimple_build_assign_with_ops (gimple_subcode (stmt), result, result,
876 tmp1);
877 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
878 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
879 bb3end = stmt1;
881 label3 = gimple_build_label (label_decl3);
882 gsi_insert_before (&gsi, label3, GSI_SAME_STMT);
884 /* Fix CFG. */
885 /* Edge e23 connects bb2 to bb3, etc. */
886 /* However block 3 is optional; if it is not there, references
887 to 3 really refer to block 2. */
888 e12 = split_block (bb, bb1end);
889 bb2 = e12->dest;
890 bb2->count = all - count1;
892 if (ncounts) /* Assumed to be 0 or 1. */
894 e23 = split_block (bb2, bb2end);
895 bb3 = e23->dest;
896 bb3->count = all - count1 - count2;
899 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
900 bb4 = e34->dest;
901 bb4->count = all;
903 e12->flags &= ~EDGE_FALLTHRU;
904 e12->flags |= EDGE_FALSE_VALUE;
905 e12->probability = REG_BR_PROB_BASE - prob1;
906 e12->count = all - count1;
908 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
909 e14->probability = prob1;
910 e14->count = count1;
912 if (ncounts) /* Assumed to be 0 or 1. */
914 e23->flags &= ~EDGE_FALLTHRU;
915 e23->flags |= EDGE_FALSE_VALUE;
916 e23->count = all - count1 - count2;
917 e23->probability = REG_BR_PROB_BASE - prob2;
919 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
920 e24->probability = prob2;
921 e24->count = count2;
924 e34->probability = REG_BR_PROB_BASE;
925 e34->count = all - count1 - count2;
927 return result;
931 /* Do transforms 3) and 4) on STMT if applicable. */
933 static bool
934 gimple_mod_subtract_transform (gimple stmt)
936 histogram_value histogram;
937 enum tree_code code;
938 gcov_type count, wrong_values, all;
939 tree lhs_type, result, value;
940 int prob1, prob2;
941 unsigned int i, steps;
942 gcov_type count1, count2;
944 if (gimple_code (stmt) != GIMPLE_ASSIGN)
945 return false;
947 lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
948 if (!INTEGRAL_TYPE_P (lhs_type))
949 return false;
951 code = gimple_assign_rhs_code (stmt);
953 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (lhs_type))
954 return false;
956 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INTERVAL);
957 if (!histogram)
958 return false;
960 value = histogram->hvalue.value;
961 all = 0;
962 wrong_values = 0;
963 for (i = 0; i < histogram->hdata.intvl.steps; i++)
964 all += histogram->hvalue.counters[i];
966 wrong_values += histogram->hvalue.counters[i];
967 wrong_values += histogram->hvalue.counters[i+1];
968 steps = histogram->hdata.intvl.steps;
969 all += wrong_values;
970 count1 = histogram->hvalue.counters[0];
971 count2 = histogram->hvalue.counters[1];
973 /* Compute probability of taking the optimal path. */
974 if (check_counter (stmt, "interval", all, gimple_bb (stmt)->count))
976 gimple_remove_histogram_value (cfun, stmt, histogram);
977 return false;
980 /* We require that we use just subtractions in at least 50% of all
981 evaluations. */
982 count = 0;
983 for (i = 0; i < histogram->hdata.intvl.steps; i++)
985 count += histogram->hvalue.counters[i];
986 if (count * 2 >= all)
987 break;
989 if (i == steps
990 || !maybe_hot_bb_p (gimple_bb (stmt)))
991 return false;
993 gimple_remove_histogram_value (cfun, stmt, histogram);
994 if (dump_file)
996 fprintf (dump_file, "Mod subtract transformation on insn ");
997 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1000 /* Compute probability of taking the optimal path(s). */
1001 prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
1002 prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
1004 /* In practice, "steps" is always 2. This interface reflects this,
1005 and will need to be changed if "steps" can change. */
1006 result = gimple_mod_subtract (stmt, prob1, prob2, i, count1, count2, all);
1008 gimple_assign_set_rhs_from_tree (stmt, result);
1010 return true;
1013 static struct cgraph_node** pid_map = NULL;
1015 /* Initialize map of pids (pid -> cgraph node) */
1017 static void
1018 init_pid_map (void)
1020 struct cgraph_node *n;
1022 if (pid_map != NULL)
1023 return;
1025 pid_map
1026 = (struct cgraph_node**) xmalloc (sizeof (struct cgraph_node*) * cgraph_max_pid);
1028 for (n = cgraph_nodes; n; n = n->next)
1030 if (n->pid != -1)
1031 pid_map [n->pid] = n;
1035 /* Return cgraph node for function with pid */
1037 static inline struct cgraph_node*
1038 find_func_by_pid (int pid)
1040 init_pid_map ();
1042 return pid_map [pid];
1045 /* Do transformation
1047 if (actual_callee_addres == addres_of_most_common_function/method)
1048 do direct call
1049 else
1050 old call
1053 static gimple
1054 gimple_ic (gimple stmt, gimple call, struct cgraph_node *direct_call,
1055 int prob, gcov_type count, gcov_type all)
1057 gimple stmt1, stmt2, stmt3;
1058 tree tmp1, tmpv, tmp;
1059 tree label_decl1 = create_artificial_label ();
1060 tree label_decl2 = create_artificial_label ();
1061 gimple label1, label2;
1062 gimple 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 gimple_stmt_iterator gsi;
1067 int region;
1069 bb = gimple_bb (stmt);
1070 gsi = gsi_for_stmt (stmt);
1072 tmpv = create_tmp_var (optype, "PROF");
1073 tmp1 = create_tmp_var (optype, "PROF");
1074 stmt1 = gimple_build_assign (tmpv, unshare_expr (gimple_call_fn (call)));
1076 tmp = fold_convert (optype, build_addr (direct_call->decl,
1077 current_function_decl));
1078 stmt2 = gimple_build_assign (tmp1, tmp);
1079 stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
1080 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
1081 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
1082 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
1083 bb1end = stmt3;
1085 label1 = gimple_build_label (label_decl1);
1086 stmt1 = gimple_copy (stmt);
1087 gimple_call_set_fn (stmt,
1088 build_addr (direct_call->decl, current_function_decl));
1089 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
1090 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
1091 bb2end = stmt1;
1093 label2 = gimple_build_label (label_decl2);
1094 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
1095 bb3end = stmt;
1097 /* Fix CFG. */
1098 /* Edge e23 connects bb2 to bb3, etc. */
1099 e12 = split_block (bb, bb1end);
1100 bb2 = e12->dest;
1101 bb2->count = count;
1102 e23 = split_block (bb2, bb2end);
1103 bb3 = e23->dest;
1104 bb3->count = all - count;
1105 e34 = split_block (bb3, bb3end);
1106 bb4 = e34->dest;
1107 bb4->count = all;
1109 e12->flags &= ~EDGE_FALLTHRU;
1110 e12->flags |= EDGE_FALSE_VALUE;
1111 e12->probability = prob;
1112 e12->count = count;
1114 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1115 e13->probability = REG_BR_PROB_BASE - prob;
1116 e13->count = all - count;
1118 remove_edge (e23);
1120 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1121 e24->probability = REG_BR_PROB_BASE;
1122 e24->count = count;
1123 e34->probability = REG_BR_PROB_BASE;
1124 e34->count = all - count;
1126 /* Fix eh edges */
1127 region = lookup_stmt_eh_region (stmt);
1128 if (region >= 0 && stmt_could_throw_p (stmt1))
1130 add_stmt_to_eh_region (stmt1, region);
1131 make_eh_edges (stmt1);
1134 if (region >= 0 && stmt_could_throw_p (stmt))
1136 gimple_purge_dead_eh_edges (bb4);
1137 make_eh_edges (stmt);
1140 return stmt1;
1144 For every checked indirect/virtual call determine if most common pid of
1145 function/class method has probability more than 50%. If yes modify code of
1146 this call to:
1149 static bool
1150 gimple_ic_transform (gimple stmt)
1152 histogram_value histogram;
1153 gcov_type val, count, all;
1154 int prob;
1155 tree callee;
1156 gimple modify;
1157 struct cgraph_node *direct_call;
1159 if (gimple_code (stmt) != GIMPLE_CALL)
1160 return false;
1162 callee = gimple_call_fn (stmt);
1164 if (TREE_CODE (callee) == FUNCTION_DECL)
1165 return false;
1167 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
1168 if (!histogram)
1169 return false;
1171 val = histogram->hvalue.counters [0];
1172 count = histogram->hvalue.counters [1];
1173 all = histogram->hvalue.counters [2];
1174 gimple_remove_histogram_value (cfun, stmt, histogram);
1176 if (4 * count <= 3 * all)
1177 return false;
1179 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1180 direct_call = find_func_by_pid ((int)val);
1182 if (direct_call == NULL)
1183 return false;
1185 modify = gimple_ic (stmt, stmt, direct_call, prob, count, all);
1187 if (dump_file)
1189 fprintf (dump_file, "Indirect call -> direct call ");
1190 print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM);
1191 fprintf (dump_file, "=> ");
1192 print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
1193 fprintf (dump_file, " transformation on insn ");
1194 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1195 fprintf (dump_file, " to ");
1196 print_gimple_stmt (dump_file, modify, 0, TDF_SLIM);
1199 return true;
1202 /* Return true if the stringop CALL with FNDECL shall be profiled. */
1203 static bool
1204 interesting_stringop_to_profile_p (tree fndecl, gimple call)
1206 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
1208 if (fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_MEMCPY
1209 && fcode != BUILT_IN_BZERO)
1210 return false;
1212 switch (fcode)
1214 case BUILT_IN_MEMCPY:
1215 case BUILT_IN_MEMPCPY:
1216 return validate_gimple_arglist (call, POINTER_TYPE, POINTER_TYPE,
1217 INTEGER_TYPE, VOID_TYPE);
1218 case BUILT_IN_MEMSET:
1219 return validate_gimple_arglist (call, POINTER_TYPE, INTEGER_TYPE,
1220 INTEGER_TYPE, VOID_TYPE);
1221 case BUILT_IN_BZERO:
1222 return validate_gimple_arglist (call, POINTER_TYPE, INTEGER_TYPE,
1223 VOID_TYPE);
1224 default:
1225 gcc_unreachable ();
1229 /* Convert stringop (..., size)
1230 into
1231 if (size == VALUE)
1232 stringop (...., VALUE);
1233 else
1234 stringop (...., size);
1235 assuming constant propagation of VALUE will happen later.
1237 static void
1238 gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
1239 gcov_type all)
1241 gimple stmt1, stmt2, stmt3;
1242 tree tmp1, tmpv;
1243 tree label_decl1 = create_artificial_label ();
1244 tree label_decl2 = create_artificial_label ();
1245 gimple label1, label2;
1246 gimple bb1end, bb2end;
1247 basic_block bb, bb2, bb3, bb4;
1248 edge e12, e13, e23, e24, e34;
1249 gimple_stmt_iterator gsi;
1250 tree blck_size = gimple_call_arg (stmt, 2);
1251 tree optype = TREE_TYPE (blck_size);
1252 int region;
1254 bb = gimple_bb (stmt);
1255 gsi = gsi_for_stmt (stmt);
1257 if (gsi_end_p (gsi))
1259 edge_iterator ei;
1260 for (ei = ei_start (bb->succs); (e34 = ei_safe_edge (ei)); )
1261 if (!e34->flags & EDGE_ABNORMAL)
1262 break;
1264 else
1266 e34 = split_block (bb, stmt);
1267 gsi = gsi_for_stmt (stmt);
1269 bb4 = e34->dest;
1271 tmpv = create_tmp_var (optype, "PROF");
1272 tmp1 = create_tmp_var (optype, "PROF");
1273 stmt1 = gimple_build_assign (tmpv, fold_convert (optype, value));
1274 stmt2 = gimple_build_assign (tmp1, blck_size);
1275 stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
1276 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
1277 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
1278 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
1279 bb1end = stmt3;
1281 label1 = gimple_build_label (label_decl1);
1282 stmt1 = gimple_copy (stmt);
1283 gimple_call_set_arg (stmt1, 2, value);
1284 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
1285 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
1286 region = lookup_stmt_eh_region (stmt);
1287 if (region >= 0)
1288 add_stmt_to_eh_region (stmt1, region);
1289 bb2end = stmt1;
1290 label2 = gimple_build_label (label_decl2);
1291 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
1293 /* Fix CFG. */
1294 /* Edge e23 connects bb2 to bb3, etc. */
1295 e12 = split_block (bb, bb1end);
1296 bb2 = e12->dest;
1297 bb2->count = count;
1298 e23 = split_block (bb2, bb2end);
1299 bb3 = e23->dest;
1300 bb3->count = all - count;
1302 e12->flags &= ~EDGE_FALLTHRU;
1303 e12->flags |= EDGE_FALSE_VALUE;
1304 e12->probability = prob;
1305 e12->count = count;
1307 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1308 e13->probability = REG_BR_PROB_BASE - prob;
1309 e13->count = all - count;
1311 remove_edge (e23);
1313 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1314 e24->probability = REG_BR_PROB_BASE;
1315 e24->count = count;
1317 e34->probability = REG_BR_PROB_BASE;
1318 e34->count = all - count;
1321 /* Find values inside STMT for that we want to measure histograms for
1322 division/modulo optimization. */
1323 static bool
1324 gimple_stringops_transform (gimple_stmt_iterator *gsi)
1326 gimple stmt = gsi_stmt (*gsi);
1327 tree fndecl;
1328 tree blck_size;
1329 enum built_in_function fcode;
1330 histogram_value histogram;
1331 gcov_type count, all, val;
1332 tree value;
1333 tree dest, src;
1334 unsigned int dest_align, src_align;
1335 int prob;
1336 tree tree_val;
1338 if (gimple_code (stmt) != GIMPLE_CALL)
1339 return false;
1340 fndecl = gimple_call_fndecl (stmt);
1341 if (!fndecl)
1342 return false;
1343 fcode = DECL_FUNCTION_CODE (fndecl);
1344 if (!interesting_stringop_to_profile_p (fndecl, stmt))
1345 return false;
1347 if (fcode == BUILT_IN_BZERO)
1348 blck_size = gimple_call_arg (stmt, 1);
1349 else
1350 blck_size = gimple_call_arg (stmt, 2);
1351 if (TREE_CODE (blck_size) == INTEGER_CST)
1352 return false;
1354 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
1355 if (!histogram)
1356 return false;
1357 value = histogram->hvalue.value;
1358 val = histogram->hvalue.counters[0];
1359 count = histogram->hvalue.counters[1];
1360 all = histogram->hvalue.counters[2];
1361 gimple_remove_histogram_value (cfun, stmt, histogram);
1362 /* We require that count is at least half of all; this means
1363 that for the transformation to fire the value must be constant
1364 at least 80% of time. */
1365 if ((6 * count / 5) < all || !maybe_hot_bb_p (gimple_bb (stmt)))
1366 return false;
1367 if (check_counter (stmt, "value", all, gimple_bb (stmt)->count))
1368 return false;
1369 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1370 dest = gimple_call_arg (stmt, 0);
1371 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1372 switch (fcode)
1374 case BUILT_IN_MEMCPY:
1375 case BUILT_IN_MEMPCPY:
1376 src = gimple_call_arg (stmt, 1);
1377 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1378 if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
1379 return false;
1380 break;
1381 case BUILT_IN_MEMSET:
1382 if (!can_store_by_pieces (val, builtin_memset_read_str,
1383 gimple_call_arg (stmt, 1),
1384 dest_align, true))
1385 return false;
1386 break;
1387 case BUILT_IN_BZERO:
1388 if (!can_store_by_pieces (val, builtin_memset_read_str,
1389 integer_zero_node,
1390 dest_align, true))
1391 return false;
1392 break;
1393 default:
1394 gcc_unreachable ();
1396 tree_val = build_int_cst_wide (get_gcov_type (),
1397 (unsigned HOST_WIDE_INT) val,
1398 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
1399 if (dump_file)
1401 fprintf (dump_file, "Single value %i stringop transformation on ",
1402 (int)val);
1403 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1405 gimple_stringop_fixed_value (stmt, tree_val, prob, count, all);
1407 return true;
1410 void
1411 stringop_block_profile (gimple stmt, unsigned int *expected_align,
1412 HOST_WIDE_INT *expected_size)
1414 histogram_value histogram;
1415 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_AVERAGE);
1416 if (!histogram)
1417 *expected_size = -1;
1418 else if (!histogram->hvalue.counters[1])
1420 *expected_size = -1;
1421 gimple_remove_histogram_value (cfun, stmt, histogram);
1423 else
1425 gcov_type size;
1426 size = ((histogram->hvalue.counters[0]
1427 + histogram->hvalue.counters[1] / 2)
1428 / histogram->hvalue.counters[1]);
1429 /* Even if we can hold bigger value in SIZE, INT_MAX
1430 is safe "infinity" for code generation strategies. */
1431 if (size > INT_MAX)
1432 size = INT_MAX;
1433 *expected_size = size;
1434 gimple_remove_histogram_value (cfun, stmt, histogram);
1436 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_IOR);
1437 if (!histogram)
1438 *expected_align = 0;
1439 else if (!histogram->hvalue.counters[0])
1441 gimple_remove_histogram_value (cfun, stmt, histogram);
1442 *expected_align = 0;
1444 else
1446 gcov_type count;
1447 int alignment;
1449 count = histogram->hvalue.counters[0];
1450 alignment = 1;
1451 while (!(count & alignment)
1452 && (alignment * 2 * BITS_PER_UNIT))
1453 alignment <<= 1;
1454 *expected_align = alignment * BITS_PER_UNIT;
1455 gimple_remove_histogram_value (cfun, stmt, histogram);
1459 struct value_prof_hooks {
1460 /* Find list of values for which we want to measure histograms. */
1461 void (*find_values_to_profile) (histogram_values *);
1463 /* Identify and exploit properties of values that are hard to analyze
1464 statically. See value-prof.c for more detail. */
1465 bool (*value_profile_transformations) (void);
1468 /* Find values inside STMT for that we want to measure histograms for
1469 division/modulo optimization. */
1470 static void
1471 gimple_divmod_values_to_profile (gimple stmt, histogram_values *values)
1473 tree lhs, divisor, op0, type;
1474 histogram_value hist;
1476 if (gimple_code (stmt) != GIMPLE_ASSIGN)
1477 return;
1479 lhs = gimple_assign_lhs (stmt);
1480 type = TREE_TYPE (lhs);
1481 if (!INTEGRAL_TYPE_P (type))
1482 return;
1484 switch (gimple_subcode (stmt))
1486 case TRUNC_DIV_EXPR:
1487 case TRUNC_MOD_EXPR:
1488 divisor = gimple_assign_rhs2 (stmt);
1489 op0 = gimple_assign_rhs1 (stmt);
1491 VEC_reserve (histogram_value, heap, *values, 3);
1493 if (is_gimple_reg (divisor))
1494 /* Check for the case where the divisor is the same value most
1495 of the time. */
1496 VEC_quick_push (histogram_value, *values,
1497 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1498 stmt, divisor));
1500 /* For mod, check whether it is not often a noop (or replaceable by
1501 a few subtractions). */
1502 if (gimple_subcode (stmt) == TRUNC_MOD_EXPR
1503 && TYPE_UNSIGNED (type))
1505 tree val;
1506 /* Check for a special case where the divisor is power of 2. */
1507 VEC_quick_push (histogram_value, *values,
1508 gimple_alloc_histogram_value (cfun, HIST_TYPE_POW2,
1509 stmt, divisor));
1511 val = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
1512 hist = gimple_alloc_histogram_value (cfun, HIST_TYPE_INTERVAL,
1513 stmt, val);
1514 hist->hdata.intvl.int_start = 0;
1515 hist->hdata.intvl.steps = 2;
1516 VEC_quick_push (histogram_value, *values, hist);
1518 return;
1520 default:
1521 return;
1525 /* Find calls inside STMT for that we want to measure histograms for
1526 indirect/virtual call optimization. */
1528 static void
1529 gimple_indirect_call_to_profile (gimple stmt, histogram_values *values)
1531 tree callee;
1533 if (gimple_code (stmt) != GIMPLE_CALL)
1534 return;
1536 callee = gimple_call_fn (stmt);
1538 if (TREE_CODE (callee) == FUNCTION_DECL)
1539 return;
1541 VEC_reserve (histogram_value, heap, *values, 3);
1543 VEC_quick_push (histogram_value, *values,
1544 gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
1545 stmt, callee));
1547 return;
1550 /* Find values inside STMT for that we want to measure histograms for
1551 string operations. */
1552 static void
1553 gimple_stringops_values_to_profile (gimple stmt, histogram_values *values)
1555 tree fndecl;
1556 tree blck_size;
1557 tree dest;
1558 enum built_in_function fcode;
1560 if (gimple_code (stmt) != GIMPLE_CALL)
1561 return;
1562 fndecl = gimple_call_fndecl (stmt);
1563 if (!fndecl)
1564 return;
1565 fcode = DECL_FUNCTION_CODE (fndecl);
1567 if (!interesting_stringop_to_profile_p (fndecl, stmt))
1568 return;
1570 dest = gimple_call_arg (stmt, 0);
1571 if (fcode == BUILT_IN_BZERO)
1572 blck_size = gimple_call_arg (stmt, 1);
1573 else
1574 blck_size = gimple_call_arg (stmt, 2);
1576 if (TREE_CODE (blck_size) != INTEGER_CST)
1578 VEC_safe_push (histogram_value, heap, *values,
1579 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1580 stmt, blck_size));
1581 VEC_safe_push (histogram_value, heap, *values,
1582 gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE,
1583 stmt, blck_size));
1585 if (TREE_CODE (blck_size) != INTEGER_CST)
1586 VEC_safe_push (histogram_value, heap, *values,
1587 gimple_alloc_histogram_value (cfun, HIST_TYPE_IOR,
1588 stmt, dest));
1591 /* Find values inside STMT for that we want to measure histograms and adds
1592 them to list VALUES. */
1594 static void
1595 gimple_values_to_profile (gimple stmt, histogram_values *values)
1597 if (flag_value_profile_transformations)
1599 gimple_divmod_values_to_profile (stmt, values);
1600 gimple_stringops_values_to_profile (stmt, values);
1601 gimple_indirect_call_to_profile (stmt, values);
1605 static void
1606 gimple_find_values_to_profile (histogram_values *values)
1608 basic_block bb;
1609 gimple_stmt_iterator gsi;
1610 unsigned i;
1611 histogram_value hist = NULL;
1613 *values = NULL;
1614 FOR_EACH_BB (bb)
1615 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1616 gimple_values_to_profile (gsi_stmt (gsi), values);
1618 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
1620 switch (hist->type)
1622 case HIST_TYPE_INTERVAL:
1623 hist->n_counters = hist->hdata.intvl.steps + 2;
1624 break;
1626 case HIST_TYPE_POW2:
1627 hist->n_counters = 2;
1628 break;
1630 case HIST_TYPE_SINGLE_VALUE:
1631 hist->n_counters = 3;
1632 break;
1634 case HIST_TYPE_CONST_DELTA:
1635 hist->n_counters = 4;
1636 break;
1638 case HIST_TYPE_INDIR_CALL:
1639 hist->n_counters = 3;
1640 break;
1642 case HIST_TYPE_AVERAGE:
1643 hist->n_counters = 2;
1644 break;
1646 case HIST_TYPE_IOR:
1647 hist->n_counters = 1;
1648 break;
1650 default:
1651 gcc_unreachable ();
1653 if (dump_file)
1655 fprintf (dump_file, "Stmt ");
1656 print_gimple_stmt (dump_file, hist->hvalue.stmt, 0, TDF_SLIM);
1657 dump_histogram_value (dump_file, hist);
1662 static struct value_prof_hooks gimple_value_prof_hooks = {
1663 gimple_find_values_to_profile,
1664 gimple_value_profile_transformations
1667 void
1668 gimple_register_value_prof_hooks (void)
1670 gcc_assert (current_ir_type () == IR_GIMPLE);
1671 value_prof_hooks = &gimple_value_prof_hooks;
1674 /* IR-independent entry points. */
1675 void
1676 find_values_to_profile (histogram_values *values)
1678 (value_prof_hooks->find_values_to_profile) (values);
1681 bool
1682 value_profile_transformations (void)
1684 return (value_prof_hooks->value_profile_transformations) ();