re PR target/30519 (Configuration mismatch -- extra parts)
[official-gcc.git] / gcc / value-prof.c
blobf23fd68dd6fe522233a0a0c114570142e04d7cec
1 /* Transformations based on profile information for values.
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "expr.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "value-prof.h"
30 #include "output.h"
31 #include "flags.h"
32 #include "insn-config.h"
33 #include "recog.h"
34 #include "optabs.h"
35 #include "regs.h"
36 #include "ggc.h"
37 #include "tree-flow.h"
38 #include "tree-flow-inline.h"
39 #include "diagnostic.h"
40 #include "coverage.h"
41 #include "tree.h"
42 #include "gcov-io.h"
43 #include "cgraph.h"
44 #include "timevar.h"
45 #include "tree-pass.h"
46 #include "toplev.h"
47 #include "pointer-set.h"
49 static struct value_prof_hooks *value_prof_hooks;
51 /* In this file value profile based optimizations are placed. Currently the
52 following optimizations are implemented (for more detailed descriptions
53 see comments at value_profile_transformations):
55 1) Division/modulo specialization. Provided that we can determine that the
56 operands of the division have some special properties, we may use it to
57 produce more effective code.
58 2) Speculative prefetching. If we are able to determine that the difference
59 between addresses accessed by a memory reference is usually constant, we
60 may add the prefetch instructions.
61 FIXME: This transformation was removed together with RTL based value
62 profiling.
64 3) Indirect/virtual call specialization. If we can determine most
65 common function callee in indirect/virtual call. We can use this
66 information to improve code effectivity (espetialy info for
67 inliner).
69 Every such optimization should add its requirements for profiled values to
70 insn_values_to_profile function. This function is called from branch_prob
71 in profile.c and the requested values are instrumented by it in the first
72 compilation with -fprofile-arcs. The optimization may then read the
73 gathered data in the second compilation with -fbranch-probabilities.
75 The measured data is pointed to from the histograms
76 field of the statement annotation of the instrumented insns. It is
77 kept as a linked list of struct histogram_value_t's, which contain the
78 same information as above. */
81 static tree tree_divmod_fixed_value (tree, tree, tree, tree,
82 tree, int, gcov_type, gcov_type);
83 static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
84 static tree tree_mod_subtract (tree, tree, tree, tree, int, int, int,
85 gcov_type, gcov_type, gcov_type);
86 static bool tree_divmod_fixed_value_transform (tree);
87 static bool tree_mod_pow2_value_transform (tree);
88 static bool tree_mod_subtract_transform (tree);
89 static bool tree_stringops_transform (block_stmt_iterator *);
90 static bool tree_ic_transform (tree);
92 /* Allocate histogram value. */
94 static histogram_value
95 gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
96 enum hist_type type, tree stmt, tree value)
98 histogram_value hist = (histogram_value) xcalloc (1, sizeof (*hist));
99 hist->hvalue.value = value;
100 hist->hvalue.stmt = stmt;
101 hist->type = type;
102 return hist;
105 /* Hash value for histogram. */
107 static hashval_t
108 histogram_hash (const void *x)
110 return htab_hash_pointer (((histogram_value)x)->hvalue.stmt);
113 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
115 static int
116 histogram_eq (const void *x, const void *y)
118 return ((histogram_value) x)->hvalue.stmt == (tree)y;
121 /* Set histogram for STMT. */
123 static void
124 set_histogram_value (struct function *fun, tree stmt, histogram_value hist)
126 void **loc;
127 if (!hist && !VALUE_HISTOGRAMS (fun))
128 return;
129 if (!VALUE_HISTOGRAMS (fun))
130 VALUE_HISTOGRAMS (fun) = htab_create (1, histogram_hash,
131 histogram_eq, NULL);
132 loc = htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun), stmt,
133 htab_hash_pointer (stmt),
134 hist ? INSERT : NO_INSERT);
135 if (!hist)
137 if (loc)
138 htab_clear_slot (VALUE_HISTOGRAMS (fun), loc);
139 return;
141 *loc = hist;
144 /* Get histogram list for STMT. */
146 histogram_value
147 gimple_histogram_value (struct function *fun, tree stmt)
149 if (!VALUE_HISTOGRAMS (fun))
150 return NULL;
151 return htab_find_with_hash (VALUE_HISTOGRAMS (fun), stmt,
152 htab_hash_pointer (stmt));
155 /* Add histogram for STMT. */
157 void
158 gimple_add_histogram_value (struct function *fun, tree stmt, histogram_value hist)
160 hist->hvalue.next = gimple_histogram_value (fun, stmt);
161 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, tree stmt, histogram_value hist)
169 histogram_value hist2 = gimple_histogram_value (fun, stmt);
170 if (hist == hist2)
172 set_histogram_value (fun, stmt, hist->hvalue.next);
174 else
176 while (hist2->hvalue.next != hist)
177 hist2 = hist2->hvalue.next;
178 hist2->hvalue.next = hist->hvalue.next;
180 free (hist->hvalue.counters);
181 #ifdef ENABLE_CHECKING
182 memset (hist, 0xab, sizeof (*hist));
183 #endif
184 free (hist);
187 /* Lookup histogram of type TYPE in the STMT. */
189 histogram_value
190 gimple_histogram_value_of_type (struct function *fun, tree stmt, enum hist_type type)
192 histogram_value hist;
193 for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
194 if (hist->type == type)
195 return hist;
196 return NULL;
199 /* Dump information about HIST to DUMP_FILE. */
201 static void
202 dump_histogram_value (FILE *dump_file, histogram_value hist)
204 switch (hist->type)
206 case HIST_TYPE_INTERVAL:
207 fprintf (dump_file, "Interval counter range %d -- %d",
208 hist->hdata.intvl.int_start,
209 (hist->hdata.intvl.int_start
210 + hist->hdata.intvl.steps - 1));
211 if (hist->hvalue.counters)
213 unsigned int i;
214 fprintf(dump_file, " [");
215 for (i = 0; i < hist->hdata.intvl.steps; i++)
216 fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
217 hist->hdata.intvl.int_start + i,
218 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
219 fprintf (dump_file, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC,
220 (HOST_WIDEST_INT) hist->hvalue.counters[i]);
222 fprintf (dump_file, ".\n");
223 break;
225 case HIST_TYPE_POW2:
226 fprintf (dump_file, "Pow2 counter ");
227 if (hist->hvalue.counters)
229 fprintf (dump_file, "pow2:"HOST_WIDEST_INT_PRINT_DEC
230 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC,
231 (HOST_WIDEST_INT) hist->hvalue.counters[0],
232 (HOST_WIDEST_INT) hist->hvalue.counters[1]);
234 fprintf (dump_file, ".\n");
235 break;
237 case HIST_TYPE_SINGLE_VALUE:
238 fprintf (dump_file, "Single value ");
239 if (hist->hvalue.counters)
241 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
242 " match:"HOST_WIDEST_INT_PRINT_DEC
243 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
244 (HOST_WIDEST_INT) hist->hvalue.counters[0],
245 (HOST_WIDEST_INT) hist->hvalue.counters[1],
246 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
248 fprintf (dump_file, ".\n");
249 break;
251 case HIST_TYPE_CONST_DELTA:
252 fprintf (dump_file, "Constant delta ");
253 if (hist->hvalue.counters)
255 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
256 " match:"HOST_WIDEST_INT_PRINT_DEC
257 " wrong:"HOST_WIDEST_INT_PRINT_DEC,
258 (HOST_WIDEST_INT) hist->hvalue.counters[0],
259 (HOST_WIDEST_INT) hist->hvalue.counters[1],
260 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
262 fprintf (dump_file, ".\n");
263 break;
264 case HIST_TYPE_INDIR_CALL:
265 fprintf (dump_file, "Indirect call ");
266 if (hist->hvalue.counters)
268 fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
269 " match:"HOST_WIDEST_INT_PRINT_DEC
270 " all:"HOST_WIDEST_INT_PRINT_DEC,
271 (HOST_WIDEST_INT) hist->hvalue.counters[0],
272 (HOST_WIDEST_INT) hist->hvalue.counters[1],
273 (HOST_WIDEST_INT) hist->hvalue.counters[2]);
275 fprintf (dump_file, ".\n");
276 break;
280 /* Dump all histograms attached to STMT to DUMP_FILE. */
282 void
283 dump_histograms_for_stmt (struct function *fun, FILE *dump_file, tree stmt)
285 histogram_value hist;
286 for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
287 dump_histogram_value (dump_file, hist);
290 /* Remove all histograms associated with STMT. */
292 void
293 gimple_remove_stmt_histograms (struct function *fun, tree stmt)
295 histogram_value val;
296 while ((val = gimple_histogram_value (fun, stmt)) != NULL)
297 gimple_remove_histogram_value (fun, stmt, val);
300 /* Duplicate all histograms associates with OSTMT to STMT. */
302 void
303 gimple_duplicate_stmt_histograms (struct function *fun, tree stmt,
304 struct function *ofun, tree ostmt)
306 histogram_value val;
307 for (val = gimple_histogram_value (ofun, ostmt); val != NULL; val = val->hvalue.next)
309 histogram_value new = gimple_alloc_histogram_value (fun, val->type, NULL, NULL);
310 memcpy (new, val, sizeof (*val));
311 new->hvalue.stmt = stmt;
312 new->hvalue.counters = xmalloc (sizeof (*new->hvalue.counters) * new->n_counters);
313 memcpy (new->hvalue.counters, val->hvalue.counters, sizeof (*new->hvalue.counters) * new->n_counters);
314 gimple_add_histogram_value (fun, stmt, new);
318 static bool error_found = false;
320 /* Helper function for verify_histograms. For each histogram reachable via htab
321 walk verify that it was reached via statement walk. */
323 static int
324 visit_hist (void **slot, void *data)
326 struct pointer_set_t *visited = (struct pointer_set_t *) data;
327 histogram_value hist = *(histogram_value *) slot;
328 if (!pointer_set_contains (visited, hist))
330 error ("Dead histogram");
331 dump_histogram_value (stderr, hist);
332 debug_generic_stmt (hist->hvalue.stmt);
333 error_found = true;
335 return 0;
338 /* Verify sanity of the histograms. */
340 void
341 verify_histograms (void)
343 basic_block bb;
344 block_stmt_iterator bsi;
345 histogram_value hist;
346 struct pointer_set_t *visited_hists;
348 error_found = false;
349 visited_hists = pointer_set_create ();
350 FOR_EACH_BB (bb)
351 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
353 tree stmt = bsi_stmt (bsi);
355 for (hist = gimple_histogram_value (cfun, stmt); hist; hist = hist->hvalue.next)
357 if (hist->hvalue.stmt != stmt)
359 error ("Histogram value statement does not correspond to statement"
360 " it is associated with");
361 debug_generic_stmt (stmt);
362 dump_histogram_value (stderr, hist);
363 error_found = true;
365 pointer_set_insert (visited_hists, hist);
368 if (VALUE_HISTOGRAMS (cfun))
369 htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
370 pointer_set_destroy (visited_hists);
371 if (error_found)
372 internal_error ("verify_histograms failed");
375 /* Helper function for verify_histograms. For each histogram reachable via htab
376 walk verify that it was reached via statement walk. */
378 static int
379 free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
381 histogram_value hist = *(histogram_value *) slot;
382 free (hist->hvalue.counters);
383 #ifdef ENABLE_CHECKING
384 memset (hist, 0xab, sizeof (*hist));
385 #endif
386 free (hist);
387 return 0;
390 void
391 free_histograms (void)
393 if (VALUE_HISTOGRAMS (cfun))
395 htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
396 htab_delete (VALUE_HISTOGRAMS (cfun));
397 VALUE_HISTOGRAMS (cfun) = NULL;
401 /* The overall number of invocations of the counter should match execution count
402 of basic block. Report it as error rather than internal error as it might
403 mean that user has misused the profile somehow. */
404 static bool
405 check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
407 if (all != bb_count)
409 location_t * locus;
410 locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
411 ? EXPR_LOCUS (stmt)
412 : &DECL_SOURCE_LOCATION (current_function_decl));
413 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
414 locus, name, (int)all, (int)bb_count);
415 return true;
417 return false;
420 /* Tree based transformations. */
421 static bool
422 tree_value_profile_transformations (void)
424 basic_block bb;
425 block_stmt_iterator bsi;
426 bool changed = false;
428 FOR_EACH_BB (bb)
430 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
432 tree stmt = bsi_stmt (bsi);
433 histogram_value th = gimple_histogram_value (cfun, stmt);
434 if (!th)
435 continue;
437 if (dump_file)
439 fprintf (dump_file, "Trying transformations on stmt ");
440 print_generic_stmt (dump_file, stmt, TDF_SLIM);
441 dump_histograms_for_stmt (cfun, dump_file, stmt);
444 /* Transformations: */
445 /* The order of things in this conditional controls which
446 transformation is used when more than one is applicable. */
447 /* It is expected that any code added by the transformations
448 will be added before the current statement, and that the
449 current statement remain valid (although possibly
450 modified) upon return. */
451 if (flag_value_profile_transformations
452 && (tree_mod_subtract_transform (stmt)
453 || tree_divmod_fixed_value_transform (stmt)
454 || tree_mod_pow2_value_transform (stmt)
455 || tree_stringops_transform (&bsi)
456 || tree_ic_transform (stmt)))
458 stmt = bsi_stmt (bsi);
459 changed = true;
460 /* Original statement may no longer be in the same block. */
461 if (bb != bb_for_stmt (stmt))
463 bb = bb_for_stmt (stmt);
464 bsi = bsi_for_stmt (stmt);
470 if (changed)
472 counts_to_freqs ();
475 return changed;
478 /* Generate code for transformation 1 (with OPERATION, operands OP1
479 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
480 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
481 within roundoff error). This generates the result into a temp and returns
482 the temp; it does not replace or alter the original STMT. */
483 static tree
484 tree_divmod_fixed_value (tree stmt, tree operation,
485 tree op1, tree op2, tree value, int prob, gcov_type count,
486 gcov_type all)
488 tree stmt1, stmt2, stmt3;
489 tree tmp1, tmp2, tmpv;
490 tree label_decl1 = create_artificial_label ();
491 tree label_decl2 = create_artificial_label ();
492 tree label1, label2;
493 tree bb1end, bb2end, bb3end;
494 basic_block bb, bb2, bb3, bb4;
495 tree optype = TREE_TYPE (operation);
496 edge e12, e13, e23, e24, e34;
497 block_stmt_iterator bsi;
499 bb = bb_for_stmt (stmt);
500 bsi = bsi_for_stmt (stmt);
502 tmpv = create_tmp_var (optype, "PROF");
503 tmp1 = create_tmp_var (optype, "PROF");
504 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv,
505 fold_convert (optype, value));
506 stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, op2);
507 stmt3 = build3 (COND_EXPR, void_type_node,
508 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
509 build1 (GOTO_EXPR, void_type_node, label_decl2),
510 build1 (GOTO_EXPR, void_type_node, label_decl1));
511 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
512 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
513 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
514 bb1end = stmt3;
516 tmp2 = create_tmp_var (optype, "PROF");
517 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
518 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2,
519 build2 (TREE_CODE (operation), optype, op1, tmpv));
520 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
521 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
522 bb2end = stmt1;
524 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
525 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2,
526 build2 (TREE_CODE (operation), optype, op1, op2));
527 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
528 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
529 bb3end = stmt1;
531 /* Fix CFG. */
532 /* Edge e23 connects bb2 to bb3, etc. */
533 e12 = split_block (bb, bb1end);
534 bb2 = e12->dest;
535 bb2->count = count;
536 e23 = split_block (bb2, bb2end);
537 bb3 = e23->dest;
538 bb3->count = all - count;
539 e34 = split_block (bb3, bb3end);
540 bb4 = e34->dest;
541 bb4->count = all;
543 e12->flags &= ~EDGE_FALLTHRU;
544 e12->flags |= EDGE_FALSE_VALUE;
545 e12->probability = prob;
546 e12->count = count;
548 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
549 e13->probability = REG_BR_PROB_BASE - prob;
550 e13->count = all - count;
552 remove_edge (e23);
554 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
555 e24->probability = REG_BR_PROB_BASE;
556 e24->count = count;
558 e34->probability = REG_BR_PROB_BASE;
559 e34->count = all - count;
561 return tmp2;
564 /* Do transform 1) on INSN if applicable. */
565 static bool
566 tree_divmod_fixed_value_transform (tree stmt)
568 histogram_value histogram;
569 enum tree_code code;
570 gcov_type val, count, all;
571 tree modify, op, op1, op2, result, value, tree_val;
572 int prob;
574 modify = stmt;
575 if (TREE_CODE (stmt) == RETURN_EXPR
576 && TREE_OPERAND (stmt, 0)
577 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
578 modify = TREE_OPERAND (stmt, 0);
579 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
580 return false;
581 op = GIMPLE_STMT_OPERAND (modify, 1);
582 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
583 return false;
584 code = TREE_CODE (op);
586 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
587 return false;
589 op1 = TREE_OPERAND (op, 0);
590 op2 = TREE_OPERAND (op, 1);
592 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
593 if (!histogram)
594 return false;
596 value = histogram->hvalue.value;
597 val = histogram->hvalue.counters[0];
598 count = histogram->hvalue.counters[1];
599 all = histogram->hvalue.counters[2];
600 gimple_remove_histogram_value (cfun, stmt, histogram);
602 /* We require that count is at least half of all; this means
603 that for the transformation to fire the value must be constant
604 at least 50% of time (and 75% gives the guarantee of usage). */
605 if (simple_cst_equal (op2, value) != 1 || 2 * count < all
606 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
607 return false;
609 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
610 return false;
612 /* Compute probability of taking the optimal path. */
613 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
615 tree_val = build_int_cst_wide (get_gcov_type (),
616 (unsigned HOST_WIDE_INT) val,
617 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
618 result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
620 if (dump_file)
622 fprintf (dump_file, "Div/mod by constant ");
623 print_generic_expr (dump_file, value, TDF_SLIM);
624 fprintf (dump_file, "=");
625 print_generic_expr (dump_file, tree_val, TDF_SLIM);
626 fprintf (dump_file, " transformation on insn ");
627 print_generic_stmt (dump_file, stmt, TDF_SLIM);
630 GIMPLE_STMT_OPERAND (modify, 1) = result;
632 return true;
635 /* Generate code for transformation 2 (with OPERATION, operands OP1
636 and OP2, parent modify-expr STMT and probability of taking the optimal
637 path PROB, which is equivalent to COUNT/ALL within roundoff error).
638 This generates the result into a temp and returns
639 the temp; it does not replace or alter the original STMT. */
640 static tree
641 tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
642 gcov_type count, gcov_type all)
644 tree stmt1, stmt2, stmt3, stmt4;
645 tree tmp2, tmp3;
646 tree label_decl1 = create_artificial_label ();
647 tree label_decl2 = create_artificial_label ();
648 tree label1, label2;
649 tree bb1end, bb2end, bb3end;
650 basic_block bb, bb2, bb3, bb4;
651 tree optype = TREE_TYPE (operation);
652 edge e12, e13, e23, e24, e34;
653 block_stmt_iterator bsi;
654 tree result = create_tmp_var (optype, "PROF");
656 bb = bb_for_stmt (stmt);
657 bsi = bsi_for_stmt (stmt);
659 tmp2 = create_tmp_var (optype, "PROF");
660 tmp3 = create_tmp_var (optype, "PROF");
661 stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2,
662 build2 (PLUS_EXPR, optype, op2, build_int_cst (optype, -1)));
663 stmt3 = build2 (GIMPLE_MODIFY_STMT, optype, tmp3,
664 build2 (BIT_AND_EXPR, optype, tmp2, op2));
665 stmt4 = build3 (COND_EXPR, void_type_node,
666 build2 (NE_EXPR, boolean_type_node,
667 tmp3, build_int_cst (optype, 0)),
668 build1 (GOTO_EXPR, void_type_node, label_decl2),
669 build1 (GOTO_EXPR, void_type_node, label_decl1));
670 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
671 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
672 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
673 bb1end = stmt4;
675 /* tmp2 == op2-1 inherited from previous block */
676 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
677 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
678 build2 (BIT_AND_EXPR, optype, op1, tmp2));
679 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
680 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
681 bb2end = stmt1;
683 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
684 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
685 build2 (TREE_CODE (operation), optype, op1, op2));
686 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
687 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
688 bb3end = stmt1;
690 /* Fix CFG. */
691 /* Edge e23 connects bb2 to bb3, etc. */
692 e12 = split_block (bb, bb1end);
693 bb2 = e12->dest;
694 bb2->count = count;
695 e23 = split_block (bb2, bb2end);
696 bb3 = e23->dest;
697 bb3->count = all - count;
698 e34 = split_block (bb3, bb3end);
699 bb4 = e34->dest;
700 bb4->count = all;
702 e12->flags &= ~EDGE_FALLTHRU;
703 e12->flags |= EDGE_FALSE_VALUE;
704 e12->probability = prob;
705 e12->count = count;
707 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
708 e13->probability = REG_BR_PROB_BASE - prob;
709 e13->count = all - count;
711 remove_edge (e23);
713 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
714 e24->probability = REG_BR_PROB_BASE;
715 e24->count = count;
717 e34->probability = REG_BR_PROB_BASE;
718 e34->count = all - count;
720 return result;
723 /* Do transform 2) on INSN if applicable. */
724 static bool
725 tree_mod_pow2_value_transform (tree stmt)
727 histogram_value histogram;
728 enum tree_code code;
729 gcov_type count, wrong_values, all;
730 tree modify, op, op1, op2, result, value;
731 int prob;
733 modify = stmt;
734 if (TREE_CODE (stmt) == RETURN_EXPR
735 && TREE_OPERAND (stmt, 0)
736 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
737 modify = TREE_OPERAND (stmt, 0);
738 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
739 return false;
740 op = GIMPLE_STMT_OPERAND (modify, 1);
741 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
742 return false;
743 code = TREE_CODE (op);
745 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
746 return false;
748 op1 = TREE_OPERAND (op, 0);
749 op2 = TREE_OPERAND (op, 1);
751 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_POW2);
752 if (!histogram)
753 return false;
755 value = histogram->hvalue.value;
756 wrong_values = histogram->hvalue.counters[0];
757 count = histogram->hvalue.counters[1];
759 gimple_remove_histogram_value (cfun, stmt, histogram);
761 /* We require that we hit a power of 2 at least half of all evaluations. */
762 if (simple_cst_equal (op2, value) != 1 || count < wrong_values
763 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
764 return false;
766 if (dump_file)
768 fprintf (dump_file, "Mod power of 2 transformation on insn ");
769 print_generic_stmt (dump_file, stmt, TDF_SLIM);
772 /* Compute probability of taking the optimal path. */
773 all = count + wrong_values;
775 if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
776 return false;
778 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
780 result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
782 GIMPLE_STMT_OPERAND (modify, 1) = result;
784 return true;
787 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
788 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
789 support. Currently only NCOUNTS==0 or 1 is supported and this is
790 built into this interface. The probabilities of taking the optimal
791 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
792 COUNT2/ALL respectively within roundoff error). This generates the
793 result into a temp and returns the temp; it does not replace or alter
794 the original STMT. */
795 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
797 static tree
798 tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
799 int prob1, int prob2, int ncounts,
800 gcov_type count1, gcov_type count2, gcov_type all)
802 tree stmt1, stmt2, stmt3;
803 tree tmp1;
804 tree label_decl1 = create_artificial_label ();
805 tree label_decl2 = create_artificial_label ();
806 tree label_decl3 = create_artificial_label ();
807 tree label1, label2, label3;
808 tree bb1end, bb2end = NULL_TREE, bb3end;
809 basic_block bb, bb2, bb3, bb4;
810 tree optype = TREE_TYPE (operation);
811 edge e12, e23 = 0, e24, e34, e14;
812 block_stmt_iterator bsi;
813 tree result = create_tmp_var (optype, "PROF");
815 bb = bb_for_stmt (stmt);
816 bsi = bsi_for_stmt (stmt);
818 tmp1 = create_tmp_var (optype, "PROF");
819 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result, op1);
820 stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, op2);
821 stmt3 = build3 (COND_EXPR, void_type_node,
822 build2 (LT_EXPR, boolean_type_node, result, tmp1),
823 build1 (GOTO_EXPR, void_type_node, label_decl3),
824 build1 (GOTO_EXPR, void_type_node,
825 ncounts ? label_decl1 : label_decl2));
826 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
827 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
828 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
829 bb1end = stmt3;
831 if (ncounts) /* Assumed to be 0 or 1 */
833 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
834 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
835 build2 (MINUS_EXPR, optype, result, tmp1));
836 stmt2 = build3 (COND_EXPR, void_type_node,
837 build2 (LT_EXPR, boolean_type_node, result, tmp1),
838 build1 (GOTO_EXPR, void_type_node, label_decl3),
839 build1 (GOTO_EXPR, void_type_node, label_decl2));
840 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
841 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
842 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
843 bb2end = stmt2;
846 /* Fallback case. */
847 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
848 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
849 build2 (TREE_CODE (operation), optype, result, tmp1));
850 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
851 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
852 bb3end = stmt1;
854 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
855 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
857 /* Fix CFG. */
858 /* Edge e23 connects bb2 to bb3, etc. */
859 /* However block 3 is optional; if it is not there, references
860 to 3 really refer to block 2. */
861 e12 = split_block (bb, bb1end);
862 bb2 = e12->dest;
863 bb2->count = all - count1;
865 if (ncounts) /* Assumed to be 0 or 1. */
867 e23 = split_block (bb2, bb2end);
868 bb3 = e23->dest;
869 bb3->count = all - count1 - count2;
872 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
873 bb4 = e34->dest;
874 bb4->count = all;
876 e12->flags &= ~EDGE_FALLTHRU;
877 e12->flags |= EDGE_FALSE_VALUE;
878 e12->probability = REG_BR_PROB_BASE - prob1;
879 e12->count = all - count1;
881 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
882 e14->probability = prob1;
883 e14->count = count1;
885 if (ncounts) /* Assumed to be 0 or 1. */
887 e23->flags &= ~EDGE_FALLTHRU;
888 e23->flags |= EDGE_FALSE_VALUE;
889 e23->count = all - count1 - count2;
890 e23->probability = REG_BR_PROB_BASE - prob2;
892 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
893 e24->probability = prob2;
894 e24->count = count2;
897 e34->probability = REG_BR_PROB_BASE;
898 e34->count = all - count1 - count2;
900 return result;
903 /* Do transforms 3) and 4) on INSN if applicable. */
904 static bool
905 tree_mod_subtract_transform (tree stmt)
907 histogram_value histogram;
908 enum tree_code code;
909 gcov_type count, wrong_values, all;
910 tree modify, op, op1, op2, result, value;
911 int prob1, prob2;
912 unsigned int i, steps;
913 gcov_type count1, count2;
915 modify = stmt;
916 if (TREE_CODE (stmt) == RETURN_EXPR
917 && TREE_OPERAND (stmt, 0)
918 && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
919 modify = TREE_OPERAND (stmt, 0);
920 if (TREE_CODE (modify) != GIMPLE_MODIFY_STMT)
921 return false;
922 op = GIMPLE_STMT_OPERAND (modify, 1);
923 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
924 return false;
925 code = TREE_CODE (op);
927 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
928 return false;
930 op1 = TREE_OPERAND (op, 0);
931 op2 = TREE_OPERAND (op, 1);
933 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INTERVAL);
934 if (!histogram)
935 return false;
937 value = histogram->hvalue.value;
938 all = 0;
939 wrong_values = 0;
940 for (i = 0; i < histogram->hdata.intvl.steps; i++)
941 all += histogram->hvalue.counters[i];
943 wrong_values += histogram->hvalue.counters[i];
944 wrong_values += histogram->hvalue.counters[i+1];
945 steps = histogram->hdata.intvl.steps;
946 all += wrong_values;
947 count1 = histogram->hvalue.counters[0];
948 count2 = histogram->hvalue.counters[1];
950 /* Compute probability of taking the optimal path. */
951 if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
953 gimple_remove_histogram_value (cfun, stmt, histogram);
954 return false;
957 /* We require that we use just subtractions in at least 50% of all
958 evaluations. */
959 count = 0;
960 for (i = 0; i < histogram->hdata.intvl.steps; i++)
962 count += histogram->hvalue.counters[i];
963 if (count * 2 >= all)
964 break;
966 if (i == steps
967 || !maybe_hot_bb_p (bb_for_stmt (stmt)))
968 return false;
970 gimple_remove_histogram_value (cfun, stmt, histogram);
971 if (dump_file)
973 fprintf (dump_file, "Mod subtract transformation on insn ");
974 print_generic_stmt (dump_file, stmt, TDF_SLIM);
977 /* Compute probability of taking the optimal path(s). */
978 prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
979 prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
981 /* In practice, "steps" is always 2. This interface reflects this,
982 and will need to be changed if "steps" can change. */
983 result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
984 count1, count2, all);
986 GIMPLE_STMT_OPERAND (modify, 1) = result;
988 return true;
991 static struct cgraph_node** pid_map = NULL;
993 /* Initialize map of pids (pid -> cgraph node) */
995 static void
996 init_pid_map (void)
998 struct cgraph_node *n;
1000 if (pid_map != NULL)
1001 return;
1003 pid_map
1004 = (struct cgraph_node**) xmalloc (sizeof (struct cgraph_node*) * cgraph_max_pid);
1006 for (n = cgraph_nodes; n; n = n->next)
1008 if (n->pid != -1)
1009 pid_map [n->pid] = n;
1013 /* Return cgraph node for function with pid */
1015 static inline struct cgraph_node*
1016 find_func_by_pid (int pid)
1018 init_pid_map ();
1020 return pid_map [pid];
1023 /* Do transformation
1025 if (actual_callee_addres == addres_of_most_common_function/method)
1026 do direct call
1027 else
1028 old call
1031 static tree
1032 tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
1033 int prob, gcov_type count, gcov_type all)
1035 tree stmt1, stmt2, stmt3;
1036 tree tmp1, tmpv;
1037 tree label_decl1 = create_artificial_label ();
1038 tree label_decl2 = create_artificial_label ();
1039 tree label1, label2;
1040 tree bb1end, bb2end, bb3end;
1041 tree new_call;
1042 basic_block bb, bb2, bb3, bb4;
1043 tree optype = build_pointer_type (void_type_node);
1044 edge e12, e13, e23, e24, e34;
1045 block_stmt_iterator bsi;
1046 int region;
1048 bb = bb_for_stmt (stmt);
1049 bsi = bsi_for_stmt (stmt);
1051 tmpv = create_tmp_var (optype, "PROF");
1052 tmp1 = create_tmp_var (optype, "PROF");
1053 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv,
1054 unshare_expr (TREE_OPERAND (call, 0)));
1055 stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1,
1056 fold_convert (optype, build_addr (direct_call->decl,
1057 current_function_decl)));
1058 stmt3 = build3 (COND_EXPR, void_type_node,
1059 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
1060 build1 (GOTO_EXPR, void_type_node, label_decl2),
1061 build1 (GOTO_EXPR, void_type_node, label_decl1));
1062 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1063 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
1064 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
1065 bb1end = stmt3;
1067 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
1068 stmt1 = unshare_expr (stmt);
1069 new_call = get_call_expr_in (stmt1);
1070 TREE_OPERAND (new_call, 0) = build_addr (direct_call->decl,
1071 current_function_decl);
1072 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
1073 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1074 bb2end = stmt1;
1076 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
1077 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
1078 bb3end = stmt;
1080 /* Fix CFG. */
1081 /* Edge e23 connects bb2 to bb3, etc. */
1082 e12 = split_block (bb, bb1end);
1083 bb2 = e12->dest;
1084 bb2->count = count;
1085 e23 = split_block (bb2, bb2end);
1086 bb3 = e23->dest;
1087 bb3->count = all - count;
1088 e34 = split_block (bb3, bb3end);
1089 bb4 = e34->dest;
1090 bb4->count = all;
1092 e12->flags &= ~EDGE_FALLTHRU;
1093 e12->flags |= EDGE_FALSE_VALUE;
1094 e12->probability = prob;
1095 e12->count = count;
1097 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1098 e13->probability = REG_BR_PROB_BASE - prob;
1099 e13->count = all - count;
1101 remove_edge (e23);
1103 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1104 e24->probability = REG_BR_PROB_BASE;
1105 e24->count = count;
1106 e34->probability = REG_BR_PROB_BASE;
1107 e34->count = all - count;
1109 /* Fix eh edges */
1110 region = lookup_stmt_eh_region (stmt);
1111 if (region >=0 && tree_could_throw_p (stmt1))
1113 add_stmt_to_eh_region (stmt1, region);
1114 make_eh_edges (stmt1);
1117 if (region >=0 && tree_could_throw_p (stmt))
1119 tree_purge_dead_eh_edges (bb4);
1120 make_eh_edges (stmt);
1123 return stmt1;
1127 For every checked indirect/virtual call determine if most common pid of
1128 function/class method has probability more than 50%. If yes modify code of
1129 this call to:
1132 static bool
1133 tree_ic_transform (tree stmt)
1135 histogram_value histogram;
1136 gcov_type val, count, all;
1137 int prob;
1138 tree call, callee, modify;
1139 struct cgraph_node *direct_call;
1141 call = get_call_expr_in (stmt);
1143 if (!call || TREE_CODE (call) != CALL_EXPR)
1144 return false;
1146 callee = TREE_OPERAND (call, 0);
1148 if (TREE_CODE (callee) == ADDR_EXPR)
1149 return false;
1151 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
1152 if (!histogram)
1153 return false;
1155 val = histogram->hvalue.counters [0];
1156 count = histogram->hvalue.counters [1];
1157 all = histogram->hvalue.counters [2];
1158 gimple_remove_histogram_value (cfun, stmt, histogram);
1160 if (4 * count <= 3 * all)
1161 return false;
1163 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1164 direct_call = find_func_by_pid ((int)val);
1166 if (direct_call == NULL)
1167 return false;
1169 modify = tree_ic (stmt, call, direct_call, prob, count, all);
1171 if (dump_file)
1173 fprintf (dump_file, "Indirect call -> direct call ");
1174 print_generic_expr (dump_file, call, TDF_SLIM);
1175 fprintf (dump_file, "=> ");
1176 print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
1177 fprintf (dump_file, " transformation on insn ");
1178 print_generic_stmt (dump_file, stmt, TDF_SLIM);
1179 fprintf (dump_file, " to ");
1180 print_generic_stmt (dump_file, modify, TDF_SLIM);
1183 return true;
1186 /* Return true if the stringop FNDECL with ARGLIST shall be profiled. */
1187 static bool
1188 interesting_stringop_to_profile_p (tree fndecl, tree arglist)
1190 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
1192 if (fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_MEMCPY
1193 && fcode != BUILT_IN_BZERO)
1194 return false;
1196 switch (fcode)
1198 case BUILT_IN_MEMCPY:
1199 case BUILT_IN_MEMPCPY:
1200 return validate_arglist (arglist,
1201 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
1202 VOID_TYPE);
1203 case BUILT_IN_MEMSET:
1204 return validate_arglist (arglist,
1205 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
1206 VOID_TYPE);
1207 case BUILT_IN_BZERO:
1208 return validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE,
1209 VOID_TYPE);
1210 default:
1211 gcc_unreachable ();
1215 /* Convert stringop (..., size)
1216 into
1217 if (size == VALUE)
1218 stringop (...., VALUE);
1219 else
1220 stringop (...., size);
1221 assuming constant propagation of VALUE will happen later.
1223 static void
1224 tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
1225 gcov_type all)
1227 tree stmt1, stmt2, stmt3;
1228 tree tmp1, tmpv;
1229 tree label_decl1 = create_artificial_label ();
1230 tree label_decl2 = create_artificial_label ();
1231 tree label1, label2;
1232 tree bb1end, bb2end;
1233 basic_block bb, bb2, bb3, bb4;
1234 edge e12, e13, e23, e24, e34;
1235 block_stmt_iterator bsi;
1236 tree call = get_call_expr_in (stmt);
1237 tree arglist = TREE_OPERAND (call, 1);
1238 tree blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1239 tree optype = TREE_TYPE (blck_size);
1240 int region;
1242 bb = bb_for_stmt (stmt);
1243 bsi = bsi_for_stmt (stmt);
1245 if (bsi_end_p (bsi))
1247 edge_iterator ei;
1248 for (ei = ei_start (bb->succs); (e34 = ei_safe_edge (ei)); )
1249 if (!e34->flags & EDGE_ABNORMAL)
1250 break;
1252 else
1254 e34 = split_block (bb, stmt);
1255 bsi = bsi_for_stmt (stmt);
1257 bb4 = e34->dest;
1259 tmpv = create_tmp_var (optype, "PROF");
1260 tmp1 = create_tmp_var (optype, "PROF");
1261 stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv,
1262 fold_convert (optype, value));
1263 stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, blck_size);
1264 stmt3 = build3 (COND_EXPR, void_type_node,
1265 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
1266 build1 (GOTO_EXPR, void_type_node, label_decl2),
1267 build1 (GOTO_EXPR, void_type_node, label_decl1));
1268 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1269 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
1270 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
1271 bb1end = stmt3;
1273 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
1274 stmt1 = unshare_expr (stmt);
1275 call = get_call_expr_in (stmt1);
1276 arglist = TREE_OPERAND (call, 1);
1277 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))) = value;
1278 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
1279 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
1280 region = lookup_stmt_eh_region (stmt);
1281 if (region >= 0)
1282 add_stmt_to_eh_region (stmt1, region);
1283 bb2end = stmt1;
1284 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
1285 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
1287 /* Fix CFG. */
1288 /* Edge e23 connects bb2 to bb3, etc. */
1289 e12 = split_block (bb, bb1end);
1290 bb2 = e12->dest;
1291 bb2->count = count;
1292 e23 = split_block (bb2, bb2end);
1293 bb3 = e23->dest;
1294 bb3->count = all - count;
1296 e12->flags &= ~EDGE_FALLTHRU;
1297 e12->flags |= EDGE_FALSE_VALUE;
1298 e12->probability = prob;
1299 e12->count = count;
1301 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1302 e13->probability = REG_BR_PROB_BASE - prob;
1303 e13->count = all - count;
1305 remove_edge (e23);
1307 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1308 e24->probability = REG_BR_PROB_BASE;
1309 e24->count = count;
1311 e34->probability = REG_BR_PROB_BASE;
1312 e34->count = all - count;
1315 /* Find values inside STMT for that we want to measure histograms for
1316 division/modulo optimization. */
1317 static bool
1318 tree_stringops_transform (block_stmt_iterator *bsi)
1320 tree stmt = bsi_stmt (*bsi);
1321 tree call = get_call_expr_in (stmt);
1322 tree fndecl;
1323 tree arglist;
1324 tree blck_size;
1325 enum built_in_function fcode;
1326 histogram_value histogram;
1327 gcov_type count, all, val;
1328 tree value;
1329 tree dest, src;
1330 unsigned int dest_align, src_align;
1331 int prob;
1332 tree tree_val;
1334 if (!call)
1335 return false;
1336 fndecl = get_callee_fndecl (call);
1337 if (!fndecl)
1338 return false;
1339 fcode = DECL_FUNCTION_CODE (fndecl);
1340 arglist = TREE_OPERAND (call, 1);
1341 if (!interesting_stringop_to_profile_p (fndecl, arglist))
1342 return false;
1344 if (fcode == BUILT_IN_BZERO)
1345 blck_size = TREE_VALUE (TREE_CHAIN (arglist));
1346 else
1347 blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1348 if (TREE_CODE (blck_size) == INTEGER_CST)
1349 return false;
1351 histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
1352 if (!histogram)
1353 return false;
1354 value = histogram->hvalue.value;
1355 val = histogram->hvalue.counters[0];
1356 count = histogram->hvalue.counters[1];
1357 all = histogram->hvalue.counters[2];
1358 gimple_remove_histogram_value (cfun, stmt, histogram);
1359 /* We require that count is at least half of all; this means
1360 that for the transformation to fire the value must be constant
1361 at least 80% of time. */
1362 if ((6 * count / 5) < all || !maybe_hot_bb_p (bb_for_stmt (stmt)))
1363 return false;
1364 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
1365 return false;
1366 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1367 dest = TREE_VALUE (arglist);
1368 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1369 switch (fcode)
1371 case BUILT_IN_MEMCPY:
1372 case BUILT_IN_MEMPCPY:
1373 src = TREE_VALUE (TREE_CHAIN (arglist));
1374 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1375 if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
1376 return false;
1377 break;
1378 case BUILT_IN_MEMSET:
1379 if (!can_store_by_pieces (val, builtin_memset_read_str,
1380 TREE_VALUE (TREE_CHAIN (arglist)),
1381 dest_align))
1382 return false;
1383 break;
1384 case BUILT_IN_BZERO:
1385 if (!can_store_by_pieces (val, builtin_memset_read_str,
1386 integer_zero_node,
1387 dest_align))
1388 return false;
1389 break;
1390 default:
1391 gcc_unreachable ();
1393 tree_val = build_int_cst_wide (get_gcov_type (),
1394 (unsigned HOST_WIDE_INT) val,
1395 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
1396 if (dump_file)
1398 fprintf (dump_file, "Single value %i stringop transformation on ",
1399 (int)val);
1400 print_generic_stmt (dump_file, stmt, TDF_SLIM);
1402 tree_stringop_fixed_value (stmt, tree_val, prob, count, all);
1404 return true;
1407 struct value_prof_hooks {
1408 /* Find list of values for which we want to measure histograms. */
1409 void (*find_values_to_profile) (histogram_values *);
1411 /* Identify and exploit properties of values that are hard to analyze
1412 statically. See value-prof.c for more detail. */
1413 bool (*value_profile_transformations) (void);
1416 /* Find values inside STMT for that we want to measure histograms for
1417 division/modulo optimization. */
1418 static void
1419 tree_divmod_values_to_profile (tree stmt, histogram_values *values)
1421 tree assign, lhs, rhs, divisor, op0, type;
1422 histogram_value hist;
1424 if (TREE_CODE (stmt) == RETURN_EXPR)
1425 assign = TREE_OPERAND (stmt, 0);
1426 else
1427 assign = stmt;
1429 if (!assign
1430 || TREE_CODE (assign) != GIMPLE_MODIFY_STMT)
1431 return;
1432 lhs = GIMPLE_STMT_OPERAND (assign, 0);
1433 type = TREE_TYPE (lhs);
1434 if (!INTEGRAL_TYPE_P (type))
1435 return;
1437 rhs = GIMPLE_STMT_OPERAND (assign, 1);
1438 switch (TREE_CODE (rhs))
1440 case TRUNC_DIV_EXPR:
1441 case TRUNC_MOD_EXPR:
1442 divisor = TREE_OPERAND (rhs, 1);
1443 op0 = TREE_OPERAND (rhs, 0);
1445 VEC_reserve (histogram_value, heap, *values, 3);
1447 if (is_gimple_reg (divisor))
1448 /* Check for the case where the divisor is the same value most
1449 of the time. */
1450 VEC_quick_push (histogram_value, *values,
1451 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1452 stmt, divisor));
1454 /* For mod, check whether it is not often a noop (or replaceable by
1455 a few subtractions). */
1456 if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
1457 && TYPE_UNSIGNED (type))
1459 tree val;
1460 /* Check for a special case where the divisor is power of 2. */
1461 VEC_quick_push (histogram_value, *values,
1462 gimple_alloc_histogram_value (cfun, HIST_TYPE_POW2,
1463 stmt, divisor));
1465 val = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
1466 hist = gimple_alloc_histogram_value (cfun, HIST_TYPE_INTERVAL,
1467 stmt, val);
1468 hist->hdata.intvl.int_start = 0;
1469 hist->hdata.intvl.steps = 2;
1470 VEC_quick_push (histogram_value, *values, hist);
1472 return;
1474 default:
1475 return;
1479 /* Find calls inside STMT for that we want to measure histograms for
1480 indirect/virtual call optimization. */
1482 static void
1483 tree_indirect_call_to_profile (tree stmt, histogram_values *values)
1485 tree call;
1486 tree callee;
1488 call = get_call_expr_in (stmt);
1490 if (!call || TREE_CODE (call) != CALL_EXPR)
1491 return;
1493 callee = TREE_OPERAND (call, 0);
1495 if (TREE_CODE (callee) == ADDR_EXPR)
1496 return;
1498 VEC_reserve (histogram_value, heap, *values, 3);
1500 VEC_quick_push (histogram_value, *values,
1501 gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
1502 stmt, callee));
1504 return;
1507 /* Find values inside STMT for that we want to measure histograms for
1508 string operations. */
1509 static void
1510 tree_stringops_values_to_profile (tree stmt, histogram_values *values)
1512 tree call = get_call_expr_in (stmt);
1513 tree fndecl;
1514 tree arglist;
1515 tree blck_size;
1516 enum built_in_function fcode;
1518 if (!call)
1519 return;
1520 fndecl = get_callee_fndecl (call);
1521 if (!fndecl)
1522 return;
1523 fcode = DECL_FUNCTION_CODE (fndecl);
1524 arglist = TREE_OPERAND (call, 1);
1526 if (!interesting_stringop_to_profile_p (fndecl, arglist))
1527 return;
1529 if (fcode == BUILT_IN_BZERO)
1530 blck_size = TREE_VALUE (TREE_CHAIN (arglist));
1531 else
1532 blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1534 if (TREE_CODE (blck_size) != INTEGER_CST)
1535 VEC_safe_push (histogram_value, heap, *values,
1536 gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
1537 stmt, blck_size));
1540 /* Find values inside STMT for that we want to measure histograms and adds
1541 them to list VALUES. */
1543 static void
1544 tree_values_to_profile (tree stmt, histogram_values *values)
1546 if (flag_value_profile_transformations)
1548 tree_divmod_values_to_profile (stmt, values);
1549 tree_stringops_values_to_profile (stmt, values);
1550 tree_indirect_call_to_profile (stmt, values);
1554 static void
1555 tree_find_values_to_profile (histogram_values *values)
1557 basic_block bb;
1558 block_stmt_iterator bsi;
1559 unsigned i;
1560 histogram_value hist = NULL;
1562 *values = NULL;
1563 FOR_EACH_BB (bb)
1564 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
1565 tree_values_to_profile (bsi_stmt (bsi), values);
1567 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
1569 switch (hist->type)
1571 case HIST_TYPE_INTERVAL:
1572 hist->n_counters = hist->hdata.intvl.steps + 2;
1573 break;
1575 case HIST_TYPE_POW2:
1576 hist->n_counters = 2;
1577 break;
1579 case HIST_TYPE_SINGLE_VALUE:
1580 hist->n_counters = 3;
1581 break;
1583 case HIST_TYPE_CONST_DELTA:
1584 hist->n_counters = 4;
1585 break;
1587 case HIST_TYPE_INDIR_CALL:
1588 hist->n_counters = 3;
1589 break;
1591 default:
1592 gcc_unreachable ();
1594 if (dump_file)
1596 fprintf (dump_file, "Stmt ");
1597 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
1598 dump_histogram_value (dump_file, hist);
1603 static struct value_prof_hooks tree_value_prof_hooks = {
1604 tree_find_values_to_profile,
1605 tree_value_profile_transformations
1608 void
1609 tree_register_value_prof_hooks (void)
1611 gcc_assert (current_ir_type () == IR_GIMPLE);
1612 value_prof_hooks = &tree_value_prof_hooks;
1615 /* IR-independent entry points. */
1616 void
1617 find_values_to_profile (histogram_values *values)
1619 (value_prof_hooks->find_values_to_profile) (values);
1622 bool
1623 value_profile_transformations (void)
1625 return (value_prof_hooks->value_profile_transformations) ();