OSDN Git Service

* tree-ssa-address.c (create_mem_ref): Remove ", bsi" from
[pf3gnuchains/gcc-fork.git] / gcc / value-prof.c
1 /* Transformations based on profile information for values.
2    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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.  */
20
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"
48
49 static struct value_prof_hooks *value_prof_hooks;
50
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):
54
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.
63
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).
68
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.
74
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.  */
79
80
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);
91
92 /* Allocate histogram value.  */
93
94 static histogram_value
95 gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
96                               enum hist_type type, tree stmt, tree value)
97 {
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;
103 }
104
105 /* Hash value for histogram.  */
106
107 static hashval_t
108 histogram_hash (const void *x)
109 {
110   return htab_hash_pointer (((histogram_value)x)->hvalue.stmt);
111 }
112
113 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
114
115 static int
116 histogram_eq (const void *x, const void *y)
117 {
118   return ((histogram_value) x)->hvalue.stmt == (tree)y;
119 }
120
121 /* Set histogram for STMT.  */
122
123 static void
124 set_histogram_value (struct function *fun, tree stmt, histogram_value hist)
125 {
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)
136     {
137       if (loc)
138         htab_clear_slot (VALUE_HISTOGRAMS (fun), loc);
139       return;
140     }
141   *loc = hist;
142 }
143
144 /* Get histogram list for STMT.  */
145
146 histogram_value
147 gimple_histogram_value (struct function *fun, tree stmt)
148 {
149   if (!VALUE_HISTOGRAMS (fun))
150     return NULL;
151   return htab_find_with_hash (VALUE_HISTOGRAMS (fun), stmt,
152                               htab_hash_pointer (stmt));
153 }
154
155 /* Add histogram for STMT.  */
156
157 void
158 gimple_add_histogram_value (struct function *fun, tree stmt, histogram_value hist)
159 {
160   hist->hvalue.next = gimple_histogram_value (fun, stmt);
161   set_histogram_value (fun, stmt, hist);
162 }
163
164 /* Remove histogram HIST from STMT's histogram list.  */
165
166 void
167 gimple_remove_histogram_value (struct function *fun, tree stmt, histogram_value hist)
168 {
169   histogram_value hist2 = gimple_histogram_value (fun, stmt);
170   if (hist == hist2)
171     {
172       set_histogram_value (fun, stmt, hist->hvalue.next);
173     }
174   else
175     {
176       while (hist2->hvalue.next != hist)
177         hist2 = hist2->hvalue.next;
178       hist2->hvalue.next = hist->hvalue.next;
179     }
180   free (hist->hvalue.counters);
181 #ifdef ENABLE_CHECKING
182   memset (hist, 0xab, sizeof (*hist));
183 #endif
184   free (hist);
185 }
186
187 /* Lookup histogram of type TYPE in the STMT.  */
188
189 histogram_value
190 gimple_histogram_value_of_type (struct function *fun, tree stmt, enum hist_type type)
191 {
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;
197 }
198
199 /* Dump information about HIST to DUMP_FILE.  */
200
201 static void
202 dump_histogram_value (FILE *dump_file, histogram_value hist)
203 {
204   switch (hist->type)
205     {
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)
212         {
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]);
221         }
222       fprintf (dump_file, ".\n");
223       break;
224
225     case HIST_TYPE_POW2:
226       fprintf (dump_file, "Pow2 counter ");
227       if (hist->hvalue.counters)
228         {
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]);
233         }
234       fprintf (dump_file, ".\n");
235       break;
236
237     case HIST_TYPE_SINGLE_VALUE:
238       fprintf (dump_file, "Single value ");
239       if (hist->hvalue.counters)
240         {
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]);
247         }
248       fprintf (dump_file, ".\n");
249       break;
250
251     case HIST_TYPE_CONST_DELTA:
252       fprintf (dump_file, "Constant delta ");
253       if (hist->hvalue.counters)
254         {
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]);
261         }
262       fprintf (dump_file, ".\n");
263       break;
264     case HIST_TYPE_INDIR_CALL:
265       fprintf (dump_file, "Indirect call ");
266       if (hist->hvalue.counters)
267         {
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]);
274         }
275       fprintf (dump_file, ".\n");
276       break;
277    }
278 }
279
280 /* Dump all histograms attached to STMT to DUMP_FILE.  */
281
282 void
283 dump_histograms_for_stmt (struct function *fun, FILE *dump_file, tree stmt)
284 {
285   histogram_value hist;
286   for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
287    dump_histogram_value (dump_file, hist);
288 }
289
290 /* Remove all histograms associated with STMT.  */
291
292 void
293 gimple_remove_stmt_histograms (struct function *fun, tree stmt)
294 {
295   histogram_value val;
296   while ((val = gimple_histogram_value (fun, stmt)) != NULL)
297     gimple_remove_histogram_value (fun, stmt, val);
298 }
299
300 /* Duplicate all histograms associates with OSTMT to STMT.  */
301
302 void
303 gimple_duplicate_stmt_histograms (struct function *fun, tree stmt,
304                                   struct function *ofun, tree ostmt)
305 {
306   histogram_value val;
307   for (val = gimple_histogram_value (ofun, ostmt); val != NULL; val = val->hvalue.next)
308     {
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);
315     }
316 }
317
318 static bool error_found = false;
319
320 /* Helper function for verify_histograms.  For each histogram reachable via htab
321    walk verify that it was reached via statement walk.  */
322
323 static int
324 visit_hist (void **slot, void *data)
325 {
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))
329     {
330       error ("Dead histogram");
331       dump_histogram_value (stderr, hist);
332       debug_generic_stmt (hist->hvalue.stmt);
333       error_found = true;
334     }
335   return 0;
336 }
337
338 /* Verify sanity of the histograms.  */
339
340 void
341 verify_histograms (void)
342 {
343   basic_block bb;
344   block_stmt_iterator bsi;
345   histogram_value hist;
346   struct pointer_set_t *visited_hists;
347
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))
352       {
353         tree stmt = bsi_stmt (bsi);
354
355         for (hist = gimple_histogram_value (cfun, stmt); hist; hist = hist->hvalue.next)
356           {
357             if (hist->hvalue.stmt != stmt)
358               {
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;
364               }
365             pointer_set_insert (visited_hists, hist);
366           }
367       }
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");
373 }
374
375 /* Helper function for verify_histograms.  For each histogram reachable via htab
376    walk verify that it was reached via statement walk.  */
377
378 static int
379 free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
380 {
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;
388 }
389
390 void
391 free_histograms (void)
392 {
393   if (VALUE_HISTOGRAMS (cfun))
394     {
395       htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
396       htab_delete (VALUE_HISTOGRAMS (cfun));
397       VALUE_HISTOGRAMS (cfun) = NULL;
398     }
399 }
400
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)
406 {
407   if (all != bb_count)
408     {
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;
416     }
417   return false;
418 }
419
420 /* Tree based transformations. */
421 static bool
422 tree_value_profile_transformations (void)
423 {
424   basic_block bb;
425   block_stmt_iterator bsi;
426   bool changed = false;
427
428   FOR_EACH_BB (bb)
429     {
430       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
431         {
432           tree stmt = bsi_stmt (bsi);
433           histogram_value th = gimple_histogram_value (cfun, stmt);
434           if (!th)
435             continue;
436
437           if (dump_file)
438             {
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);
442             }
443
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)))
457             {
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))
462                 {
463                   bb = bb_for_stmt (stmt);
464                   bsi = bsi_for_stmt (stmt);
465                 }
466             }
467         }
468     }
469
470   if (changed)
471     {
472       counts_to_freqs ();
473     }
474
475   return changed;
476 }
477
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)
487 {
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;
498
499   bb = bb_for_stmt (stmt);
500   bsi = bsi_for_stmt (stmt);
501
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;
515
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;
523
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;
530
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;
542
543   e12->flags &= ~EDGE_FALLTHRU;
544   e12->flags |= EDGE_FALSE_VALUE;
545   e12->probability = prob;
546   e12->count = count;
547
548   e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
549   e13->probability = REG_BR_PROB_BASE - prob;
550   e13->count = all - count;
551
552   remove_edge (e23);
553   
554   e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
555   e24->probability = REG_BR_PROB_BASE;
556   e24->count = count;
557
558   e34->probability = REG_BR_PROB_BASE;
559   e34->count = all - count;
560
561   return tmp2;
562 }
563
564 /* Do transform 1) on INSN if applicable.  */
565 static bool
566 tree_divmod_fixed_value_transform (tree stmt)
567 {
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;
573
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);
585   
586   if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
587     return false;
588
589   op1 = TREE_OPERAND (op, 0);
590   op2 = TREE_OPERAND (op, 1);
591
592   histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
593   if (!histogram)
594     return false;
595
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);
601
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;
608
609   if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
610     return false;
611
612   /* Compute probability of taking the optimal path.  */
613   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
614
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);
619
620   if (dump_file)
621     {
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);
628     }
629
630   GIMPLE_STMT_OPERAND (modify, 1) = result;
631
632   return true;
633 }
634
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)
643 {
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");
655
656   bb = bb_for_stmt (stmt);
657   bsi = bsi_for_stmt (stmt);
658
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;
674
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;
682
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;
689
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;
701
702   e12->flags &= ~EDGE_FALLTHRU;
703   e12->flags |= EDGE_FALSE_VALUE;
704   e12->probability = prob;
705   e12->count = count;
706
707   e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
708   e13->probability = REG_BR_PROB_BASE - prob;
709   e13->count = all - count;
710
711   remove_edge (e23);
712   
713   e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
714   e24->probability = REG_BR_PROB_BASE;
715   e24->count = count;
716
717   e34->probability = REG_BR_PROB_BASE;
718   e34->count = all - count;
719
720   return result;
721 }
722
723 /* Do transform 2) on INSN if applicable.  */
724 static bool
725 tree_mod_pow2_value_transform (tree stmt)
726 {
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;
732
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);
744   
745   if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
746     return false;
747
748   op1 = TREE_OPERAND (op, 0);
749   op2 = TREE_OPERAND (op, 1);
750
751   histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_POW2);
752   if (!histogram)
753     return false;
754
755   value = histogram->hvalue.value;
756   wrong_values = histogram->hvalue.counters[0];
757   count = histogram->hvalue.counters[1];
758
759   gimple_remove_histogram_value (cfun, stmt, histogram);
760
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;
765
766   if (dump_file)
767     {
768       fprintf (dump_file, "Mod power of 2 transformation on insn ");
769       print_generic_stmt (dump_file, stmt, TDF_SLIM);
770     }
771
772   /* Compute probability of taking the optimal path.  */
773   all = count + wrong_values;
774
775   if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
776     return false;
777
778   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
779
780   result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
781
782   GIMPLE_STMT_OPERAND (modify, 1) = result;
783
784   return true;
785 }
786
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.  */
796
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)
801 {
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");
814
815   bb = bb_for_stmt (stmt);
816   bsi = bsi_for_stmt (stmt);
817
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;
830
831   if (ncounts)  /* Assumed to be 0 or 1 */
832     {
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;
844     }
845
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;
853
854   label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
855   bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
856
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;
864     
865   if (ncounts)  /* Assumed to be 0 or 1.  */
866     {
867       e23 = split_block (bb2, bb2end);
868       bb3 = e23->dest;
869       bb3->count = all - count1 - count2;
870     }
871
872   e34 = split_block (ncounts ? bb3 : bb2, bb3end);
873   bb4 = e34->dest;
874   bb4->count = all;
875
876   e12->flags &= ~EDGE_FALLTHRU;
877   e12->flags |= EDGE_FALSE_VALUE;
878   e12->probability = REG_BR_PROB_BASE - prob1;
879   e12->count = all - count1;
880
881   e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
882   e14->probability = prob1;
883   e14->count = count1;
884
885   if (ncounts)  /* Assumed to be 0 or 1.  */
886     {
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;
891
892       e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
893       e24->probability = prob2;
894       e24->count = count2;
895     }
896
897   e34->probability = REG_BR_PROB_BASE;
898   e34->count = all - count1 - count2;
899
900   return result;
901 }
902
903 /* Do transforms 3) and 4) on INSN if applicable.  */
904 static bool
905 tree_mod_subtract_transform (tree stmt)
906 {
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;
914
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);
926   
927   if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
928     return false;
929
930   op1 = TREE_OPERAND (op, 0);
931   op2 = TREE_OPERAND (op, 1);
932
933   histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INTERVAL);
934   if (!histogram)
935     return false;
936
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];
942
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];
949
950   /* Compute probability of taking the optimal path.  */
951   if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
952     {
953       gimple_remove_histogram_value (cfun, stmt, histogram);
954       return false;
955     }
956
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++)
961     {
962       count += histogram->hvalue.counters[i];
963       if (count * 2 >= all)
964         break;
965     }
966   if (i == steps
967       || !maybe_hot_bb_p (bb_for_stmt (stmt)))
968     return false;
969
970   gimple_remove_histogram_value (cfun, stmt, histogram);
971   if (dump_file)
972     {
973       fprintf (dump_file, "Mod subtract transformation on insn ");
974       print_generic_stmt (dump_file, stmt, TDF_SLIM);
975     }
976
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;
980
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);
985
986   GIMPLE_STMT_OPERAND (modify, 1) = result;
987
988   return true;
989 }
990
991 static struct cgraph_node** pid_map = NULL;
992
993 /* Initialize map of pids (pid -> cgraph node) */
994
995 static void 
996 init_pid_map (void)
997 {
998   struct cgraph_node *n;
999
1000   if (pid_map != NULL)
1001     return;
1002
1003   pid_map 
1004     = (struct cgraph_node**) xmalloc (sizeof (struct cgraph_node*) * cgraph_max_pid);
1005
1006   for (n = cgraph_nodes; n; n = n->next)
1007     {
1008       if (n->pid != -1)
1009         pid_map [n->pid] = n;
1010     }
1011 }
1012
1013 /* Return cgraph node for function with pid */
1014
1015 static inline struct cgraph_node*
1016 find_func_by_pid (int   pid)
1017 {
1018   init_pid_map ();
1019
1020   return pid_map [pid];
1021 }
1022
1023 /* Do transformation
1024
1025   if (actual_callee_addres == addres_of_most_common_function/method)
1026     do direct call
1027   else
1028     old call
1029  */
1030
1031 static tree
1032 tree_ic (tree stmt, tree call, struct cgraph_node* direct_call, 
1033          int prob, gcov_type count, gcov_type all)
1034 {
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;
1047
1048   bb = bb_for_stmt (stmt);
1049   bsi = bsi_for_stmt (stmt);
1050
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;
1066
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;
1075
1076   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
1077   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
1078   bb3end = stmt;
1079
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;
1091
1092   e12->flags &= ~EDGE_FALLTHRU;
1093   e12->flags |= EDGE_FALSE_VALUE;
1094   e12->probability = prob;
1095   e12->count = count;
1096
1097   e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1098   e13->probability = REG_BR_PROB_BASE - prob;
1099   e13->count = all - count;
1100
1101   remove_edge (e23);
1102   
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;
1108
1109   /* Fix eh edges */
1110   region = lookup_stmt_eh_region (stmt);
1111   if (region >=0 && tree_could_throw_p (stmt1))
1112     {
1113       add_stmt_to_eh_region (stmt1, region);
1114       make_eh_edges (stmt1);
1115     }
1116
1117   if (region >=0 && tree_could_throw_p (stmt))
1118     {
1119       tree_purge_dead_eh_edges (bb4);
1120       make_eh_edges (stmt);
1121     }
1122
1123   return stmt1;
1124 }
1125
1126 /*
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:
1130  */
1131
1132 static bool
1133 tree_ic_transform (tree stmt)
1134 {
1135   histogram_value histogram;
1136   gcov_type val, count, all;
1137   int prob;
1138   tree call, callee, modify;
1139   struct cgraph_node *direct_call;
1140   
1141   call = get_call_expr_in (stmt);
1142
1143   if (!call || TREE_CODE (call) != CALL_EXPR)
1144     return false;
1145
1146   callee = TREE_OPERAND (call, 0);
1147
1148   if (TREE_CODE (callee) == ADDR_EXPR)
1149     return false;
1150
1151   histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
1152   if (!histogram)
1153     return false;
1154
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);
1159
1160   if (4 * count <= 3 * all)
1161     return false;
1162
1163   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
1164   direct_call = find_func_by_pid ((int)val);
1165
1166   if (direct_call == NULL)
1167     return false;
1168
1169   modify = tree_ic (stmt, call, direct_call, prob, count, all);
1170
1171   if (dump_file)
1172     {
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);
1181     }
1182
1183   return true;
1184 }
1185
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)
1189 {
1190   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
1191
1192   if (fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_MEMCPY
1193       && fcode != BUILT_IN_BZERO)
1194     return false;
1195
1196   switch (fcode)
1197     {
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 ();
1212     }
1213 }
1214
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.
1222 */
1223 static void
1224 tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
1225                            gcov_type all)
1226 {
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;
1241
1242   bb = bb_for_stmt (stmt);
1243   bsi = bsi_for_stmt (stmt);
1244
1245   if (bsi_end_p (bsi))
1246     {
1247       edge_iterator ei;
1248       for (ei = ei_start (bb->succs); (e34 = ei_safe_edge (ei)); )
1249         if (!e34->flags & EDGE_ABNORMAL)
1250           break;
1251     }
1252   else
1253     {
1254       e34 = split_block (bb, stmt);
1255       bsi = bsi_for_stmt (stmt);
1256     }
1257   bb4 = e34->dest;
1258
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;
1272
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);
1286
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;
1295
1296   e12->flags &= ~EDGE_FALLTHRU;
1297   e12->flags |= EDGE_FALSE_VALUE;
1298   e12->probability = prob;
1299   e12->count = count;
1300
1301   e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
1302   e13->probability = REG_BR_PROB_BASE - prob;
1303   e13->count = all - count;
1304
1305   remove_edge (e23);
1306   
1307   e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
1308   e24->probability = REG_BR_PROB_BASE;
1309   e24->count = count;
1310
1311   e34->probability = REG_BR_PROB_BASE;
1312   e34->count = all - count;
1313 }
1314
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)
1319 {
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;
1333
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;
1343
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;
1350
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)
1370     {
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 ();
1392     }
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)
1397     {
1398       fprintf (dump_file, "Single value %i stringop transformation on ",
1399                (int)val);
1400       print_generic_stmt (dump_file, stmt, TDF_SLIM);
1401     }
1402   tree_stringop_fixed_value (stmt, tree_val, prob, count, all);
1403   
1404   return true;
1405 }
1406
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 *);
1410
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);  
1414 };
1415 \f
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)
1420 {
1421   tree assign, lhs, rhs, divisor, op0, type;
1422   histogram_value hist;
1423
1424   if (TREE_CODE (stmt) == RETURN_EXPR)
1425     assign = TREE_OPERAND (stmt, 0);
1426   else
1427     assign = stmt;
1428
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;
1436
1437   rhs = GIMPLE_STMT_OPERAND (assign, 1);
1438   switch (TREE_CODE (rhs))
1439     {
1440     case TRUNC_DIV_EXPR:
1441     case TRUNC_MOD_EXPR:
1442       divisor = TREE_OPERAND (rhs, 1);
1443       op0 = TREE_OPERAND (rhs, 0);
1444
1445       VEC_reserve (histogram_value, heap, *values, 3);
1446
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));
1453
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))
1458         {
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));
1464
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);
1471         }
1472       return;
1473
1474     default:
1475       return;
1476     }
1477 }
1478
1479 /* Find calls inside STMT for that we want to measure histograms for 
1480    indirect/virtual call optimization. */ 
1481
1482 static void
1483 tree_indirect_call_to_profile (tree stmt, histogram_values *values)
1484 {
1485   tree                  call;
1486   tree                  callee;
1487
1488   call = get_call_expr_in (stmt);
1489
1490   if (!call || TREE_CODE (call) != CALL_EXPR)
1491     return;
1492
1493   callee = TREE_OPERAND (call, 0);
1494   
1495   if (TREE_CODE (callee) == ADDR_EXPR)
1496     return;
1497
1498   VEC_reserve (histogram_value, heap, *values, 3);
1499
1500   VEC_quick_push (histogram_value, *values, 
1501                   gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
1502                                                 stmt, callee));
1503
1504   return;
1505 }
1506
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)
1511 {
1512   tree call = get_call_expr_in (stmt);
1513   tree fndecl;
1514   tree arglist;
1515   tree blck_size;
1516   enum built_in_function fcode;
1517
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);
1525
1526   if (!interesting_stringop_to_profile_p (fndecl, arglist))
1527     return;
1528
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)));
1533
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));
1538 }
1539
1540 /* Find values inside STMT for that we want to measure histograms and adds
1541    them to list VALUES.  */
1542
1543 static void
1544 tree_values_to_profile (tree stmt, histogram_values *values)
1545 {
1546   if (flag_value_profile_transformations)
1547     {
1548       tree_divmod_values_to_profile (stmt, values);
1549       tree_stringops_values_to_profile (stmt, values);
1550       tree_indirect_call_to_profile (stmt, values);
1551     }
1552 }
1553
1554 static void
1555 tree_find_values_to_profile (histogram_values *values)
1556 {
1557   basic_block bb;
1558   block_stmt_iterator bsi;
1559   unsigned i;
1560   histogram_value hist = NULL;
1561
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);
1566   
1567   for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
1568     {
1569       switch (hist->type)
1570         {
1571         case HIST_TYPE_INTERVAL:
1572           hist->n_counters = hist->hdata.intvl.steps + 2;
1573           break;
1574
1575         case HIST_TYPE_POW2:
1576           hist->n_counters = 2;
1577           break;
1578
1579         case HIST_TYPE_SINGLE_VALUE:
1580           hist->n_counters = 3;
1581           break;
1582
1583         case HIST_TYPE_CONST_DELTA:
1584           hist->n_counters = 4;
1585           break;
1586
1587         case HIST_TYPE_INDIR_CALL:
1588           hist->n_counters = 3;
1589           break;
1590
1591         default:
1592           gcc_unreachable ();
1593         }
1594       if (dump_file)
1595         {
1596           fprintf (dump_file, "Stmt ");
1597           print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
1598           dump_histogram_value (dump_file, hist);
1599         }
1600     }
1601 }
1602
1603 static struct value_prof_hooks tree_value_prof_hooks = {
1604   tree_find_values_to_profile,
1605   tree_value_profile_transformations
1606 };
1607
1608 void
1609 tree_register_value_prof_hooks (void)
1610 {
1611   gcc_assert (current_ir_type () == IR_GIMPLE);
1612   value_prof_hooks = &tree_value_prof_hooks;
1613 }
1614 \f
1615 /* IR-independent entry points.  */
1616 void
1617 find_values_to_profile (histogram_values *values)
1618 {
1619   (value_prof_hooks->find_values_to_profile) (values);
1620 }
1621
1622 bool
1623 value_profile_transformations (void)
1624 {
1625   return (value_prof_hooks->value_profile_transformations) ();
1626 }
1627 \f
1628