1 /* Transformations based on profile information for values.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
26 #include "hard-reg-set.h"
27 #include "basic-block.h"
28 #include "value-prof.h"
31 #include "insn-config.h"
36 #include "tree-flow.h"
37 #include "tree-flow-inline.h"
38 #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 3) Indirect/virtual call specialization. If we can determine most
64 common function callee in indirect/virtual call. We can use this
65 information to improve code effectiveness (especially info for
68 Every such optimization should add its requirements for profiled values to
69 insn_values_to_profile function. This function is called from branch_prob
70 in profile.c and the requested values are instrumented by it in the first
71 compilation with -fprofile-arcs. The optimization may then read the
72 gathered data in the second compilation with -fbranch-probabilities.
74 The measured data is pointed to from the histograms
75 field of the statement annotation of the instrumented insns. It is
76 kept as a linked list of struct histogram_value_t's, which contain the
77 same information as above. */
80 static tree
tree_divmod_fixed_value (tree
, tree
, tree
, tree
,
81 tree
, int, gcov_type
, gcov_type
);
82 static tree
tree_mod_pow2 (tree
, tree
, tree
, tree
, int, gcov_type
, gcov_type
);
83 static tree
tree_mod_subtract (tree
, tree
, tree
, tree
, int, int, int,
84 gcov_type
, gcov_type
, gcov_type
);
85 static bool tree_divmod_fixed_value_transform (tree
);
86 static bool tree_mod_pow2_value_transform (tree
);
87 static bool tree_mod_subtract_transform (tree
);
88 static bool tree_stringops_transform (block_stmt_iterator
*);
89 static bool tree_ic_transform (tree
);
91 /* Allocate histogram value. */
93 static histogram_value
94 gimple_alloc_histogram_value (struct function
*fun ATTRIBUTE_UNUSED
,
95 enum hist_type type
, tree stmt
, tree value
)
97 histogram_value hist
= (histogram_value
) xcalloc (1, sizeof (*hist
));
98 hist
->hvalue
.value
= value
;
99 hist
->hvalue
.stmt
= stmt
;
104 /* Hash value for histogram. */
107 histogram_hash (const void *x
)
109 return htab_hash_pointer (((const_histogram_value
)x
)->hvalue
.stmt
);
112 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
115 histogram_eq (const void *x
, const void *y
)
117 return ((const_histogram_value
) x
)->hvalue
.stmt
== (const_tree
)y
;
120 /* Set histogram for STMT. */
123 set_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
126 if (!hist
&& !VALUE_HISTOGRAMS (fun
))
128 if (!VALUE_HISTOGRAMS (fun
))
129 VALUE_HISTOGRAMS (fun
) = htab_create (1, histogram_hash
,
131 loc
= htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
132 htab_hash_pointer (stmt
),
133 hist
? INSERT
: NO_INSERT
);
137 htab_clear_slot (VALUE_HISTOGRAMS (fun
), loc
);
143 /* Get histogram list for STMT. */
146 gimple_histogram_value (struct function
*fun
, tree stmt
)
148 if (!VALUE_HISTOGRAMS (fun
))
150 return htab_find_with_hash (VALUE_HISTOGRAMS (fun
), stmt
,
151 htab_hash_pointer (stmt
));
154 /* Add histogram for STMT. */
157 gimple_add_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
159 hist
->hvalue
.next
= gimple_histogram_value (fun
, stmt
);
160 set_histogram_value (fun
, stmt
, hist
);
163 /* Remove histogram HIST from STMT's histogram list. */
166 gimple_remove_histogram_value (struct function
*fun
, tree stmt
, histogram_value hist
)
168 histogram_value hist2
= gimple_histogram_value (fun
, stmt
);
171 set_histogram_value (fun
, stmt
, hist
->hvalue
.next
);
175 while (hist2
->hvalue
.next
!= hist
)
176 hist2
= hist2
->hvalue
.next
;
177 hist2
->hvalue
.next
= hist
->hvalue
.next
;
179 free (hist
->hvalue
.counters
);
180 #ifdef ENABLE_CHECKING
181 memset (hist
, 0xab, sizeof (*hist
));
186 /* Lookup histogram of type TYPE in the STMT. */
189 gimple_histogram_value_of_type (struct function
*fun
, tree stmt
, enum hist_type type
)
191 histogram_value hist
;
192 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
193 if (hist
->type
== type
)
198 /* Dump information about HIST to DUMP_FILE. */
201 dump_histogram_value (FILE *dump_file
, histogram_value hist
)
205 case HIST_TYPE_INTERVAL
:
206 fprintf (dump_file
, "Interval counter range %d -- %d",
207 hist
->hdata
.intvl
.int_start
,
208 (hist
->hdata
.intvl
.int_start
209 + hist
->hdata
.intvl
.steps
- 1));
210 if (hist
->hvalue
.counters
)
213 fprintf(dump_file
, " [");
214 for (i
= 0; i
< hist
->hdata
.intvl
.steps
; i
++)
215 fprintf (dump_file
, " %d:"HOST_WIDEST_INT_PRINT_DEC
,
216 hist
->hdata
.intvl
.int_start
+ i
,
217 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
218 fprintf (dump_file
, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC
,
219 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[i
]);
221 fprintf (dump_file
, ".\n");
225 fprintf (dump_file
, "Pow2 counter ");
226 if (hist
->hvalue
.counters
)
228 fprintf (dump_file
, "pow2:"HOST_WIDEST_INT_PRINT_DEC
229 " nonpow2:"HOST_WIDEST_INT_PRINT_DEC
,
230 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
231 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1]);
233 fprintf (dump_file
, ".\n");
236 case HIST_TYPE_SINGLE_VALUE
:
237 fprintf (dump_file
, "Single value ");
238 if (hist
->hvalue
.counters
)
240 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
241 " match:"HOST_WIDEST_INT_PRINT_DEC
242 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
243 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
244 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
245 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
247 fprintf (dump_file
, ".\n");
250 case HIST_TYPE_AVERAGE
:
251 fprintf (dump_file
, "Average value ");
252 if (hist
->hvalue
.counters
)
254 fprintf (dump_file
, "sum:"HOST_WIDEST_INT_PRINT_DEC
255 " times:"HOST_WIDEST_INT_PRINT_DEC
,
256 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
257 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1]);
259 fprintf (dump_file
, ".\n");
263 fprintf (dump_file
, "IOR value ");
264 if (hist
->hvalue
.counters
)
266 fprintf (dump_file
, "ior:"HOST_WIDEST_INT_PRINT_DEC
,
267 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0]);
269 fprintf (dump_file
, ".\n");
272 case HIST_TYPE_CONST_DELTA
:
273 fprintf (dump_file
, "Constant delta ");
274 if (hist
->hvalue
.counters
)
276 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
277 " match:"HOST_WIDEST_INT_PRINT_DEC
278 " wrong:"HOST_WIDEST_INT_PRINT_DEC
,
279 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
280 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
281 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
283 fprintf (dump_file
, ".\n");
285 case HIST_TYPE_INDIR_CALL
:
286 fprintf (dump_file
, "Indirect call ");
287 if (hist
->hvalue
.counters
)
289 fprintf (dump_file
, "value:"HOST_WIDEST_INT_PRINT_DEC
290 " match:"HOST_WIDEST_INT_PRINT_DEC
291 " all:"HOST_WIDEST_INT_PRINT_DEC
,
292 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[0],
293 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[1],
294 (HOST_WIDEST_INT
) hist
->hvalue
.counters
[2]);
296 fprintf (dump_file
, ".\n");
301 /* Dump all histograms attached to STMT to DUMP_FILE. */
304 dump_histograms_for_stmt (struct function
*fun
, FILE *dump_file
, tree stmt
)
306 histogram_value hist
;
307 for (hist
= gimple_histogram_value (fun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
308 dump_histogram_value (dump_file
, hist
);
311 /* Remove all histograms associated with STMT. */
314 gimple_remove_stmt_histograms (struct function
*fun
, tree stmt
)
317 while ((val
= gimple_histogram_value (fun
, stmt
)) != NULL
)
318 gimple_remove_histogram_value (fun
, stmt
, val
);
321 /* Duplicate all histograms associates with OSTMT to STMT. */
324 gimple_duplicate_stmt_histograms (struct function
*fun
, tree stmt
,
325 struct function
*ofun
, tree ostmt
)
328 for (val
= gimple_histogram_value (ofun
, ostmt
); val
!= NULL
; val
= val
->hvalue
.next
)
330 histogram_value
new = gimple_alloc_histogram_value (fun
, val
->type
, NULL
, NULL
);
331 memcpy (new, val
, sizeof (*val
));
332 new->hvalue
.stmt
= stmt
;
333 new->hvalue
.counters
= xmalloc (sizeof (*new->hvalue
.counters
) * new->n_counters
);
334 memcpy (new->hvalue
.counters
, val
->hvalue
.counters
, sizeof (*new->hvalue
.counters
) * new->n_counters
);
335 gimple_add_histogram_value (fun
, stmt
, new);
339 static bool error_found
= false;
341 /* Helper function for verify_histograms. For each histogram reachable via htab
342 walk verify that it was reached via statement walk. */
345 visit_hist (void **slot
, void *data
)
347 struct pointer_set_t
*visited
= (struct pointer_set_t
*) data
;
348 histogram_value hist
= *(histogram_value
*) slot
;
349 if (!pointer_set_contains (visited
, hist
))
351 error ("Dead histogram");
352 dump_histogram_value (stderr
, hist
);
353 debug_generic_stmt (hist
->hvalue
.stmt
);
359 /* Verify sanity of the histograms. */
362 verify_histograms (void)
365 block_stmt_iterator bsi
;
366 histogram_value hist
;
367 struct pointer_set_t
*visited_hists
;
370 visited_hists
= pointer_set_create ();
372 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
374 tree stmt
= bsi_stmt (bsi
);
376 for (hist
= gimple_histogram_value (cfun
, stmt
); hist
; hist
= hist
->hvalue
.next
)
378 if (hist
->hvalue
.stmt
!= stmt
)
380 error ("Histogram value statement does not correspond to statement"
381 " it is associated with");
382 debug_generic_stmt (stmt
);
383 dump_histogram_value (stderr
, hist
);
386 pointer_set_insert (visited_hists
, hist
);
389 if (VALUE_HISTOGRAMS (cfun
))
390 htab_traverse (VALUE_HISTOGRAMS (cfun
), visit_hist
, visited_hists
);
391 pointer_set_destroy (visited_hists
);
393 internal_error ("verify_histograms failed");
396 /* Helper function for verify_histograms. For each histogram reachable via htab
397 walk verify that it was reached via statement walk. */
400 free_hist (void **slot
, void *data ATTRIBUTE_UNUSED
)
402 histogram_value hist
= *(histogram_value
*) slot
;
403 free (hist
->hvalue
.counters
);
404 #ifdef ENABLE_CHECKING
405 memset (hist
, 0xab, sizeof (*hist
));
412 free_histograms (void)
414 if (VALUE_HISTOGRAMS (cfun
))
416 htab_traverse (VALUE_HISTOGRAMS (cfun
), free_hist
, NULL
);
417 htab_delete (VALUE_HISTOGRAMS (cfun
));
418 VALUE_HISTOGRAMS (cfun
) = NULL
;
422 /* The overall number of invocations of the counter should match execution count
423 of basic block. Report it as error rather than internal error as it might
424 mean that user has misused the profile somehow. */
426 check_counter (tree stmt
, const char * name
, gcov_type all
, gcov_type bb_count
)
431 locus
= (stmt
!= NULL
&& EXPR_HAS_LOCATION (stmt
)
433 : &DECL_SOURCE_LOCATION (current_function_decl
));
434 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
435 locus
, name
, (int)all
, (int)bb_count
);
441 /* Tree based transformations. */
443 tree_value_profile_transformations (void)
446 block_stmt_iterator bsi
;
447 bool changed
= false;
451 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
453 tree stmt
= bsi_stmt (bsi
);
454 histogram_value th
= gimple_histogram_value (cfun
, stmt
);
460 fprintf (dump_file
, "Trying transformations on stmt ");
461 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
462 dump_histograms_for_stmt (cfun
, dump_file
, stmt
);
465 /* Transformations: */
466 /* The order of things in this conditional controls which
467 transformation is used when more than one is applicable. */
468 /* It is expected that any code added by the transformations
469 will be added before the current statement, and that the
470 current statement remain valid (although possibly
471 modified) upon return. */
472 if (flag_value_profile_transformations
473 && (tree_mod_subtract_transform (stmt
)
474 || tree_divmod_fixed_value_transform (stmt
)
475 || tree_mod_pow2_value_transform (stmt
)
476 || tree_stringops_transform (&bsi
)
477 || tree_ic_transform (stmt
)))
479 stmt
= bsi_stmt (bsi
);
481 /* Original statement may no longer be in the same block. */
482 if (bb
!= bb_for_stmt (stmt
))
484 bb
= bb_for_stmt (stmt
);
485 bsi
= bsi_for_stmt (stmt
);
499 /* Generate code for transformation 1 (with OPERATION, operands OP1
500 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
501 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
502 within roundoff error). This generates the result into a temp and returns
503 the temp; it does not replace or alter the original STMT. */
505 tree_divmod_fixed_value (tree stmt
, tree operation
,
506 tree op1
, tree op2
, tree value
, int prob
, gcov_type count
,
509 tree stmt1
, stmt2
, stmt3
;
510 tree tmp1
, tmp2
, tmpv
;
511 tree label_decl1
= create_artificial_label ();
512 tree label_decl2
= create_artificial_label ();
514 tree bb1end
, bb2end
, bb3end
;
515 basic_block bb
, bb2
, bb3
, bb4
;
516 tree optype
= TREE_TYPE (operation
);
517 edge e12
, e13
, e23
, e24
, e34
;
518 block_stmt_iterator bsi
;
520 bb
= bb_for_stmt (stmt
);
521 bsi
= bsi_for_stmt (stmt
);
523 tmpv
= create_tmp_var (optype
, "PROF");
524 tmp1
= create_tmp_var (optype
, "PROF");
525 stmt1
= build_gimple_modify_stmt (tmpv
, fold_convert (optype
, value
));
526 stmt2
= build_gimple_modify_stmt (tmp1
, op2
);
527 stmt3
= build3 (COND_EXPR
, void_type_node
,
528 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
529 NULL_TREE
, NULL_TREE
);
530 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
531 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
532 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
535 tmp2
= create_tmp_var (optype
, "PROF");
536 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
537 stmt1
= build_gimple_modify_stmt (tmp2
,
538 build2 (TREE_CODE (operation
), optype
,
540 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
541 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
544 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
545 stmt1
= build_gimple_modify_stmt (tmp2
,
546 build2 (TREE_CODE (operation
), optype
,
548 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
549 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
553 /* Edge e23 connects bb2 to bb3, etc. */
554 e12
= split_block (bb
, bb1end
);
557 e23
= split_block (bb2
, bb2end
);
559 bb3
->count
= all
- count
;
560 e34
= split_block (bb3
, bb3end
);
564 e12
->flags
&= ~EDGE_FALLTHRU
;
565 e12
->flags
|= EDGE_FALSE_VALUE
;
566 e12
->probability
= prob
;
569 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
570 e13
->probability
= REG_BR_PROB_BASE
- prob
;
571 e13
->count
= all
- count
;
575 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
576 e24
->probability
= REG_BR_PROB_BASE
;
579 e34
->probability
= REG_BR_PROB_BASE
;
580 e34
->count
= all
- count
;
585 /* Do transform 1) on INSN if applicable. */
587 tree_divmod_fixed_value_transform (tree stmt
)
589 histogram_value histogram
;
591 gcov_type val
, count
, all
;
592 tree modify
, op
, op1
, op2
, result
, value
, tree_val
;
596 if (TREE_CODE (stmt
) == RETURN_EXPR
597 && TREE_OPERAND (stmt
, 0)
598 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
599 modify
= TREE_OPERAND (stmt
, 0);
600 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
602 op
= GIMPLE_STMT_OPERAND (modify
, 1);
603 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
605 code
= TREE_CODE (op
);
607 if (code
!= TRUNC_DIV_EXPR
&& code
!= TRUNC_MOD_EXPR
)
610 op1
= TREE_OPERAND (op
, 0);
611 op2
= TREE_OPERAND (op
, 1);
613 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
617 value
= histogram
->hvalue
.value
;
618 val
= histogram
->hvalue
.counters
[0];
619 count
= histogram
->hvalue
.counters
[1];
620 all
= histogram
->hvalue
.counters
[2];
621 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
623 /* We require that count is at least half of all; this means
624 that for the transformation to fire the value must be constant
625 at least 50% of time (and 75% gives the guarantee of usage). */
626 if (simple_cst_equal (op2
, value
) != 1 || 2 * count
< all
627 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
630 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
633 /* Compute probability of taking the optimal path. */
634 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
636 tree_val
= build_int_cst_wide (get_gcov_type (),
637 (unsigned HOST_WIDE_INT
) val
,
638 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
639 result
= tree_divmod_fixed_value (stmt
, op
, op1
, op2
, tree_val
, prob
, count
, all
);
643 fprintf (dump_file
, "Div/mod by constant ");
644 print_generic_expr (dump_file
, value
, TDF_SLIM
);
645 fprintf (dump_file
, "=");
646 print_generic_expr (dump_file
, tree_val
, TDF_SLIM
);
647 fprintf (dump_file
, " transformation on insn ");
648 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
651 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
656 /* Generate code for transformation 2 (with OPERATION, operands OP1
657 and OP2, parent modify-expr STMT and probability of taking the optimal
658 path PROB, which is equivalent to COUNT/ALL within roundoff error).
659 This generates the result into a temp and returns
660 the temp; it does not replace or alter the original STMT. */
662 tree_mod_pow2 (tree stmt
, tree operation
, tree op1
, tree op2
, int prob
,
663 gcov_type count
, gcov_type all
)
665 tree stmt1
, stmt2
, stmt3
, stmt4
;
667 tree label_decl1
= create_artificial_label ();
668 tree label_decl2
= create_artificial_label ();
670 tree bb1end
, bb2end
, bb3end
;
671 basic_block bb
, bb2
, bb3
, bb4
;
672 tree optype
= TREE_TYPE (operation
);
673 edge e12
, e13
, e23
, e24
, e34
;
674 block_stmt_iterator bsi
;
675 tree result
= create_tmp_var (optype
, "PROF");
677 bb
= bb_for_stmt (stmt
);
678 bsi
= bsi_for_stmt (stmt
);
680 tmp2
= create_tmp_var (optype
, "PROF");
681 tmp3
= create_tmp_var (optype
, "PROF");
682 stmt2
= build_gimple_modify_stmt (tmp2
,
683 build2 (PLUS_EXPR
, optype
, op2
,
684 build_int_cst (optype
, -1)));
685 stmt3
= build_gimple_modify_stmt (tmp3
,
686 build2 (BIT_AND_EXPR
, optype
, tmp2
, op2
));
687 stmt4
= build3 (COND_EXPR
, void_type_node
,
688 build2 (NE_EXPR
, boolean_type_node
,
689 tmp3
, build_int_cst (optype
, 0)),
690 NULL_TREE
, NULL_TREE
);
691 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
692 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
693 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
696 /* tmp2 == op2-1 inherited from previous block */
697 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
698 stmt1
= build_gimple_modify_stmt (result
,
699 build2 (BIT_AND_EXPR
, optype
, op1
, tmp2
));
700 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
701 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
704 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
705 stmt1
= build_gimple_modify_stmt (result
,
706 build2 (TREE_CODE (operation
), optype
,
708 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
709 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
713 /* Edge e23 connects bb2 to bb3, etc. */
714 e12
= split_block (bb
, bb1end
);
717 e23
= split_block (bb2
, bb2end
);
719 bb3
->count
= all
- count
;
720 e34
= split_block (bb3
, bb3end
);
724 e12
->flags
&= ~EDGE_FALLTHRU
;
725 e12
->flags
|= EDGE_FALSE_VALUE
;
726 e12
->probability
= prob
;
729 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
730 e13
->probability
= REG_BR_PROB_BASE
- prob
;
731 e13
->count
= all
- count
;
735 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
736 e24
->probability
= REG_BR_PROB_BASE
;
739 e34
->probability
= REG_BR_PROB_BASE
;
740 e34
->count
= all
- count
;
745 /* Do transform 2) on INSN if applicable. */
747 tree_mod_pow2_value_transform (tree stmt
)
749 histogram_value histogram
;
751 gcov_type count
, wrong_values
, all
;
752 tree modify
, op
, op1
, op2
, result
, value
;
756 if (TREE_CODE (stmt
) == RETURN_EXPR
757 && TREE_OPERAND (stmt
, 0)
758 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
759 modify
= TREE_OPERAND (stmt
, 0);
760 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
762 op
= GIMPLE_STMT_OPERAND (modify
, 1);
763 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
765 code
= TREE_CODE (op
);
767 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
770 op1
= TREE_OPERAND (op
, 0);
771 op2
= TREE_OPERAND (op
, 1);
773 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_POW2
);
777 value
= histogram
->hvalue
.value
;
778 wrong_values
= histogram
->hvalue
.counters
[0];
779 count
= histogram
->hvalue
.counters
[1];
781 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
783 /* We require that we hit a power of 2 at least half of all evaluations. */
784 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
785 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
790 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
791 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
794 /* Compute probability of taking the optimal path. */
795 all
= count
+ wrong_values
;
797 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
800 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
802 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
804 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
809 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
810 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
811 support. Currently only NCOUNTS==0 or 1 is supported and this is
812 built into this interface. The probabilities of taking the optimal
813 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
814 COUNT2/ALL respectively within roundoff error). This generates the
815 result into a temp and returns the temp; it does not replace or alter
816 the original STMT. */
817 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
820 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
821 int prob1
, int prob2
, int ncounts
,
822 gcov_type count1
, gcov_type count2
, gcov_type all
)
824 tree stmt1
, stmt2
, stmt3
;
826 tree label_decl1
= create_artificial_label ();
827 tree label_decl2
= create_artificial_label ();
828 tree label_decl3
= create_artificial_label ();
829 tree label1
, label2
, label3
;
830 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
831 basic_block bb
, bb2
, bb3
, bb4
;
832 tree optype
= TREE_TYPE (operation
);
833 edge e12
, e23
= 0, e24
, e34
, e14
;
834 block_stmt_iterator bsi
;
835 tree result
= create_tmp_var (optype
, "PROF");
837 bb
= bb_for_stmt (stmt
);
838 bsi
= bsi_for_stmt (stmt
);
840 tmp1
= create_tmp_var (optype
, "PROF");
841 stmt1
= build_gimple_modify_stmt (result
, op1
);
842 stmt2
= build_gimple_modify_stmt (tmp1
, op2
);
843 stmt3
= build3 (COND_EXPR
, void_type_node
,
844 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
845 NULL_TREE
, NULL_TREE
);
846 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
847 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
848 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
851 if (ncounts
) /* Assumed to be 0 or 1 */
853 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
854 stmt1
= build_gimple_modify_stmt (result
,
855 build2 (MINUS_EXPR
, optype
,
857 stmt2
= build3 (COND_EXPR
, void_type_node
,
858 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
859 NULL_TREE
, NULL_TREE
);
860 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
861 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
862 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
867 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
868 stmt1
= build_gimple_modify_stmt (result
,
869 build2 (TREE_CODE (operation
), optype
,
871 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
872 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
875 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
876 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
879 /* Edge e23 connects bb2 to bb3, etc. */
880 /* However block 3 is optional; if it is not there, references
881 to 3 really refer to block 2. */
882 e12
= split_block (bb
, bb1end
);
884 bb2
->count
= all
- count1
;
886 if (ncounts
) /* Assumed to be 0 or 1. */
888 e23
= split_block (bb2
, bb2end
);
890 bb3
->count
= all
- count1
- count2
;
893 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
897 e12
->flags
&= ~EDGE_FALLTHRU
;
898 e12
->flags
|= EDGE_FALSE_VALUE
;
899 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
900 e12
->count
= all
- count1
;
902 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
903 e14
->probability
= prob1
;
906 if (ncounts
) /* Assumed to be 0 or 1. */
908 e23
->flags
&= ~EDGE_FALLTHRU
;
909 e23
->flags
|= EDGE_FALSE_VALUE
;
910 e23
->count
= all
- count1
- count2
;
911 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
913 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
914 e24
->probability
= prob2
;
918 e34
->probability
= REG_BR_PROB_BASE
;
919 e34
->count
= all
- count1
- count2
;
924 /* Do transforms 3) and 4) on INSN if applicable. */
926 tree_mod_subtract_transform (tree stmt
)
928 histogram_value histogram
;
930 gcov_type count
, wrong_values
, all
;
931 tree modify
, op
, op1
, op2
, result
, value
;
933 unsigned int i
, steps
;
934 gcov_type count1
, count2
;
937 if (TREE_CODE (stmt
) == RETURN_EXPR
938 && TREE_OPERAND (stmt
, 0)
939 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
)
940 modify
= TREE_OPERAND (stmt
, 0);
941 if (TREE_CODE (modify
) != GIMPLE_MODIFY_STMT
)
943 op
= GIMPLE_STMT_OPERAND (modify
, 1);
944 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
946 code
= TREE_CODE (op
);
948 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
951 op1
= TREE_OPERAND (op
, 0);
952 op2
= TREE_OPERAND (op
, 1);
954 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_INTERVAL
);
958 value
= histogram
->hvalue
.value
;
961 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
962 all
+= histogram
->hvalue
.counters
[i
];
964 wrong_values
+= histogram
->hvalue
.counters
[i
];
965 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
966 steps
= histogram
->hdata
.intvl
.steps
;
968 count1
= histogram
->hvalue
.counters
[0];
969 count2
= histogram
->hvalue
.counters
[1];
971 /* Compute probability of taking the optimal path. */
972 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
974 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
978 /* We require that we use just subtractions in at least 50% of all
981 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
983 count
+= histogram
->hvalue
.counters
[i
];
984 if (count
* 2 >= all
)
988 || !maybe_hot_bb_p (bb_for_stmt (stmt
)))
991 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
994 fprintf (dump_file
, "Mod subtract transformation on insn ");
995 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
998 /* Compute probability of taking the optimal path(s). */
999 prob1
= (count1
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1000 prob2
= (count2
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1002 /* In practice, "steps" is always 2. This interface reflects this,
1003 and will need to be changed if "steps" can change. */
1004 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
1005 count1
, count2
, all
);
1007 GIMPLE_STMT_OPERAND (modify
, 1) = result
;
1012 static struct cgraph_node
** pid_map
= NULL
;
1014 /* Initialize map of pids (pid -> cgraph node) */
1019 struct cgraph_node
*n
;
1021 if (pid_map
!= NULL
)
1025 = (struct cgraph_node
**) xmalloc (sizeof (struct cgraph_node
*) * cgraph_max_pid
);
1027 for (n
= cgraph_nodes
; n
; n
= n
->next
)
1030 pid_map
[n
->pid
] = n
;
1034 /* Return cgraph node for function with pid */
1036 static inline struct cgraph_node
*
1037 find_func_by_pid (int pid
)
1041 return pid_map
[pid
];
1044 /* Do transformation
1046 if (actual_callee_addres == addres_of_most_common_function/method)
1053 tree_ic (tree stmt
, tree call
, struct cgraph_node
* direct_call
,
1054 int prob
, gcov_type count
, gcov_type all
)
1056 tree stmt1
, stmt2
, stmt3
;
1057 tree tmp1
, tmpv
, tmp
;
1058 tree label_decl1
= create_artificial_label ();
1059 tree label_decl2
= create_artificial_label ();
1060 tree label1
, label2
;
1061 tree bb1end
, bb2end
, bb3end
;
1063 basic_block bb
, bb2
, bb3
, bb4
;
1064 tree optype
= build_pointer_type (void_type_node
);
1065 edge e12
, e13
, e23
, e24
, e34
;
1066 block_stmt_iterator bsi
;
1069 bb
= bb_for_stmt (stmt
);
1070 bsi
= bsi_for_stmt (stmt
);
1072 tmpv
= create_tmp_var (optype
, "PROF");
1073 tmp1
= create_tmp_var (optype
, "PROF");
1074 stmt1
= build_gimple_modify_stmt (tmpv
,
1075 unshare_expr (CALL_EXPR_FN (call
)));
1076 tmp
= fold_convert (optype
, build_addr (direct_call
->decl
,
1077 current_function_decl
));
1078 stmt2
= build_gimple_modify_stmt (tmp1
, tmp
);
1079 stmt3
= build3 (COND_EXPR
, void_type_node
,
1080 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
1081 NULL_TREE
, NULL_TREE
);
1082 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1083 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
1084 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
1087 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
1088 stmt1
= unshare_expr (stmt
);
1089 new_call
= get_call_expr_in (stmt1
);
1090 CALL_EXPR_FN (new_call
) = build_addr (direct_call
->decl
,
1091 current_function_decl
);
1092 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
1093 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1096 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
1097 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
1101 /* Edge e23 connects bb2 to bb3, etc. */
1102 e12
= split_block (bb
, bb1end
);
1105 e23
= split_block (bb2
, bb2end
);
1107 bb3
->count
= all
- count
;
1108 e34
= split_block (bb3
, bb3end
);
1112 e12
->flags
&= ~EDGE_FALLTHRU
;
1113 e12
->flags
|= EDGE_FALSE_VALUE
;
1114 e12
->probability
= prob
;
1117 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
1118 e13
->probability
= REG_BR_PROB_BASE
- prob
;
1119 e13
->count
= all
- count
;
1123 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
1124 e24
->probability
= REG_BR_PROB_BASE
;
1126 e34
->probability
= REG_BR_PROB_BASE
;
1127 e34
->count
= all
- count
;
1130 region
= lookup_stmt_eh_region (stmt
);
1131 if (region
>=0 && tree_could_throw_p (stmt1
))
1133 add_stmt_to_eh_region (stmt1
, region
);
1134 make_eh_edges (stmt1
);
1137 if (region
>=0 && tree_could_throw_p (stmt
))
1139 tree_purge_dead_eh_edges (bb4
);
1140 make_eh_edges (stmt
);
1147 For every checked indirect/virtual call determine if most common pid of
1148 function/class method has probability more than 50%. If yes modify code of
1153 tree_ic_transform (tree stmt
)
1155 histogram_value histogram
;
1156 gcov_type val
, count
, all
;
1158 tree call
, callee
, modify
;
1159 struct cgraph_node
*direct_call
;
1161 call
= get_call_expr_in (stmt
);
1163 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1166 callee
= CALL_EXPR_FN (call
);
1168 if (TREE_CODE (callee
) == ADDR_EXPR
)
1171 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_INDIR_CALL
);
1175 val
= histogram
->hvalue
.counters
[0];
1176 count
= histogram
->hvalue
.counters
[1];
1177 all
= histogram
->hvalue
.counters
[2];
1178 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1180 if (4 * count
<= 3 * all
)
1183 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1184 direct_call
= find_func_by_pid ((int)val
);
1186 if (direct_call
== NULL
)
1189 modify
= tree_ic (stmt
, call
, direct_call
, prob
, count
, all
);
1193 fprintf (dump_file
, "Indirect call -> direct call ");
1194 print_generic_expr (dump_file
, call
, TDF_SLIM
);
1195 fprintf (dump_file
, "=> ");
1196 print_generic_expr (dump_file
, direct_call
->decl
, TDF_SLIM
);
1197 fprintf (dump_file
, " transformation on insn ");
1198 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
1199 fprintf (dump_file
, " to ");
1200 print_generic_stmt (dump_file
, modify
, TDF_SLIM
);
1206 /* Return true if the stringop CALL with FNDECL shall be profiled. */
1208 interesting_stringop_to_profile_p (tree fndecl
, tree call
)
1210 enum built_in_function fcode
= DECL_FUNCTION_CODE (fndecl
);
1212 if (fcode
!= BUILT_IN_MEMSET
&& fcode
!= BUILT_IN_MEMCPY
1213 && fcode
!= BUILT_IN_BZERO
)
1218 case BUILT_IN_MEMCPY
:
1219 case BUILT_IN_MEMPCPY
:
1220 return validate_arglist (call
,
1221 POINTER_TYPE
, POINTER_TYPE
, INTEGER_TYPE
,
1223 case BUILT_IN_MEMSET
:
1224 return validate_arglist (call
,
1225 POINTER_TYPE
, INTEGER_TYPE
, INTEGER_TYPE
,
1227 case BUILT_IN_BZERO
:
1228 return validate_arglist (call
, POINTER_TYPE
, INTEGER_TYPE
,
1235 /* Convert stringop (..., size)
1238 stringop (...., VALUE);
1240 stringop (...., size);
1241 assuming constant propagation of VALUE will happen later.
1244 tree_stringop_fixed_value (tree stmt
, tree value
, int prob
, gcov_type count
,
1247 tree stmt1
, stmt2
, stmt3
;
1249 tree label_decl1
= create_artificial_label ();
1250 tree label_decl2
= create_artificial_label ();
1251 tree label1
, label2
;
1252 tree bb1end
, bb2end
;
1253 basic_block bb
, bb2
, bb3
, bb4
;
1254 edge e12
, e13
, e23
, e24
, e34
;
1255 block_stmt_iterator bsi
;
1256 tree call
= get_call_expr_in (stmt
);
1257 tree blck_size
= CALL_EXPR_ARG (call
, 2);
1258 tree optype
= TREE_TYPE (blck_size
);
1261 bb
= bb_for_stmt (stmt
);
1262 bsi
= bsi_for_stmt (stmt
);
1264 if (bsi_end_p (bsi
))
1267 for (ei
= ei_start (bb
->succs
); (e34
= ei_safe_edge (ei
)); )
1268 if (!e34
->flags
& EDGE_ABNORMAL
)
1273 e34
= split_block (bb
, stmt
);
1274 bsi
= bsi_for_stmt (stmt
);
1278 tmpv
= create_tmp_var (optype
, "PROF");
1279 tmp1
= create_tmp_var (optype
, "PROF");
1280 stmt1
= build_gimple_modify_stmt (tmpv
, fold_convert (optype
, value
));
1281 stmt2
= build_gimple_modify_stmt (tmp1
, blck_size
);
1282 stmt3
= build3 (COND_EXPR
, void_type_node
,
1283 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
1284 NULL_TREE
, NULL_TREE
);
1285 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1286 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
1287 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
1290 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
1291 stmt1
= unshare_expr (stmt
);
1292 call
= get_call_expr_in (stmt1
);
1293 CALL_EXPR_ARG (call
, 2) = value
;
1294 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
1295 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
1296 region
= lookup_stmt_eh_region (stmt
);
1298 add_stmt_to_eh_region (stmt1
, region
);
1300 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
1301 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
1304 /* Edge e23 connects bb2 to bb3, etc. */
1305 e12
= split_block (bb
, bb1end
);
1308 e23
= split_block (bb2
, bb2end
);
1310 bb3
->count
= all
- count
;
1312 e12
->flags
&= ~EDGE_FALLTHRU
;
1313 e12
->flags
|= EDGE_FALSE_VALUE
;
1314 e12
->probability
= prob
;
1317 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
1318 e13
->probability
= REG_BR_PROB_BASE
- prob
;
1319 e13
->count
= all
- count
;
1323 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
1324 e24
->probability
= REG_BR_PROB_BASE
;
1327 e34
->probability
= REG_BR_PROB_BASE
;
1328 e34
->count
= all
- count
;
1331 /* Find values inside STMT for that we want to measure histograms for
1332 division/modulo optimization. */
1334 tree_stringops_transform (block_stmt_iterator
*bsi
)
1336 tree stmt
= bsi_stmt (*bsi
);
1337 tree call
= get_call_expr_in (stmt
);
1340 enum built_in_function fcode
;
1341 histogram_value histogram
;
1342 gcov_type count
, all
, val
;
1345 unsigned int dest_align
, src_align
;
1351 fndecl
= get_callee_fndecl (call
);
1354 fcode
= DECL_FUNCTION_CODE (fndecl
);
1355 if (!interesting_stringop_to_profile_p (fndecl
, call
))
1358 if (fcode
== BUILT_IN_BZERO
)
1359 blck_size
= CALL_EXPR_ARG (call
, 1);
1361 blck_size
= CALL_EXPR_ARG (call
, 2);
1362 if (TREE_CODE (blck_size
) == INTEGER_CST
)
1365 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_SINGLE_VALUE
);
1368 value
= histogram
->hvalue
.value
;
1369 val
= histogram
->hvalue
.counters
[0];
1370 count
= histogram
->hvalue
.counters
[1];
1371 all
= histogram
->hvalue
.counters
[2];
1372 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1373 /* We require that count is at least half of all; this means
1374 that for the transformation to fire the value must be constant
1375 at least 80% of time. */
1376 if ((6 * count
/ 5) < all
|| !maybe_hot_bb_p (bb_for_stmt (stmt
)))
1378 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
1380 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
1381 dest
= CALL_EXPR_ARG (call
, 0);
1382 dest_align
= get_pointer_alignment (dest
, BIGGEST_ALIGNMENT
);
1385 case BUILT_IN_MEMCPY
:
1386 case BUILT_IN_MEMPCPY
:
1387 src
= CALL_EXPR_ARG (call
, 1);
1388 src_align
= get_pointer_alignment (src
, BIGGEST_ALIGNMENT
);
1389 if (!can_move_by_pieces (val
, MIN (dest_align
, src_align
)))
1392 case BUILT_IN_MEMSET
:
1393 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
1394 CALL_EXPR_ARG (call
, 1),
1398 case BUILT_IN_BZERO
:
1399 if (!can_store_by_pieces (val
, builtin_memset_read_str
,
1407 tree_val
= build_int_cst_wide (get_gcov_type (),
1408 (unsigned HOST_WIDE_INT
) val
,
1409 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
1412 fprintf (dump_file
, "Single value %i stringop transformation on ",
1414 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
1416 tree_stringop_fixed_value (stmt
, tree_val
, prob
, count
, all
);
1422 stringop_block_profile (tree stmt
, unsigned int *expected_align
,
1423 HOST_WIDE_INT
*expected_size
)
1425 histogram_value histogram
;
1426 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_AVERAGE
);
1428 *expected_size
= -1;
1429 else if (!histogram
->hvalue
.counters
[1])
1431 *expected_size
= -1;
1432 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1437 size
= ((histogram
->hvalue
.counters
[0]
1438 + histogram
->hvalue
.counters
[1] / 2)
1439 / histogram
->hvalue
.counters
[1]);
1440 /* Even if we can hold bigger value in SIZE, INT_MAX
1441 is safe "infinity" for code generation strategies. */
1444 *expected_size
= size
;
1445 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1447 histogram
= gimple_histogram_value_of_type (cfun
, stmt
, HIST_TYPE_IOR
);
1449 *expected_align
= 0;
1450 else if (!histogram
->hvalue
.counters
[0])
1452 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1453 *expected_align
= 0;
1460 count
= histogram
->hvalue
.counters
[0];
1462 while (!(count
& alignment
)
1463 && (alignment
* 2 * BITS_PER_UNIT
))
1465 *expected_align
= alignment
* BITS_PER_UNIT
;
1466 gimple_remove_histogram_value (cfun
, stmt
, histogram
);
1470 struct value_prof_hooks
{
1471 /* Find list of values for which we want to measure histograms. */
1472 void (*find_values_to_profile
) (histogram_values
*);
1474 /* Identify and exploit properties of values that are hard to analyze
1475 statically. See value-prof.c for more detail. */
1476 bool (*value_profile_transformations
) (void);
1479 /* Find values inside STMT for that we want to measure histograms for
1480 division/modulo optimization. */
1482 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
1484 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
1485 histogram_value hist
;
1487 if (TREE_CODE (stmt
) == RETURN_EXPR
)
1488 assign
= TREE_OPERAND (stmt
, 0);
1493 || TREE_CODE (assign
) != GIMPLE_MODIFY_STMT
)
1495 lhs
= GIMPLE_STMT_OPERAND (assign
, 0);
1496 type
= TREE_TYPE (lhs
);
1497 if (!INTEGRAL_TYPE_P (type
))
1500 rhs
= GIMPLE_STMT_OPERAND (assign
, 1);
1501 switch (TREE_CODE (rhs
))
1503 case TRUNC_DIV_EXPR
:
1504 case TRUNC_MOD_EXPR
:
1505 divisor
= TREE_OPERAND (rhs
, 1);
1506 op0
= TREE_OPERAND (rhs
, 0);
1508 VEC_reserve (histogram_value
, heap
, *values
, 3);
1510 if (is_gimple_reg (divisor
))
1511 /* Check for the case where the divisor is the same value most
1513 VEC_quick_push (histogram_value
, *values
,
1514 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
1517 /* For mod, check whether it is not often a noop (or replaceable by
1518 a few subtractions). */
1519 if (TREE_CODE (rhs
) == TRUNC_MOD_EXPR
1520 && TYPE_UNSIGNED (type
))
1523 /* Check for a special case where the divisor is power of 2. */
1524 VEC_quick_push (histogram_value
, *values
,
1525 gimple_alloc_histogram_value (cfun
, HIST_TYPE_POW2
,
1528 val
= build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
1529 hist
= gimple_alloc_histogram_value (cfun
, HIST_TYPE_INTERVAL
,
1531 hist
->hdata
.intvl
.int_start
= 0;
1532 hist
->hdata
.intvl
.steps
= 2;
1533 VEC_quick_push (histogram_value
, *values
, hist
);
1542 /* Find calls inside STMT for that we want to measure histograms for
1543 indirect/virtual call optimization. */
1546 tree_indirect_call_to_profile (tree stmt
, histogram_values
*values
)
1551 call
= get_call_expr_in (stmt
);
1553 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1556 callee
= CALL_EXPR_FN (call
);
1558 if (TREE_CODE (callee
) == ADDR_EXPR
)
1561 VEC_reserve (histogram_value
, heap
, *values
, 3);
1563 VEC_quick_push (histogram_value
, *values
,
1564 gimple_alloc_histogram_value (cfun
, HIST_TYPE_INDIR_CALL
,
1570 /* Find values inside STMT for that we want to measure histograms for
1571 string operations. */
1573 tree_stringops_values_to_profile (tree stmt
, histogram_values
*values
)
1575 tree call
= get_call_expr_in (stmt
);
1579 enum built_in_function fcode
;
1583 fndecl
= get_callee_fndecl (call
);
1586 fcode
= DECL_FUNCTION_CODE (fndecl
);
1588 if (!interesting_stringop_to_profile_p (fndecl
, call
))
1591 dest
= CALL_EXPR_ARG (call
, 0);
1592 if (fcode
== BUILT_IN_BZERO
)
1593 blck_size
= CALL_EXPR_ARG (call
, 1);
1595 blck_size
= CALL_EXPR_ARG (call
, 2);
1597 if (TREE_CODE (blck_size
) != INTEGER_CST
)
1599 VEC_safe_push (histogram_value
, heap
, *values
,
1600 gimple_alloc_histogram_value (cfun
, HIST_TYPE_SINGLE_VALUE
,
1602 VEC_safe_push (histogram_value
, heap
, *values
,
1603 gimple_alloc_histogram_value (cfun
, HIST_TYPE_AVERAGE
,
1606 if (TREE_CODE (blck_size
) != INTEGER_CST
)
1607 VEC_safe_push (histogram_value
, heap
, *values
,
1608 gimple_alloc_histogram_value (cfun
, HIST_TYPE_IOR
,
1612 /* Find values inside STMT for that we want to measure histograms and adds
1613 them to list VALUES. */
1616 tree_values_to_profile (tree stmt
, histogram_values
*values
)
1618 if (flag_value_profile_transformations
)
1620 tree_divmod_values_to_profile (stmt
, values
);
1621 tree_stringops_values_to_profile (stmt
, values
);
1622 tree_indirect_call_to_profile (stmt
, values
);
1627 tree_find_values_to_profile (histogram_values
*values
)
1630 block_stmt_iterator bsi
;
1632 histogram_value hist
= NULL
;
1636 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
1637 tree_values_to_profile (bsi_stmt (bsi
), values
);
1639 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
1643 case HIST_TYPE_INTERVAL
:
1644 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
1647 case HIST_TYPE_POW2
:
1648 hist
->n_counters
= 2;
1651 case HIST_TYPE_SINGLE_VALUE
:
1652 hist
->n_counters
= 3;
1655 case HIST_TYPE_CONST_DELTA
:
1656 hist
->n_counters
= 4;
1659 case HIST_TYPE_INDIR_CALL
:
1660 hist
->n_counters
= 3;
1663 case HIST_TYPE_AVERAGE
:
1664 hist
->n_counters
= 2;
1668 hist
->n_counters
= 1;
1676 fprintf (dump_file
, "Stmt ");
1677 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
1678 dump_histogram_value (dump_file
, hist
);
1683 static struct value_prof_hooks tree_value_prof_hooks
= {
1684 tree_find_values_to_profile
,
1685 tree_value_profile_transformations
1689 tree_register_value_prof_hooks (void)
1691 gcc_assert (current_ir_type () == IR_GIMPLE
);
1692 value_prof_hooks
= &tree_value_prof_hooks
;
1695 /* IR-independent entry points. */
1697 find_values_to_profile (histogram_values
*values
)
1699 (value_prof_hooks
->find_values_to_profile
) (values
);
1703 value_profile_transformations (void)
1705 return (value_prof_hooks
->value_profile_transformations
) ();