1 /* Transformations based on profile information for values.
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "value-prof.h"
32 #include "insn-config.h"
37 #include "tree-flow.h"
38 #include "tree-flow-inline.h"
39 #include "diagnostic.h"
44 #include "tree-pass.h"
46 #include "pointer-set.h"
48 static struct value_prof_hooks
*value_prof_hooks
;
50 /* In this file value profile based optimizations are placed. Currently the
51 following optimizations are implemented (for more detailed descriptions
52 see comments at value_profile_transformations):
54 1) Division/modulo specialization. Provided that we can determine that the
55 operands of the division have some special properties, we may use it to
56 produce more effective code.
57 2) Speculative prefetching. If we are able to determine that the difference
58 between addresses accessed by a memory reference is usually constant, we
59 may add the prefetch instructions.
60 FIXME: This transformation was removed together with RTL based value
63 Every such optimization should add its requirements for profiled values to
64 insn_values_to_profile function. This function is called from branch_prob
65 in profile.c and the requested values are instrumented by it in the first
66 compilation with -fprofile-arcs. The optimization may then read the
67 gathered data in the second compilation with -fbranch-probabilities.
69 The measured data is pointed to from the histograms
70 field of the statement annotation of the instrumented insns. It is
71 kept as a linked list of struct histogram_value_t's, which contain the
72 same information as above. */
75 static tree
tree_divmod_fixed_value (tree
, tree
, tree
, tree
,
76 tree
, int, gcov_type
, gcov_type
);
77 static tree
tree_mod_pow2 (tree
, tree
, tree
, tree
, int, gcov_type
, gcov_type
);
78 static tree
tree_mod_subtract (tree
, tree
, tree
, tree
, int, int, int,
79 gcov_type
, gcov_type
, gcov_type
);
80 static bool tree_divmod_fixed_value_transform (tree
);
81 static bool tree_mod_pow2_value_transform (tree
);
82 static bool tree_mod_subtract_transform (tree
);
83 static bool tree_stringops_transform (block_stmt_iterator
*);
85 /* Allocate histogram value. */
87 static histogram_value
88 gimple_alloc_histogram_value (struct function
*fun ATTRIBUTE_UNUSED
,
89 enum hist_type type
, tree stmt
, tree value
)
91 histogram_value hist
= (histogram_value
) xcalloc (1, sizeof (*hist
));
92 hist
->hvalue
.value
= value
;
93 hist
->hvalue
.stmt
= stmt
;
98 /* Hash value for histogram. */
101 histogram_hash (const void *x
)
103 return htab_hash_pointer (((histogram_value
)x
)->hvalue
.stmt
);
106 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
109 histogram_eq (const void *x
, const void *y
)
111 return ((histogram_value
) x
)->hvalue
.stmt
== (tree
)y
;
114 /* Set histogram for STMT. */
117 set_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
120 if (!hist
&& !VALUE_HISTOGRAMS (fun
))
122 if (!VALUE_HISTOGRAMS (fun
))
123 VALUE_HISTOGRAMS (fun
) = htab_create (1, histogram_hash
,
125 loc
= htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
126 htab_hash_pointer (stmt
),
127 hist
? INSERT
: NO_INSERT
);
131 htab_clear_slot (VALUE_HISTOGRAMS (fun
), loc
);
137 /* Get histogram list for STMT. */
140 gimple_histogram_value (struct function
*fun
, tree stmt
)
142 if (!VALUE_HISTOGRAMS (fun
))
144 return htab_find_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
145 htab_hash_pointer (stmt
));
148 /* Add histogram for STMT. */
151 gimple_add_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
153 hist
->hvalue
.next
= gimple_histogram_value (fun
, stmt
);
154 set_histogram_value (fun
, stmt
, hist
);
157 /* Remove histogram HIST from STMT's histogram list. */
160 gimple_remove_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
162 histogram_value hist2
= gimple_histogram_value (fun
, stmt
);
165 set_histogram_value (fun
, stmt
, hist
->hvalue
.next
);
169 while (hist2
->hvalue
.next
!= hist
)
170 hist2
= hist2
->hvalue
.next
;
171 hist2
->hvalue
.next
= hist
->hvalue
.next
;
173 free (hist
->hvalue
.counters
);
174 #ifdef ENABLE_CHECKING
175 memset (hist
, 0xab, sizeof (*hist
));
180 /* Lookup histogram of type TYPE in the STMT. */
183 gimple_histogram_value_of_type (struct function
*fun
, tree stmt
, enum hist_type type
)
185 histogram_value hist
;
186 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
187 if (hist
->type
== type
)
192 /* Dump information about HIST to DUMP_FILE. */
195 dump_histogram_value (FILE *dump_file
, histogram_value hist
)
199 case HIST_TYPE_INTERVAL
:
200 fprintf (dump_file
, "Interval counter range %d -- %d",
201 hist
->hdata
.intvl
.int_start
,
202 (hist
->hdata
.intvl
.int_start
203 + hist
->hdata
.intvl
.steps
- 1));
204 if (hist
->hvalue
.counters
)
207 fprintf(dump_file
, " [");
208 for (i
= 0; i
< hist
->hdata
.intvl
.steps
; i
++)
209 fprintf (dump_file
, " %d:"HOST_WIDEST_INT_PRINT_DEC
,
210 hist
->hdata
.intvl
.int_start
+ i
,
211 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
212 fprintf (dump_file
, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC
,
213 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
215 fprintf (dump_file
, ".\n");
219 fprintf (dump_file
, "Pow2 counter ");
220 if (hist
->hvalue
.counters
)
222 fprintf (dump_file
, "pow2:"HOST_WIDEST_INT_PRINT_DEC
223 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC
,
224 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
225 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1]);
227 fprintf (dump_file
, ".\n");
230 case HIST_TYPE_SINGLE_VALUE
:
231 fprintf (dump_file
, "Single value ");
232 if (hist
->hvalue
.counters
)
234 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
235 " match:"HOST_WIDEST_INT_PRINT_DEC
236 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
237 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
238 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
239 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
241 fprintf (dump_file
, ".\n");
244 case HIST_TYPE_CONST_DELTA
:
245 fprintf (dump_file
, "Constant delta ");
246 if (hist
->hvalue
.counters
)
248 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
249 " match:"HOST_WIDEST_INT_PRINT_DEC
250 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
251 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
252 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
253 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
255 fprintf (dump_file
, ".\n");
260 /* Dump all histograms attached to STMT to DUMP_FILE. */
263 dump_histograms_for_stmt (struct function
*fun
, FILE *dump_file
, tree stmt
)
265 histogram_value hist
;
266 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
267 dump_histogram_value (dump_file
, hist
);
270 /* Remove all histograms associated with STMT. */
273 gimple_remove_stmt_histograms (struct function
*fun
, tree stmt
)
276 while ((val
= gimple_histogram_value (fun
, stmt
)) != NULL
)
277 gimple_remove_histogram_value (fun
, stmt
, val
);
280 /* Duplicate all histograms associates with OSTMT to STMT. */
283 gimple_duplicate_stmt_histograms (struct function
*fun
, tree stmt
,
284 struct function
*ofun
, tree ostmt
)
287 for (val
= gimple_histogram_value (ofun
, ostmt
); val
!= NULL
; val
= val
->hvalue
.next
)
289 histogram_value
new = gimple_alloc_histogram_value (fun
, val
->type
, NULL
, NULL
);
290 memcpy (new, val
, sizeof (*val
));
291 new->hvalue
.stmt
= stmt
;
292 new->hvalue
.counters
= xmalloc (sizeof (*new->hvalue
.counters
) * new->n_counters
);
293 memcpy (new->hvalue
.counters
, val
->hvalue
.counters
, sizeof (*new->hvalue
.counters
) * new->n_counters
);
294 gimple_add_histogram_value (fun
, stmt
, new);
298 static bool error_found
= false;
300 /* Helper function for verify_histograms. For each histogram reachable via htab
301 walk verify that it was reached via statement walk. */
304 visit_hist (void **slot
, void *data
)
306 struct pointer_set_t
*visited
= (struct pointer_set_t
*) data
;
307 histogram_value hist
= *(histogram_value
*) slot
;
308 if (!pointer_set_contains (visited
, hist
))
310 error ("Dead histogram");
311 dump_histogram_value (stderr
, hist
);
312 debug_generic_stmt (hist
->hvalue
.stmt
);
318 /* Verify sanity of the histograms. */
321 verify_histograms (void)
324 block_stmt_iterator bsi
;
325 histogram_value hist
;
326 struct pointer_set_t
*visited_hists
;
329 visited_hists
= pointer_set_create ();
331 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
333 tree stmt
= bsi_stmt (bsi
);
335 for (hist
= gimple_histogram_value (cfun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
337 if (hist
->hvalue
.stmt
!= stmt
)
339 error ("Histogram value statement does not correspond to statement"
340 " it is associated with");
341 debug_generic_stmt (stmt
);
342 dump_histogram_value (stderr
, hist
);
345 pointer_set_insert (visited_hists
, hist
);
348 if (VALUE_HISTOGRAMS (cfun
))
349 htab_traverse (VALUE_HISTOGRAMS (cfun
), visit_hist
, visited_hists
);
350 pointer_set_destroy (visited_hists
);
352 internal_error ("verify_histograms failed");
355 /* Helper function for verify_histograms. For each histogram reachable via htab
356 walk verify that it was reached via statement walk. */
359 free_hist (void **slot
, void *data ATTRIBUTE_UNUSED
)
361 histogram_value hist
= *(histogram_value
*) slot
;
362 free (hist
->hvalue
.counters
);
363 #ifdef ENABLE_CHECKING
364 memset (hist
, 0xab, sizeof (*hist
));
371 free_histograms (void)
373 if (VALUE_HISTOGRAMS (cfun
))
375 htab_traverse (VALUE_HISTOGRAMS (cfun
), free_hist
, NULL
);
376 htab_delete (VALUE_HISTOGRAMS (cfun
));
377 VALUE_HISTOGRAMS (cfun
) = NULL
;
381 /* The overall number of invocations of the counter should match execution count
382 of basic block. Report it as error rather than internal error as it might
383 mean that user has misused the profile somehow. */
385 check_counter (tree stmt
, const char * name
, gcov_type all
, gcov_type bb_count
)
390 locus
= (stmt
!= NULL
&& EXPR_HAS_LOCATION (stmt
)
392 : &DECL_SOURCE_LOCATION (current_function_decl
));
393 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
394 locus
, name
, (int)all
, (int)bb_count
);
400 /* Tree based transformations. */
402 tree_value_profile_transformations (void)
405 block_stmt_iterator bsi
;
406 bool changed
= false;
410 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
412 tree stmt
= bsi_stmt (bsi
);
413 histogram_value th
= gimple_histogram_value (cfun
, stmt
);
419 fprintf (dump_file
, "Trying transformations on stmt ");
420 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
421 dump_histograms_for_stmt (cfun
, dump_file
, stmt
);
424 /* Transformations: */
425 /* The order of things in this conditional controls which
426 transformation is used when more than one is applicable. */
427 /* It is expected that any code added by the transformations
428 will be added before the current statement, and that the
429 current statement remain valid (although possibly
430 modified) upon return. */
431 if (flag_value_profile_transformations
432 && (tree_mod_subtract_transform (stmt
)
433 || tree_divmod_fixed_value_transform (stmt
)
434 || tree_mod_pow2_value_transform (stmt
)
435 || tree_stringops_transform (&bsi
)))
437 stmt
= bsi_stmt (bsi
);
439 /* Original statement may no longer be in the same block. */
440 if (bb
!= bb_for_stmt (stmt
))
442 bb
= bb_for_stmt (stmt
);
443 bsi
= bsi_for_stmt (stmt
);
457 /* Generate code for transformation 1 (with OPERATION, operands OP1
458 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
459 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
460 within roundoff error). This generates the result into a temp and returns
461 the temp; it does not replace or alter the original STMT. */
463 tree_divmod_fixed_value (tree stmt
, tree operation
,
464 tree op1
, tree op2
, tree value
, int prob
, gcov_type count
,
467 tree stmt1
, stmt2
, stmt3
;
468 tree tmp1
, tmp2
, tmpv
;
469 tree label_decl1
= create_artificial_label ();
470 tree label_decl2
= create_artificial_label ();
472 tree bb1end
, bb2end
, bb3end
;
473 basic_block bb
, bb2
, bb3
, bb4
;
474 tree optype
= TREE_TYPE (operation
);
475 edge e12
, e13
, e23
, e24
, e34
;
476 block_stmt_iterator bsi
;
478 bb
= bb_for_stmt (stmt
);
479 bsi
= bsi_for_stmt (stmt
);
481 tmpv
= create_tmp_var (optype
, "PROF");
482 tmp1
= create_tmp_var (optype
, "PROF");
483 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmpv
,
484 fold_convert (optype
, value
));
485 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
, op2
);
486 stmt3
= build3 (COND_EXPR
, void_type_node
,
487 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
488 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
489 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
490 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
491 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
492 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
495 tmp2
= create_tmp_var (optype
, "PROF");
496 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
497 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp2
,
498 build2 (TREE_CODE (operation
), optype
, op1
, tmpv
));
499 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
500 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
503 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
504 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp2
,
505 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
506 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
507 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
511 /* Edge e23 connects bb2 to bb3, etc. */
512 e12
= split_block (bb
, bb1end
);
515 e23
= split_block (bb2
, bb2end
);
517 bb3
->count
= all
- count
;
518 e34
= split_block (bb3
, bb3end
);
522 e12
->flags
&= ~EDGE_FALLTHRU
;
523 e12
->flags
|= EDGE_FALSE_VALUE
;
524 e12
->probability
= prob
;
527 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
528 e13
->probability
= REG_BR_PROB_BASE
- prob
;
529 e13
->count
= all
- count
;
533 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
534 e24
->probability
= REG_BR_PROB_BASE
;
537 e34
->probability
= REG_BR_PROB_BASE
;
538 e34
->count
= all
- count
;
543 /* Do transform 1) on INSN if applicable. */
545 tree_divmod_fixed_value_transform (tree stmt
)
547 histogram_value histogram
;
549 gcov_type val
, count
, all
;
550 tree modify
, op
, op1
, op2
, result
, value
, tree_val
;
554 if (TREE_CODE (stmt
) == RETURN_EXPR
555 && TREE_OPERAND (stmt
, 0)
556 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
557 modify
= TREE_OPERAND (stmt
, 0);
558 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
560 op
= GIMPLE_STMT_OPERAND (modify
, 1);
561 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
563 code
= TREE_CODE (op
);
565 if (code
!= TRUNC_DIV_EXPR
&& code
!= TRUNC_MOD_EXPR
)
568 op1
= TREE_OPERAND (op
, 0);
569 op2
= TREE_OPERAND (op
, 1);
571 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
575 value
= histogram
->hvalue
.value
;
576 val
= histogram
->hvalue
.counters
[0];
577 count
= histogram
->hvalue
.counters
[1];
578 all
= histogram
->hvalue
.counters
[2];
579 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
581 /* We require that count is at least half of all; this means
582 that for the transformation to fire the value must be constant
583 at least 50% of time (and 75% gives the guarantee of usage). */
584 if (simple_cst_equal (op2
, value
) != 1 || 2 * count
< all
585 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
588 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
591 /* Compute probability of taking the optimal path. */
592 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
594 tree_val
= build_int_cst_wide (get_gcov_type (),
595 (unsigned HOST_WIDE_INT
) val
,
596 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
597 result
= tree_divmod_fixed_value (stmt
, op
, op1
, op2
, tree_val
, prob
, count
, all
);
601 fprintf (dump_file
, "Div/mod by constant ");
602 print_generic_expr (dump_file
, value
, TDF_SLIM
);
603 fprintf (dump_file
, "=");
604 print_generic_expr (dump_file
, tree_val
, TDF_SLIM
);
605 fprintf (dump_file
, " transformation on insn ");
606 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
609 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
614 /* Generate code for transformation 2 (with OPERATION, operands OP1
615 and OP2, parent modify-expr STMT and probability of taking the optimal
616 path PROB, which is equivalent to COUNT/ALL within roundoff error).
617 This generates the result into a temp and returns
618 the temp; it does not replace or alter the original STMT. */
620 tree_mod_pow2 (tree stmt
, tree operation
, tree op1
, tree op2
, int prob
,
621 gcov_type count
, gcov_type all
)
623 tree stmt1
, stmt2
, stmt3
, stmt4
;
625 tree label_decl1
= create_artificial_label ();
626 tree label_decl2
= create_artificial_label ();
628 tree bb1end
, bb2end
, bb3end
;
629 basic_block bb
, bb2
, bb3
, bb4
;
630 tree optype
= TREE_TYPE (operation
);
631 edge e12
, e13
, e23
, e24
, e34
;
632 block_stmt_iterator bsi
;
633 tree result
= create_tmp_var (optype
, "PROF");
635 bb
= bb_for_stmt (stmt
);
636 bsi
= bsi_for_stmt (stmt
);
638 tmp2
= create_tmp_var (optype
, "PROF");
639 tmp3
= create_tmp_var (optype
, "PROF");
640 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp2
,
641 build2 (PLUS_EXPR
, optype
, op2
, build_int_cst (optype
, -1)));
642 stmt3
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp3
,
643 build2 (BIT_AND_EXPR
, optype
, tmp2
, op2
));
644 stmt4
= build3 (COND_EXPR
, void_type_node
,
645 build2 (NE_EXPR
, boolean_type_node
,
646 tmp3
, build_int_cst (optype
, 0)),
647 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
648 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
649 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
650 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
651 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
654 /* tmp2 == op2-1 inherited from previous block */
655 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
656 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
,
657 build2 (BIT_AND_EXPR
, optype
, op1
, tmp2
));
658 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
659 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
662 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
663 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
,
664 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
665 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
666 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
670 /* Edge e23 connects bb2 to bb3, etc. */
671 e12
= split_block (bb
, bb1end
);
674 e23
= split_block (bb2
, bb2end
);
676 bb3
->count
= all
- count
;
677 e34
= split_block (bb3
, bb3end
);
681 e12
->flags
&= ~EDGE_FALLTHRU
;
682 e12
->flags
|= EDGE_FALSE_VALUE
;
683 e12
->probability
= prob
;
686 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
687 e13
->probability
= REG_BR_PROB_BASE
- prob
;
688 e13
->count
= all
- count
;
692 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
693 e24
->probability
= REG_BR_PROB_BASE
;
696 e34
->probability
= REG_BR_PROB_BASE
;
697 e34
->count
= all
- count
;
702 /* Do transform 2) on INSN if applicable. */
704 tree_mod_pow2_value_transform (tree stmt
)
706 histogram_value histogram
;
708 gcov_type count
, wrong_values
, all
;
709 tree modify
, op
, op1
, op2
, result
, value
;
713 if (TREE_CODE (stmt
) == RETURN_EXPR
714 && TREE_OPERAND (stmt
, 0)
715 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
716 modify
= TREE_OPERAND (stmt
, 0);
717 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
719 op
= GIMPLE_STMT_OPERAND (modify
, 1);
720 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
722 code
= TREE_CODE (op
);
724 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
727 op1
= TREE_OPERAND (op
, 0);
728 op2
= TREE_OPERAND (op
, 1);
730 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_POW2
);
734 value
= histogram
->hvalue
.value
;
735 wrong_values
= histogram
->hvalue
.counters
[0];
736 count
= histogram
->hvalue
.counters
[1];
738 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
740 /* We require that we hit a power of 2 at least half of all evaluations. */
741 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
742 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
747 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
748 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
751 /* Compute probability of taking the optimal path. */
752 all
= count
+ wrong_values
;
754 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
757 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
759 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
761 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
766 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
767 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
768 support. Currently only NCOUNTS==0 or 1 is supported and this is
769 built into this interface. The probabilities of taking the optimal
770 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
771 COUNT2/ALL respectively within roundoff error). This generates the
772 result into a temp and returns the temp; it does not replace or alter
773 the original STMT. */
774 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
777 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
778 int prob1
, int prob2
, int ncounts
,
779 gcov_type count1
, gcov_type count2
, gcov_type all
)
781 tree stmt1
, stmt2
, stmt3
;
783 tree label_decl1
= create_artificial_label ();
784 tree label_decl2
= create_artificial_label ();
785 tree label_decl3
= create_artificial_label ();
786 tree label1
, label2
, label3
;
787 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
788 basic_block bb
, bb2
, bb3
, bb4
;
789 tree optype
= TREE_TYPE (operation
);
790 edge e12
, e23
= 0, e24
, e34
, e14
;
791 block_stmt_iterator bsi
;
792 tree result
= create_tmp_var (optype
, "PROF");
794 bb
= bb_for_stmt (stmt
);
795 bsi
= bsi_for_stmt (stmt
);
797 tmp1
= create_tmp_var (optype
, "PROF");
798 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
, op1
);
799 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
, op2
);
800 stmt3
= build3 (COND_EXPR
, void_type_node
,
801 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
802 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
803 build1 (GOTO_EXPR
, void_type_node
,
804 ncounts
? label_decl1
: label_decl2
));
805 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
806 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
807 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
810 if (ncounts
) /* Assumed to be 0 or 1 */
812 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
813 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
,
814 build2 (MINUS_EXPR
, optype
, result
, tmp1
));
815 stmt2
= build3 (COND_EXPR
, void_type_node
,
816 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
817 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
818 build1 (GOTO_EXPR
, void_type_node
, label_decl2
));
819 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
820 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
821 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
826 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
827 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
,
828 build2 (TREE_CODE (operation
), optype
, result
, tmp1
));
829 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
830 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
833 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
834 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
837 /* Edge e23 connects bb2 to bb3, etc. */
838 /* However block 3 is optional; if it is not there, references
839 to 3 really refer to block 2. */
840 e12
= split_block (bb
, bb1end
);
842 bb2
->count
= all
- count1
;
844 if (ncounts
) /* Assumed to be 0 or 1. */
846 e23
= split_block (bb2
, bb2end
);
848 bb3
->count
= all
- count1
- count2
;
851 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
855 e12
->flags
&= ~EDGE_FALLTHRU
;
856 e12
->flags
|= EDGE_FALSE_VALUE
;
857 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
858 e12
->count
= all
- count1
;
860 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
861 e14
->probability
= prob1
;
864 if (ncounts
) /* Assumed to be 0 or 1. */
866 e23
->flags
&= ~EDGE_FALLTHRU
;
867 e23
->flags
|= EDGE_FALSE_VALUE
;
868 e23
->count
= all
- count1
- count2
;
869 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
871 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
872 e24
->probability
= prob2
;
876 e34
->probability
= REG_BR_PROB_BASE
;
877 e34
->count
= all
- count1
- count2
;
882 /* Do transforms 3) and 4) on INSN if applicable. */
884 tree_mod_subtract_transform (tree stmt
)
886 histogram_value histogram
;
888 gcov_type count
, wrong_values
, all
;
889 tree modify
, op
, op1
, op2
, result
, value
;
891 unsigned int i
, steps
;
892 gcov_type count1
, count2
;
895 if (TREE_CODE (stmt
) == RETURN_EXPR
896 && TREE_OPERAND (stmt
, 0)
897 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
898 modify
= TREE_OPERAND (stmt
, 0);
899 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
901 op
= GIMPLE_STMT_OPERAND (modify
, 1);
902 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
904 code
= TREE_CODE (op
);
906 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
909 op1
= TREE_OPERAND (op
, 0);
910 op2
= TREE_OPERAND (op
, 1);
912 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_INTERVAL
);
916 value
= histogram
->hvalue
.value
;
919 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
920 all
+= histogram
->hvalue
.counters
[i
];
922 wrong_values
+= histogram
->hvalue
.counters
[i
];
923 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
924 steps
= histogram
->hdata
.intvl
.steps
;
926 count1
= histogram
->hvalue
.counters
[0];
927 count2
= histogram
->hvalue
.counters
[1];
929 /* Compute probability of taking the optimal path. */
930 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
932 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
936 /* We require that we use just subtractions in at least 50% of all
939 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
941 count
+= histogram
->hvalue
.counters
[i
];
942 if (count
* 2 >= all
)
946 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
949 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
952 fprintf (dump_file
, "Mod subtract transformation on insn ");
953 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
956 /* Compute probability of taking the optimal path(s). */
957 prob1
= (count1
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
958 prob2
= (count2
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
960 /* In practice, "steps" is always 2. This interface reflects this,
961 and will need to be changed if "steps" can change. */
962 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
963 count1
, count2
, all
);
965 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
970 /* Return true if the stringop FNDECL with ARGLIST shall be profiled. */
972 interesting_stringop_to_profile_p (tree fndecl
, tree arglist
)
974 enum built_in_function fcode
= DECL_FUNCTION_CODE (fndecl
);
976 if (fcode
!= BUILT_IN_MEMSET
&& fcode
!= BUILT_IN_MEMCPY
977 && fcode
!= BUILT_IN_BZERO
)
982 case BUILT_IN_MEMCPY
:
983 case BUILT_IN_MEMPCPY
:
984 return validate_arglist (arglist
,
985 POINTER_TYPE
, POINTER_TYPE
, INTEGER_TYPE
,
987 case BUILT_IN_MEMSET
:
988 return validate_arglist (arglist
,
989 POINTER_TYPE
, INTEGER_TYPE
, INTEGER_TYPE
,
992 return validate_arglist (arglist
, POINTER_TYPE
, INTEGER_TYPE
,
999 /* Convert stringop (..., size)
1002 stringop (...., VALUE);
1004 stringop (...., size);
1005 assuming constant propagation of VALUE will happen later.
1008 tree_stringop_fixed_value (tree stmt
, tree value
, int prob
, gcov_type count
,
1011 tree stmt1
, stmt2
, stmt3
;
1013 tree label_decl1
= create_artificial_label ();
1014 tree label_decl2
= create_artificial_label ();
1015 tree label1
, label2
;
1016 tree bb1end
, bb2end
;
1017 basic_block bb
, bb2
, bb3
, bb4
;
1018 edge e12
, e13
, e23
, e24
, e34
;
1019 block_stmt_iterator bsi
;
1020 tree call
= get_call_expr_in (stmt
);
1021 tree arglist
= TREE_OPERAND (call
, 1);
1022 tree blck_size
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
1023 tree optype
= TREE_TYPE (blck_size
);
1026 bb
= bb_for_stmt (stmt
);
1027 bsi
= bsi_for_stmt (stmt
);
1029 if (bsi_end_p (bsi
))
1032 for (ei
= ei_start (bb
->succs
); (e34
= ei_safe_edge (ei
)); )
1033 if (!e34
->flags
& EDGE_ABNORMAL
)
1038 e34
= split_block (bb
, stmt
);
1039 bsi
= bsi_for_stmt (stmt
);
1043 tmpv
= create_tmp_var (optype
, "PROF");
1044 tmp1
= create_tmp_var (optype
, "PROF");
1045 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmpv
,
1046 fold_convert (optype
, value
));
1047 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
, blck_size
);
1048 stmt3
= build3 (COND_EXPR
, void_type_node
,
1049 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
1050 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
1051 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
1052 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1053 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
1054 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
1057 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
1058 stmt1
= unshare_expr (stmt
);
1059 call
= get_call_expr_in (stmt1
);
1060 arglist
= TREE_OPERAND (call
, 1);
1061 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
))) = value
;
1062 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
1063 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1064 region
= lookup_stmt_eh_region (stmt
);
1066 add_stmt_to_eh_region (stmt1
, region
);
1068 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
1069 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
1072 /* Edge e23 connects bb2 to bb3, etc. */
1073 e12
= split_block (bb
, bb1end
);
1076 e23
= split_block (bb2
, bb2end
);
1078 bb3
->count
= all
- count
;
1080 e12
->flags
&= ~EDGE_FALLTHRU
;
1081 e12
->flags
|= EDGE_FALSE_VALUE
;
1082 e12
->probability
= prob
;
1085 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
1086 e13
->probability
= REG_BR_PROB_BASE
- prob
;
1087 e13
->count
= all
- count
;
1091 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
1092 e24
->probability
= REG_BR_PROB_BASE
;
1095 e34
->probability
= REG_BR_PROB_BASE
;
1096 e34
->count
= all
- count
;
1099 /* Find values inside STMT for that we want to measure histograms for
1100 division/modulo optimization. */
1102 tree_stringops_transform (block_stmt_iterator
*bsi
)
1104 tree stmt
= bsi_stmt (*bsi
);
1105 tree call
= get_call_expr_in (stmt
);
1109 enum built_in_function fcode
;
1110 histogram_value histogram
;
1111 gcov_type count
, all
, val
;
1114 unsigned int dest_align
, src_align
;
1120 fndecl
= get_callee_fndecl (call
);
1123 fcode
= DECL_FUNCTION_CODE (fndecl
);
1124 arglist
= TREE_OPERAND (call
, 1);
1125 if (!interesting_stringop_to_profile_p (fndecl
, arglist
))
1128 if (fcode
== BUILT_IN_BZERO
)
1129 blck_size
= TREE_VALUE (TREE_CHAIN (arglist
));
1131 blck_size
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
1132 if (TREE_CODE (blck_size
) == INTEGER_CST
)
1135 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
1138 value
= histogram
->hvalue
.value
;
1139 val
= histogram
->hvalue
.counters
[0];
1140 count
= histogram
->hvalue
.counters
[1];
1141 all
= histogram
->hvalue
.counters
[2];
1142 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1143 /* We require that count is at least half of all; this means
1144 that for the transformation to fire the value must be constant
1145 at least 80% of time. */
1146 if ((6 * count
/ 5) < all
|| !maybe_hot_bb_p (bb_for_stmt (stmt
)))
1148 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
1150 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1151 dest
= TREE_VALUE (arglist
);
1152 dest_align
= get_pointer_alignment (dest
, BIGGEST_ALIGNMENT
);
1155 case BUILT_IN_MEMCPY
:
1156 case BUILT_IN_MEMPCPY
:
1157 src
= TREE_VALUE (TREE_CHAIN (arglist
));
1158 src_align
= get_pointer_alignment (src
, BIGGEST_ALIGNMENT
);
1159 if (!can_move_by_pieces (val
, MIN (dest_align
, src_align
)))
1162 case BUILT_IN_MEMSET
:
1163 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
1164 TREE_VALUE (TREE_CHAIN (arglist
)),
1168 case BUILT_IN_BZERO
:
1169 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
1177 tree_val
= build_int_cst_wide (get_gcov_type (),
1178 (unsigned HOST_WIDE_INT
) val
,
1179 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
1182 fprintf (dump_file
, "Single value %i stringop transformation on ",
1184 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
1186 tree_stringop_fixed_value (stmt
, tree_val
, prob
, count
, all
);
1191 struct value_prof_hooks
{
1192 /* Find list of values for which we want to measure histograms. */
1193 void (*find_values_to_profile
) (histogram_values
*);
1195 /* Identify and exploit properties of values that are hard to analyze
1196 statically. See value-prof.c for more detail. */
1197 bool (*value_profile_transformations
) (void);
1200 /* Find values inside STMT for that we want to measure histograms for
1201 division/modulo optimization. */
1203 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
1205 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
1206 histogram_value hist
;
1208 if (TREE_CODE (stmt
) == RETURN_EXPR
)
1209 assign
= TREE_OPERAND (stmt
, 0);
1214 || TREE_CODE (assign
) != GIMPLE_MODIFY_STMT
)
1216 lhs
= GIMPLE_STMT_OPERAND (assign
, 0);
1217 type
= TREE_TYPE (lhs
);
1218 if (!INTEGRAL_TYPE_P (type
))
1221 rhs
= GIMPLE_STMT_OPERAND (assign
, 1);
1222 switch (TREE_CODE (rhs
))
1224 case TRUNC_DIV_EXPR
:
1225 case TRUNC_MOD_EXPR
:
1226 divisor
= TREE_OPERAND (rhs
, 1);
1227 op0
= TREE_OPERAND (rhs
, 0);
1229 VEC_reserve (histogram_value
, heap
, *values
, 3);
1231 if (is_gimple_reg (divisor
))
1232 /* Check for the case where the divisor is the same value most
1234 VEC_quick_push (histogram_value
, *values
,
1235 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
1238 /* For mod, check whether it is not often a noop (or replaceable by
1239 a few subtractions). */
1240 if (TREE_CODE (rhs
) == TRUNC_MOD_EXPR
1241 && TYPE_UNSIGNED (type
))
1244 /* Check for a special case where the divisor is power of 2. */
1245 VEC_quick_push (histogram_value
, *values
,
1246 gimple_alloc_histogram_value (cfun
, HIST_TYPE_POW2
,
1249 val
= build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
1250 hist
= gimple_alloc_histogram_value (cfun
, HIST_TYPE_INTERVAL
,
1252 hist
->hdata
.intvl
.int_start
= 0;
1253 hist
->hdata
.intvl
.steps
= 2;
1254 VEC_quick_push (histogram_value
, *values
, hist
);
1263 /* Find values inside STMT for that we want to measure histograms for
1264 string operations. */
1266 tree_stringops_values_to_profile (tree stmt
, histogram_values
*values
)
1268 tree call
= get_call_expr_in (stmt
);
1272 enum built_in_function fcode
;
1276 fndecl
= get_callee_fndecl (call
);
1279 fcode
= DECL_FUNCTION_CODE (fndecl
);
1280 arglist
= TREE_OPERAND (call
, 1);
1282 if (!interesting_stringop_to_profile_p (fndecl
, arglist
))
1285 if (fcode
== BUILT_IN_BZERO
)
1286 blck_size
= TREE_VALUE (TREE_CHAIN (arglist
));
1288 blck_size
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
1290 if (TREE_CODE (blck_size
) != INTEGER_CST
)
1291 VEC_safe_push (histogram_value
, heap
, *values
,
1292 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
1296 /* Find values inside STMT for that we want to measure histograms and adds
1297 them to list VALUES. */
1300 tree_values_to_profile (tree stmt
, histogram_values
*values
)
1302 if (flag_value_profile_transformations
)
1304 tree_divmod_values_to_profile (stmt
, values
);
1305 tree_stringops_values_to_profile (stmt
, values
);
1310 tree_find_values_to_profile (histogram_values
*values
)
1313 block_stmt_iterator bsi
;
1315 histogram_value hist
= NULL
;
1319 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
1320 tree_values_to_profile (bsi_stmt (bsi
), values
);
1322 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
1326 case HIST_TYPE_INTERVAL
:
1327 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
1330 case HIST_TYPE_POW2
:
1331 hist
->n_counters
= 2;
1334 case HIST_TYPE_SINGLE_VALUE
:
1335 hist
->n_counters
= 3;
1338 case HIST_TYPE_CONST_DELTA
:
1339 hist
->n_counters
= 4;
1347 fprintf (dump_file
, "Stmt ");
1348 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
1349 dump_histogram_value (dump_file
, hist
);
1354 static struct value_prof_hooks tree_value_prof_hooks
= {
1355 tree_find_values_to_profile
,
1356 tree_value_profile_transformations
1360 tree_register_value_prof_hooks (void)
1362 gcc_assert (current_ir_type () == IR_GIMPLE
);
1363 value_prof_hooks
= &tree_value_prof_hooks
;
1366 /* IR-independent entry points. */
1368 find_values_to_profile (histogram_values
*values
)
1370 (value_prof_hooks
->find_values_to_profile
) (values
);
1374 value_profile_transformations (void)
1376 return (value_prof_hooks
->value_profile_transformations
) ();