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"
45 #include "tree-pass.h"
47 #include "pointer-set.h"
49 static struct value_prof_hooks
*value_prof_hooks
;
51 /* In this file value profile based optimizations are placed. Currently the
52 following optimizations are implemented (for more detailed descriptions
53 see comments at value_profile_transformations):
55 1) Division/modulo specialization. Provided that we can determine that the
56 operands of the division have some special properties, we may use it to
57 produce more effective code.
58 2) Speculative prefetching. If we are able to determine that the difference
59 between addresses accessed by a memory reference is usually constant, we
60 may add the prefetch instructions.
61 FIXME: This transformation was removed together with RTL based value
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
69 Every such optimization should add its requirements for profiled values to
70 insn_values_to_profile function. This function is called from branch_prob
71 in profile.c and the requested values are instrumented by it in the first
72 compilation with -fprofile-arcs. The optimization may then read the
73 gathered data in the second compilation with -fbranch-probabilities.
75 The measured data is pointed to from the histograms
76 field of the statement annotation of the instrumented insns. It is
77 kept as a linked list of struct histogram_value_t's, which contain the
78 same information as above. */
81 static tree
tree_divmod_fixed_value (tree
, tree
, tree
, tree
,
82 tree
, int, gcov_type
, gcov_type
);
83 static tree
tree_mod_pow2 (tree
, tree
, tree
, tree
, int, gcov_type
, gcov_type
);
84 static tree
tree_mod_subtract (tree
, tree
, tree
, tree
, int, int, int,
85 gcov_type
, gcov_type
, gcov_type
);
86 static bool tree_divmod_fixed_value_transform (tree
);
87 static bool tree_mod_pow2_value_transform (tree
);
88 static bool tree_mod_subtract_transform (tree
);
89 static bool tree_stringops_transform (block_stmt_iterator
*);
90 static bool tree_ic_transform (tree
);
92 /* Allocate histogram value. */
94 static histogram_value
95 gimple_alloc_histogram_value (struct function
*fun ATTRIBUTE_UNUSED
,
96 enum hist_type type
, tree stmt
, tree value
)
98 histogram_value hist
= (histogram_value
) xcalloc (1, sizeof (*hist
));
99 hist
->hvalue
.value
= value
;
100 hist
->hvalue
.stmt
= stmt
;
105 /* Hash value for histogram. */
108 histogram_hash (const void *x
)
110 return htab_hash_pointer (((histogram_value
)x
)->hvalue
.stmt
);
113 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
116 histogram_eq (const void *x
, const void *y
)
118 return ((histogram_value
) x
)->hvalue
.stmt
== (tree
)y
;
121 /* Set histogram for STMT. */
124 set_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
127 if (!hist
&& !VALUE_HISTOGRAMS (fun
))
129 if (!VALUE_HISTOGRAMS (fun
))
130 VALUE_HISTOGRAMS (fun
) = htab_create (1, histogram_hash
,
132 loc
= htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
133 htab_hash_pointer (stmt
),
134 hist
? INSERT
: NO_INSERT
);
138 htab_clear_slot (VALUE_HISTOGRAMS (fun
), loc
);
144 /* Get histogram list for STMT. */
147 gimple_histogram_value (struct function
*fun
, tree stmt
)
149 if (!VALUE_HISTOGRAMS (fun
))
151 return htab_find_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
152 htab_hash_pointer (stmt
));
155 /* Add histogram for STMT. */
158 gimple_add_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
160 hist
->hvalue
.next
= gimple_histogram_value (fun
, stmt
);
161 set_histogram_value (fun
, stmt
, hist
);
164 /* Remove histogram HIST from STMT's histogram list. */
167 gimple_remove_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
169 histogram_value hist2
= gimple_histogram_value (fun
, stmt
);
172 set_histogram_value (fun
, stmt
, hist
->hvalue
.next
);
176 while (hist2
->hvalue
.next
!= hist
)
177 hist2
= hist2
->hvalue
.next
;
178 hist2
->hvalue
.next
= hist
->hvalue
.next
;
180 free (hist
->hvalue
.counters
);
181 #ifdef ENABLE_CHECKING
182 memset (hist
, 0xab, sizeof (*hist
));
187 /* Lookup histogram of type TYPE in the STMT. */
190 gimple_histogram_value_of_type (struct function
*fun
, tree stmt
, enum hist_type type
)
192 histogram_value hist
;
193 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
194 if (hist
->type
== type
)
199 /* Dump information about HIST to DUMP_FILE. */
202 dump_histogram_value (FILE *dump_file
, histogram_value hist
)
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
)
214 fprintf(dump_file
, " [");
215 for (i
= 0; i
< hist
->hdata
.intvl
.steps
; i
++)
216 fprintf (dump_file
, " %d:"HOST_WIDEST_INT_PRINT_DEC
,
217 hist
->hdata
.intvl
.int_start
+ i
,
218 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
219 fprintf (dump_file
, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC
,
220 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
222 fprintf (dump_file
, ".\n");
226 fprintf (dump_file
, "Pow2 counter ");
227 if (hist
->hvalue
.counters
)
229 fprintf (dump_file
, "pow2:"HOST_WIDEST_INT_PRINT_DEC
230 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC
,
231 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
232 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1]);
234 fprintf (dump_file
, ".\n");
237 case HIST_TYPE_SINGLE_VALUE
:
238 fprintf (dump_file
, "Single value ");
239 if (hist
->hvalue
.counters
)
241 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
242 " match:"HOST_WIDEST_INT_PRINT_DEC
243 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
244 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
245 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
246 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
248 fprintf (dump_file
, ".\n");
251 case HIST_TYPE_CONST_DELTA
:
252 fprintf (dump_file
, "Constant delta ");
253 if (hist
->hvalue
.counters
)
255 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
256 " match:"HOST_WIDEST_INT_PRINT_DEC
257 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
258 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
259 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
260 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
262 fprintf (dump_file
, ".\n");
264 case HIST_TYPE_INDIR_CALL
:
265 fprintf (dump_file
, "Indirect call ");
266 if (hist
->hvalue
.counters
)
268 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
269 " match:"HOST_WIDEST_INT_PRINT_DEC
270 " all:"HOST_WIDEST_INT_PRINT_DEC
,
271 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
272 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
273 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
275 fprintf (dump_file
, ".\n");
280 /* Dump all histograms attached to STMT to DUMP_FILE. */
283 dump_histograms_for_stmt (struct function
*fun
, FILE *dump_file
, tree stmt
)
285 histogram_value hist
;
286 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
287 dump_histogram_value (dump_file
, hist
);
290 /* Remove all histograms associated with STMT. */
293 gimple_remove_stmt_histograms (struct function
*fun
, tree stmt
)
296 while ((val
= gimple_histogram_value (fun
, stmt
)) != NULL
)
297 gimple_remove_histogram_value (fun
, stmt
, val
);
300 /* Duplicate all histograms associates with OSTMT to STMT. */
303 gimple_duplicate_stmt_histograms (struct function
*fun
, tree stmt
,
304 struct function
*ofun
, tree ostmt
)
307 for (val
= gimple_histogram_value (ofun
, ostmt
); val
!= NULL
; val
= val
->hvalue
.next
)
309 histogram_value
new = gimple_alloc_histogram_value (fun
, val
->type
, NULL
, NULL
);
310 memcpy (new, val
, sizeof (*val
));
311 new->hvalue
.stmt
= stmt
;
312 new->hvalue
.counters
= xmalloc (sizeof (*new->hvalue
.counters
) * new->n_counters
);
313 memcpy (new->hvalue
.counters
, val
->hvalue
.counters
, sizeof (*new->hvalue
.counters
) * new->n_counters
);
314 gimple_add_histogram_value (fun
, stmt
, new);
318 static bool error_found
= false;
320 /* Helper function for verify_histograms. For each histogram reachable via htab
321 walk verify that it was reached via statement walk. */
324 visit_hist (void **slot
, void *data
)
326 struct pointer_set_t
*visited
= (struct pointer_set_t
*) data
;
327 histogram_value hist
= *(histogram_value
*) slot
;
328 if (!pointer_set_contains (visited
, hist
))
330 error ("Dead histogram");
331 dump_histogram_value (stderr
, hist
);
332 debug_generic_stmt (hist
->hvalue
.stmt
);
338 /* Verify sanity of the histograms. */
341 verify_histograms (void)
344 block_stmt_iterator bsi
;
345 histogram_value hist
;
346 struct pointer_set_t
*visited_hists
;
349 visited_hists
= pointer_set_create ();
351 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
353 tree stmt
= bsi_stmt (bsi
);
355 for (hist
= gimple_histogram_value (cfun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
357 if (hist
->hvalue
.stmt
!= stmt
)
359 error ("Histogram value statement does not correspond to statement"
360 " it is associated with");
361 debug_generic_stmt (stmt
);
362 dump_histogram_value (stderr
, hist
);
365 pointer_set_insert (visited_hists
, hist
);
368 if (VALUE_HISTOGRAMS (cfun
))
369 htab_traverse (VALUE_HISTOGRAMS (cfun
), visit_hist
, visited_hists
);
370 pointer_set_destroy (visited_hists
);
372 internal_error ("verify_histograms failed");
375 /* Helper function for verify_histograms. For each histogram reachable via htab
376 walk verify that it was reached via statement walk. */
379 free_hist (void **slot
, void *data ATTRIBUTE_UNUSED
)
381 histogram_value hist
= *(histogram_value
*) slot
;
382 free (hist
->hvalue
.counters
);
383 #ifdef ENABLE_CHECKING
384 memset (hist
, 0xab, sizeof (*hist
));
391 free_histograms (void)
393 if (VALUE_HISTOGRAMS (cfun
))
395 htab_traverse (VALUE_HISTOGRAMS (cfun
), free_hist
, NULL
);
396 htab_delete (VALUE_HISTOGRAMS (cfun
));
397 VALUE_HISTOGRAMS (cfun
) = NULL
;
401 /* The overall number of invocations of the counter should match execution count
402 of basic block. Report it as error rather than internal error as it might
403 mean that user has misused the profile somehow. */
405 check_counter (tree stmt
, const char * name
, gcov_type all
, gcov_type bb_count
)
410 locus
= (stmt
!= NULL
&& EXPR_HAS_LOCATION (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
);
420 /* Tree based transformations. */
422 tree_value_profile_transformations (void)
425 block_stmt_iterator bsi
;
426 bool changed
= false;
430 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
432 tree stmt
= bsi_stmt (bsi
);
433 histogram_value th
= gimple_histogram_value (cfun
, stmt
);
439 fprintf (dump_file
, "Trying transformations on stmt ");
440 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
441 dump_histograms_for_stmt (cfun
, dump_file
, stmt
);
444 /* Transformations: */
445 /* The order of things in this conditional controls which
446 transformation is used when more than one is applicable. */
447 /* It is expected that any code added by the transformations
448 will be added before the current statement, and that the
449 current statement remain valid (although possibly
450 modified) upon return. */
451 if (flag_value_profile_transformations
452 && (tree_mod_subtract_transform (stmt
)
453 || tree_divmod_fixed_value_transform (stmt
)
454 || tree_mod_pow2_value_transform (stmt
)
455 || tree_stringops_transform (&bsi
)
456 || tree_ic_transform (stmt
)))
458 stmt
= bsi_stmt (bsi
);
460 /* Original statement may no longer be in the same block. */
461 if (bb
!= bb_for_stmt (stmt
))
463 bb
= bb_for_stmt (stmt
);
464 bsi
= bsi_for_stmt (stmt
);
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. */
484 tree_divmod_fixed_value (tree stmt
, tree operation
,
485 tree op1
, tree op2
, tree value
, int prob
, gcov_type count
,
488 tree stmt1
, stmt2
, stmt3
;
489 tree tmp1
, tmp2
, tmpv
;
490 tree label_decl1
= create_artificial_label ();
491 tree label_decl2
= create_artificial_label ();
493 tree bb1end
, bb2end
, bb3end
;
494 basic_block bb
, bb2
, bb3
, bb4
;
495 tree optype
= TREE_TYPE (operation
);
496 edge e12
, e13
, e23
, e24
, e34
;
497 block_stmt_iterator bsi
;
499 bb
= bb_for_stmt (stmt
);
500 bsi
= bsi_for_stmt (stmt
);
502 tmpv
= create_tmp_var (optype
, "PROF");
503 tmp1
= create_tmp_var (optype
, "PROF");
504 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmpv
,
505 fold_convert (optype
, value
));
506 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
, op2
);
507 stmt3
= build3 (COND_EXPR
, void_type_node
,
508 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
509 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
510 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
511 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
512 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
513 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
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
);
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
);
532 /* Edge e23 connects bb2 to bb3, etc. */
533 e12
= split_block (bb
, bb1end
);
536 e23
= split_block (bb2
, bb2end
);
538 bb3
->count
= all
- count
;
539 e34
= split_block (bb3
, bb3end
);
543 e12
->flags
&= ~EDGE_FALLTHRU
;
544 e12
->flags
|= EDGE_FALSE_VALUE
;
545 e12
->probability
= prob
;
548 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
549 e13
->probability
= REG_BR_PROB_BASE
- prob
;
550 e13
->count
= all
- count
;
554 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
555 e24
->probability
= REG_BR_PROB_BASE
;
558 e34
->probability
= REG_BR_PROB_BASE
;
559 e34
->count
= all
- count
;
564 /* Do transform 1) on INSN if applicable. */
566 tree_divmod_fixed_value_transform (tree stmt
)
568 histogram_value histogram
;
570 gcov_type val
, count
, all
;
571 tree modify
, op
, op1
, op2
, result
, value
, tree_val
;
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
)
581 op
= GIMPLE_STMT_OPERAND (modify
, 1);
582 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
584 code
= TREE_CODE (op
);
586 if (code
!= TRUNC_DIV_EXPR
&& code
!= TRUNC_MOD_EXPR
)
589 op1
= TREE_OPERAND (op
, 0);
590 op2
= TREE_OPERAND (op
, 1);
592 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
596 value
= histogram
->hvalue
.value
;
597 val
= histogram
->hvalue
.counters
[0];
598 count
= histogram
->hvalue
.counters
[1];
599 all
= histogram
->hvalue
.counters
[2];
600 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
602 /* We require that count is at least half of all; this means
603 that for the transformation to fire the value must be constant
604 at least 50% of time (and 75% gives the guarantee of usage). */
605 if (simple_cst_equal (op2
, value
) != 1 || 2 * count
< all
606 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
609 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
612 /* Compute probability of taking the optimal path. */
613 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
615 tree_val
= build_int_cst_wide (get_gcov_type (),
616 (unsigned HOST_WIDE_INT
) val
,
617 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
618 result
= tree_divmod_fixed_value (stmt
, op
, op1
, op2
, tree_val
, prob
, count
, all
);
622 fprintf (dump_file
, "Div/mod by constant ");
623 print_generic_expr (dump_file
, value
, TDF_SLIM
);
624 fprintf (dump_file
, "=");
625 print_generic_expr (dump_file
, tree_val
, TDF_SLIM
);
626 fprintf (dump_file
, " transformation on insn ");
627 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
630 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
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. */
641 tree_mod_pow2 (tree stmt
, tree operation
, tree op1
, tree op2
, int prob
,
642 gcov_type count
, gcov_type all
)
644 tree stmt1
, stmt2
, stmt3
, stmt4
;
646 tree label_decl1
= create_artificial_label ();
647 tree label_decl2
= create_artificial_label ();
649 tree bb1end
, bb2end
, bb3end
;
650 basic_block bb
, bb2
, bb3
, bb4
;
651 tree optype
= TREE_TYPE (operation
);
652 edge e12
, e13
, e23
, e24
, e34
;
653 block_stmt_iterator bsi
;
654 tree result
= create_tmp_var (optype
, "PROF");
656 bb
= bb_for_stmt (stmt
);
657 bsi
= bsi_for_stmt (stmt
);
659 tmp2
= create_tmp_var (optype
, "PROF");
660 tmp3
= create_tmp_var (optype
, "PROF");
661 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp2
,
662 build2 (PLUS_EXPR
, optype
, op2
, build_int_cst (optype
, -1)));
663 stmt3
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp3
,
664 build2 (BIT_AND_EXPR
, optype
, tmp2
, op2
));
665 stmt4
= build3 (COND_EXPR
, void_type_node
,
666 build2 (NE_EXPR
, boolean_type_node
,
667 tmp3
, build_int_cst (optype
, 0)),
668 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
669 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
670 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
671 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
672 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
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
);
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
);
691 /* Edge e23 connects bb2 to bb3, etc. */
692 e12
= split_block (bb
, bb1end
);
695 e23
= split_block (bb2
, bb2end
);
697 bb3
->count
= all
- count
;
698 e34
= split_block (bb3
, bb3end
);
702 e12
->flags
&= ~EDGE_FALLTHRU
;
703 e12
->flags
|= EDGE_FALSE_VALUE
;
704 e12
->probability
= prob
;
707 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
708 e13
->probability
= REG_BR_PROB_BASE
- prob
;
709 e13
->count
= all
- count
;
713 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
714 e24
->probability
= REG_BR_PROB_BASE
;
717 e34
->probability
= REG_BR_PROB_BASE
;
718 e34
->count
= all
- count
;
723 /* Do transform 2) on INSN if applicable. */
725 tree_mod_pow2_value_transform (tree stmt
)
727 histogram_value histogram
;
729 gcov_type count
, wrong_values
, all
;
730 tree modify
, op
, op1
, op2
, result
, value
;
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
)
740 op
= GIMPLE_STMT_OPERAND (modify
, 1);
741 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
743 code
= TREE_CODE (op
);
745 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
748 op1
= TREE_OPERAND (op
, 0);
749 op2
= TREE_OPERAND (op
, 1);
751 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_POW2
);
755 value
= histogram
->hvalue
.value
;
756 wrong_values
= histogram
->hvalue
.counters
[0];
757 count
= histogram
->hvalue
.counters
[1];
759 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
761 /* We require that we hit a power of 2 at least half of all evaluations. */
762 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
763 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
768 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
769 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
772 /* Compute probability of taking the optimal path. */
773 all
= count
+ wrong_values
;
775 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
778 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
780 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
782 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
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. */
798 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
799 int prob1
, int prob2
, int ncounts
,
800 gcov_type count1
, gcov_type count2
, gcov_type all
)
802 tree stmt1
, stmt2
, stmt3
;
804 tree label_decl1
= create_artificial_label ();
805 tree label_decl2
= create_artificial_label ();
806 tree label_decl3
= create_artificial_label ();
807 tree label1
, label2
, label3
;
808 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
809 basic_block bb
, bb2
, bb3
, bb4
;
810 tree optype
= TREE_TYPE (operation
);
811 edge e12
, e23
= 0, e24
, e34
, e14
;
812 block_stmt_iterator bsi
;
813 tree result
= create_tmp_var (optype
, "PROF");
815 bb
= bb_for_stmt (stmt
);
816 bsi
= bsi_for_stmt (stmt
);
818 tmp1
= create_tmp_var (optype
, "PROF");
819 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
, op1
);
820 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
, op2
);
821 stmt3
= build3 (COND_EXPR
, void_type_node
,
822 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
823 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
824 build1 (GOTO_EXPR
, void_type_node
,
825 ncounts
? label_decl1
: label_decl2
));
826 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
827 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
828 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
831 if (ncounts
) /* Assumed to be 0 or 1 */
833 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
834 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, result
,
835 build2 (MINUS_EXPR
, optype
, result
, tmp1
));
836 stmt2
= build3 (COND_EXPR
, void_type_node
,
837 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
838 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
839 build1 (GOTO_EXPR
, void_type_node
, label_decl2
));
840 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
841 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
842 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
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
);
854 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
855 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
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
);
863 bb2
->count
= all
- count1
;
865 if (ncounts
) /* Assumed to be 0 or 1. */
867 e23
= split_block (bb2
, bb2end
);
869 bb3
->count
= all
- count1
- count2
;
872 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
876 e12
->flags
&= ~EDGE_FALLTHRU
;
877 e12
->flags
|= EDGE_FALSE_VALUE
;
878 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
879 e12
->count
= all
- count1
;
881 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
882 e14
->probability
= prob1
;
885 if (ncounts
) /* Assumed to be 0 or 1. */
887 e23
->flags
&= ~EDGE_FALLTHRU
;
888 e23
->flags
|= EDGE_FALSE_VALUE
;
889 e23
->count
= all
- count1
- count2
;
890 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
892 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
893 e24
->probability
= prob2
;
897 e34
->probability
= REG_BR_PROB_BASE
;
898 e34
->count
= all
- count1
- count2
;
903 /* Do transforms 3) and 4) on INSN if applicable. */
905 tree_mod_subtract_transform (tree stmt
)
907 histogram_value histogram
;
909 gcov_type count
, wrong_values
, all
;
910 tree modify
, op
, op1
, op2
, result
, value
;
912 unsigned int i
, steps
;
913 gcov_type count1
, count2
;
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
)
922 op
= GIMPLE_STMT_OPERAND (modify
, 1);
923 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
925 code
= TREE_CODE (op
);
927 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
930 op1
= TREE_OPERAND (op
, 0);
931 op2
= TREE_OPERAND (op
, 1);
933 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_INTERVAL
);
937 value
= histogram
->hvalue
.value
;
940 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
941 all
+= histogram
->hvalue
.counters
[i
];
943 wrong_values
+= histogram
->hvalue
.counters
[i
];
944 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
945 steps
= histogram
->hdata
.intvl
.steps
;
947 count1
= histogram
->hvalue
.counters
[0];
948 count2
= histogram
->hvalue
.counters
[1];
950 /* Compute probability of taking the optimal path. */
951 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
953 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
957 /* We require that we use just subtractions in at least 50% of all
960 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
962 count
+= histogram
->hvalue
.counters
[i
];
963 if (count
* 2 >= all
)
967 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
970 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
973 fprintf (dump_file
, "Mod subtract transformation on insn ");
974 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
977 /* Compute probability of taking the optimal path(s). */
978 prob1
= (count1
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
979 prob2
= (count2
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
981 /* In practice, "steps" is always 2. This interface reflects this,
982 and will need to be changed if "steps" can change. */
983 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
984 count1
, count2
, all
);
986 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
991 static struct cgraph_node
** pid_map
= NULL
;
993 /* Initialize map of pids (pid -> cgraph node) */
998 struct cgraph_node
*n
;
1000 if (pid_map
!= NULL
)
1004 = (struct cgraph_node
**) xmalloc (sizeof (struct cgraph_node
*) * cgraph_max_pid
);
1006 for (n
= cgraph_nodes
; n
; n
= n
->next
)
1009 pid_map
[n
->pid
] = n
;
1013 /* Return cgraph node for function with pid */
1015 static inline struct cgraph_node
*
1016 find_func_by_pid (int pid
)
1020 return pid_map
[pid
];
1023 /* Do transformation
1025 if (actual_callee_addres == addres_of_most_common_function/method)
1032 tree_ic (tree stmt
, tree call
, struct cgraph_node
* direct_call
,
1033 int prob
, gcov_type count
, gcov_type all
)
1035 tree stmt1
, stmt2
, stmt3
;
1037 tree label_decl1
= create_artificial_label ();
1038 tree label_decl2
= create_artificial_label ();
1039 tree label1
, label2
;
1040 tree bb1end
, bb2end
, bb3end
;
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
;
1048 bb
= bb_for_stmt (stmt
);
1049 bsi
= bsi_for_stmt (stmt
);
1051 tmpv
= create_tmp_var (optype
, "PROF");
1052 tmp1
= create_tmp_var (optype
, "PROF");
1053 stmt1
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmpv
,
1054 unshare_expr (TREE_OPERAND (call
, 0)));
1055 stmt2
= build2 (GIMPLE_MODIFY_STMT
, optype
, tmp1
,
1056 fold_convert (optype
, build_addr (direct_call
->decl
,
1057 current_function_decl
)));
1058 stmt3
= build3 (COND_EXPR
, void_type_node
,
1059 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
1060 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
1061 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
1062 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1063 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
1064 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
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
);
1076 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
1077 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
1081 /* Edge e23 connects bb2 to bb3, etc. */
1082 e12
= split_block (bb
, bb1end
);
1085 e23
= split_block (bb2
, bb2end
);
1087 bb3
->count
= all
- count
;
1088 e34
= split_block (bb3
, bb3end
);
1092 e12
->flags
&= ~EDGE_FALLTHRU
;
1093 e12
->flags
|= EDGE_FALSE_VALUE
;
1094 e12
->probability
= prob
;
1097 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
1098 e13
->probability
= REG_BR_PROB_BASE
- prob
;
1099 e13
->count
= all
- count
;
1103 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
1104 e24
->probability
= REG_BR_PROB_BASE
;
1106 e34
->probability
= REG_BR_PROB_BASE
;
1107 e34
->count
= all
- count
;
1110 region
= lookup_stmt_eh_region (stmt
);
1111 if (region
>=0 && tree_could_throw_p (stmt1
))
1113 add_stmt_to_eh_region (stmt1
, region
);
1114 make_eh_edges (stmt1
);
1117 if (region
>=0 && tree_could_throw_p (stmt
))
1119 tree_purge_dead_eh_edges (bb4
);
1120 make_eh_edges (stmt
);
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
1133 tree_ic_transform (tree stmt
)
1135 histogram_value histogram
;
1136 gcov_type val
, count
, all
;
1138 tree call
, callee
, modify
;
1139 struct cgraph_node
*direct_call
;
1141 call
= get_call_expr_in (stmt
);
1143 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1146 callee
= TREE_OPERAND (call
, 0);
1148 if (TREE_CODE (callee
) == ADDR_EXPR
)
1151 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_INDIR_CALL
);
1155 val
= histogram
->hvalue
.counters
[0];
1156 count
= histogram
->hvalue
.counters
[1];
1157 all
= histogram
->hvalue
.counters
[2];
1158 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1160 if (4 * count
<= 3 * all
)
1163 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1164 direct_call
= find_func_by_pid ((int)val
);
1166 if (direct_call
== NULL
)
1169 modify
= tree_ic (stmt
, call
, direct_call
, prob
, count
, all
);
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
);
1186 /* Return true if the stringop FNDECL with ARGLIST shall be profiled. */
1188 interesting_stringop_to_profile_p (tree fndecl
, tree arglist
)
1190 enum built_in_function fcode
= DECL_FUNCTION_CODE (fndecl
);
1192 if (fcode
!= BUILT_IN_MEMSET
&& fcode
!= BUILT_IN_MEMCPY
1193 && fcode
!= BUILT_IN_BZERO
)
1198 case BUILT_IN_MEMCPY
:
1199 case BUILT_IN_MEMPCPY
:
1200 return validate_arglist (arglist
,
1201 POINTER_TYPE
, POINTER_TYPE
, INTEGER_TYPE
,
1203 case BUILT_IN_MEMSET
:
1204 return validate_arglist (arglist
,
1205 POINTER_TYPE
, INTEGER_TYPE
, INTEGER_TYPE
,
1207 case BUILT_IN_BZERO
:
1208 return validate_arglist (arglist
, POINTER_TYPE
, INTEGER_TYPE
,
1215 /* Convert stringop (..., size)
1218 stringop (...., VALUE);
1220 stringop (...., size);
1221 assuming constant propagation of VALUE will happen later.
1224 tree_stringop_fixed_value (tree stmt
, tree value
, int prob
, gcov_type count
,
1227 tree stmt1
, stmt2
, stmt3
;
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
);
1242 bb
= bb_for_stmt (stmt
);
1243 bsi
= bsi_for_stmt (stmt
);
1245 if (bsi_end_p (bsi
))
1248 for (ei
= ei_start (bb
->succs
); (e34
= ei_safe_edge (ei
)); )
1249 if (!e34
->flags
& EDGE_ABNORMAL
)
1254 e34
= split_block (bb
, stmt
);
1255 bsi
= bsi_for_stmt (stmt
);
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
);
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
);
1282 add_stmt_to_eh_region (stmt1
, region
);
1284 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
1285 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
1288 /* Edge e23 connects bb2 to bb3, etc. */
1289 e12
= split_block (bb
, bb1end
);
1292 e23
= split_block (bb2
, bb2end
);
1294 bb3
->count
= all
- count
;
1296 e12
->flags
&= ~EDGE_FALLTHRU
;
1297 e12
->flags
|= EDGE_FALSE_VALUE
;
1298 e12
->probability
= prob
;
1301 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
1302 e13
->probability
= REG_BR_PROB_BASE
- prob
;
1303 e13
->count
= all
- count
;
1307 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
1308 e24
->probability
= REG_BR_PROB_BASE
;
1311 e34
->probability
= REG_BR_PROB_BASE
;
1312 e34
->count
= all
- count
;
1315 /* Find values inside STMT for that we want to measure histograms for
1316 division/modulo optimization. */
1318 tree_stringops_transform (block_stmt_iterator
*bsi
)
1320 tree stmt
= bsi_stmt (*bsi
);
1321 tree call
= get_call_expr_in (stmt
);
1325 enum built_in_function fcode
;
1326 histogram_value histogram
;
1327 gcov_type count
, all
, val
;
1330 unsigned int dest_align
, src_align
;
1336 fndecl
= get_callee_fndecl (call
);
1339 fcode
= DECL_FUNCTION_CODE (fndecl
);
1340 arglist
= TREE_OPERAND (call
, 1);
1341 if (!interesting_stringop_to_profile_p (fndecl
, arglist
))
1344 if (fcode
== BUILT_IN_BZERO
)
1345 blck_size
= TREE_VALUE (TREE_CHAIN (arglist
));
1347 blck_size
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
1348 if (TREE_CODE (blck_size
) == INTEGER_CST
)
1351 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
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
)))
1364 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
1366 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1367 dest
= TREE_VALUE (arglist
);
1368 dest_align
= get_pointer_alignment (dest
, BIGGEST_ALIGNMENT
);
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
)))
1378 case BUILT_IN_MEMSET
:
1379 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
1380 TREE_VALUE (TREE_CHAIN (arglist
)),
1384 case BUILT_IN_BZERO
:
1385 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
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);
1398 fprintf (dump_file
, "Single value %i stringop transformation on ",
1400 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
1402 tree_stringop_fixed_value (stmt
, tree_val
, prob
, count
, all
);
1407 struct value_prof_hooks
{
1408 /* Find list of values for which we want to measure histograms. */
1409 void (*find_values_to_profile
) (histogram_values
*);
1411 /* Identify and exploit properties of values that are hard to analyze
1412 statically. See value-prof.c for more detail. */
1413 bool (*value_profile_transformations
) (void);
1416 /* Find values inside STMT for that we want to measure histograms for
1417 division/modulo optimization. */
1419 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
1421 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
1422 histogram_value hist
;
1424 if (TREE_CODE (stmt
) == RETURN_EXPR
)
1425 assign
= TREE_OPERAND (stmt
, 0);
1430 || TREE_CODE (assign
) != GIMPLE_MODIFY_STMT
)
1432 lhs
= GIMPLE_STMT_OPERAND (assign
, 0);
1433 type
= TREE_TYPE (lhs
);
1434 if (!INTEGRAL_TYPE_P (type
))
1437 rhs
= GIMPLE_STMT_OPERAND (assign
, 1);
1438 switch (TREE_CODE (rhs
))
1440 case TRUNC_DIV_EXPR
:
1441 case TRUNC_MOD_EXPR
:
1442 divisor
= TREE_OPERAND (rhs
, 1);
1443 op0
= TREE_OPERAND (rhs
, 0);
1445 VEC_reserve (histogram_value
, heap
, *values
, 3);
1447 if (is_gimple_reg (divisor
))
1448 /* Check for the case where the divisor is the same value most
1450 VEC_quick_push (histogram_value
, *values
,
1451 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
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
))
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
,
1465 val
= build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
1466 hist
= gimple_alloc_histogram_value (cfun
, HIST_TYPE_INTERVAL
,
1468 hist
->hdata
.intvl
.int_start
= 0;
1469 hist
->hdata
.intvl
.steps
= 2;
1470 VEC_quick_push (histogram_value
, *values
, hist
);
1479 /* Find calls inside STMT for that we want to measure histograms for
1480 indirect/virtual call optimization. */
1483 tree_indirect_call_to_profile (tree stmt
, histogram_values
*values
)
1488 call
= get_call_expr_in (stmt
);
1490 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1493 callee
= TREE_OPERAND (call
, 0);
1495 if (TREE_CODE (callee
) == ADDR_EXPR
)
1498 VEC_reserve (histogram_value
, heap
, *values
, 3);
1500 VEC_quick_push (histogram_value
, *values
,
1501 gimple_alloc_histogram_value (cfun
, HIST_TYPE_INDIR_CALL
,
1507 /* Find values inside STMT for that we want to measure histograms for
1508 string operations. */
1510 tree_stringops_values_to_profile (tree stmt
, histogram_values
*values
)
1512 tree call
= get_call_expr_in (stmt
);
1516 enum built_in_function fcode
;
1520 fndecl
= get_callee_fndecl (call
);
1523 fcode
= DECL_FUNCTION_CODE (fndecl
);
1524 arglist
= TREE_OPERAND (call
, 1);
1526 if (!interesting_stringop_to_profile_p (fndecl
, arglist
))
1529 if (fcode
== BUILT_IN_BZERO
)
1530 blck_size
= TREE_VALUE (TREE_CHAIN (arglist
));
1532 blck_size
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
1534 if (TREE_CODE (blck_size
) != INTEGER_CST
)
1535 VEC_safe_push (histogram_value
, heap
, *values
,
1536 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
1540 /* Find values inside STMT for that we want to measure histograms and adds
1541 them to list VALUES. */
1544 tree_values_to_profile (tree stmt
, histogram_values
*values
)
1546 if (flag_value_profile_transformations
)
1548 tree_divmod_values_to_profile (stmt
, values
);
1549 tree_stringops_values_to_profile (stmt
, values
);
1550 tree_indirect_call_to_profile (stmt
, values
);
1555 tree_find_values_to_profile (histogram_values
*values
)
1558 block_stmt_iterator bsi
;
1560 histogram_value hist
= NULL
;
1564 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
1565 tree_values_to_profile (bsi_stmt (bsi
), values
);
1567 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
1571 case HIST_TYPE_INTERVAL
:
1572 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
1575 case HIST_TYPE_POW2
:
1576 hist
->n_counters
= 2;
1579 case HIST_TYPE_SINGLE_VALUE
:
1580 hist
->n_counters
= 3;
1583 case HIST_TYPE_CONST_DELTA
:
1584 hist
->n_counters
= 4;
1587 case HIST_TYPE_INDIR_CALL
:
1588 hist
->n_counters
= 3;
1596 fprintf (dump_file
, "Stmt ");
1597 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
1598 dump_histogram_value (dump_file
, hist
);
1603 static struct value_prof_hooks tree_value_prof_hooks
= {
1604 tree_find_values_to_profile
,
1605 tree_value_profile_transformations
1609 tree_register_value_prof_hooks (void)
1611 gcc_assert (current_ir_type () == IR_GIMPLE
);
1612 value_prof_hooks
= &tree_value_prof_hooks
;
1615 /* IR-independent entry points. */
1617 find_values_to_profile (histogram_values
*values
)
1619 (value_prof_hooks
->find_values_to_profile
) (values
);
1623 value_profile_transformations (void)
1625 return (value_prof_hooks
->value_profile_transformations
) ();