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"
47 static struct value_prof_hooks
*value_prof_hooks
;
49 /* This is the vector of histograms. Created in find_values_to_profile.
50 During profile generation, freed by instrument_values.
51 During profile use, freed by value_profile_transformations. */
53 static histogram_values static_values
= NULL
;
55 /* In this file value profile based optimizations are placed. Currently the
56 following optimizations are implemented (for more detailed descriptions
57 see comments at value_profile_transformations):
59 1) Division/modulo specialization. Provided that we can determine that the
60 operands of the division have some special properties, we may use it to
61 produce more effective code.
62 2) Speculative prefetching. If we are able to determine that the difference
63 between addresses accessed by a memory reference is usually constant, we
64 may add the prefetch instructions.
65 FIXME: This transformation was removed together with RTL based value
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
);
89 /* The overall number of invocations of the counter should match execution count
90 of basic block. Report it as error rather than internal error as it might
91 mean that user has misused the profile somehow. */
93 check_counter (tree stmt
, const char * name
, gcov_type all
, gcov_type bb_count
)
98 locus
= (stmt
!= NULL
&& EXPR_HAS_LOCATION (stmt
)
100 : &DECL_SOURCE_LOCATION (current_function_decl
));
101 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
102 locus
, name
, (int)all
, (int)bb_count
);
108 /* Tree based transformations. */
110 tree_value_profile_transformations (void)
113 block_stmt_iterator bsi
;
114 bool changed
= false;
118 /* Ignore cold areas -- we are enlarging the code. */
119 if (!maybe_hot_bb_p (bb
))
122 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
124 tree stmt
= bsi_stmt (bsi
);
125 stmt_ann_t ann
= get_stmt_ann (stmt
);
126 histogram_value th
= ann
->histograms
;
132 fprintf (dump_file
, "Trying transformations on insn ");
133 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
136 /* Transformations: */
137 /* The order of things in this conditional controls which
138 transformation is used when more than one is applicable. */
139 /* It is expected that any code added by the transformations
140 will be added before the current statement, and that the
141 current statement remain valid (although possibly
142 modified) upon return. */
143 if (flag_value_profile_transformations
144 && (tree_mod_subtract_transform (stmt
)
145 || tree_divmod_fixed_value_transform (stmt
)
146 || tree_mod_pow2_value_transform (stmt
)))
149 /* Original statement may no longer be in the same block. */
150 bb
= bb_for_stmt (stmt
);
153 /* Free extra storage from compute_value_histograms. */
156 free (th
->hvalue
.counters
);
157 th
= th
->hvalue
.next
;
171 /* Generate code for transformation 1 (with OPERATION, operands OP1
172 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
173 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
174 within roundoff error). This generates the result into a temp and returns
175 the temp; it does not replace or alter the original STMT. */
177 tree_divmod_fixed_value (tree stmt
, tree operation
,
178 tree op1
, tree op2
, tree value
, int prob
, gcov_type count
,
181 tree stmt1
, stmt2
, stmt3
;
182 tree tmp1
, tmp2
, tmpv
;
183 tree label_decl1
= create_artificial_label ();
184 tree label_decl2
= create_artificial_label ();
185 tree label_decl3
= create_artificial_label ();
186 tree label1
, label2
, label3
;
187 tree bb1end
, bb2end
, bb3end
;
188 basic_block bb
, bb2
, bb3
, bb4
;
189 tree optype
= TREE_TYPE (operation
);
190 edge e12
, e13
, e23
, e24
, e34
;
191 block_stmt_iterator bsi
;
193 bb
= bb_for_stmt (stmt
);
194 bsi
= bsi_for_stmt (stmt
);
196 tmpv
= create_tmp_var (optype
, "PROF");
197 tmp1
= create_tmp_var (optype
, "PROF");
198 stmt1
= build2 (MODIFY_EXPR
, optype
, tmpv
, fold_convert (optype
, value
));
199 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp1
, op2
);
200 stmt3
= build3 (COND_EXPR
, void_type_node
,
201 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
202 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
203 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
204 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
205 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
206 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
209 tmp2
= create_tmp_var (optype
, "PROF");
210 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
211 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp2
,
212 build2 (TREE_CODE (operation
), optype
, op1
, tmpv
));
213 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
214 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
217 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
218 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp2
,
219 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
220 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
221 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
224 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
225 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
228 /* Edge e23 connects bb2 to bb3, etc. */
229 e12
= split_block (bb
, bb1end
);
232 e23
= split_block (bb2
, bb2end
);
234 bb3
->count
= all
- count
;
235 e34
= split_block (bb3
, bb3end
);
239 e12
->flags
&= ~EDGE_FALLTHRU
;
240 e12
->flags
|= EDGE_FALSE_VALUE
;
241 e12
->probability
= prob
;
244 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
245 e13
->probability
= REG_BR_PROB_BASE
- prob
;
246 e13
->count
= all
- count
;
250 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
251 e24
->probability
= REG_BR_PROB_BASE
;
254 e34
->probability
= REG_BR_PROB_BASE
;
255 e34
->count
= all
- count
;
260 /* Do transform 1) on INSN if applicable. */
262 tree_divmod_fixed_value_transform (tree stmt
)
264 stmt_ann_t ann
= get_stmt_ann (stmt
);
265 histogram_value histogram
;
267 gcov_type val
, count
, all
;
268 tree modify
, op
, op1
, op2
, result
, value
, tree_val
;
272 if (TREE_CODE (stmt
) == RETURN_EXPR
273 && TREE_OPERAND (stmt
, 0)
274 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
275 modify
= TREE_OPERAND (stmt
, 0);
276 if (TREE_CODE (modify
) != MODIFY_EXPR
)
278 op
= TREE_OPERAND (modify
, 1);
279 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
281 code
= TREE_CODE (op
);
283 if (code
!= TRUNC_DIV_EXPR
&& code
!= TRUNC_MOD_EXPR
)
286 op1
= TREE_OPERAND (op
, 0);
287 op2
= TREE_OPERAND (op
, 1);
288 if (!ann
->histograms
)
291 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
292 if (histogram
->type
== HIST_TYPE_SINGLE_VALUE
)
298 value
= histogram
->hvalue
.value
;
299 val
= histogram
->hvalue
.counters
[0];
300 count
= histogram
->hvalue
.counters
[1];
301 all
= histogram
->hvalue
.counters
[2];
303 /* We require that count is at least half of all; this means
304 that for the transformation to fire the value must be constant
305 at least 50% of time (and 75% gives the guarantee of usage). */
306 if (simple_cst_equal (op2
, value
) != 1 || 2 * count
< all
)
309 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
312 /* Compute probability of taking the optimal path. */
313 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
315 tree_val
= build_int_cst_wide (get_gcov_type (),
316 (unsigned HOST_WIDE_INT
) val
,
317 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
318 result
= tree_divmod_fixed_value (stmt
, op
, op1
, op2
, tree_val
, prob
, count
, all
);
322 fprintf (dump_file
, "Div/mod by constant ");
323 print_generic_expr (dump_file
, value
, TDF_SLIM
);
324 fprintf (dump_file
, "=");
325 print_generic_expr (dump_file
, tree_val
, TDF_SLIM
);
326 fprintf (dump_file
, " transformation on insn ");
327 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
330 TREE_OPERAND (modify
, 1) = result
;
335 /* Generate code for transformation 2 (with OPERATION, operands OP1
336 and OP2, parent modify-expr STMT and probability of taking the optimal
337 path PROB, which is equivalent to COUNT/ALL within roundoff error).
338 This generates the result into a temp and returns
339 the temp; it does not replace or alter the original STMT. */
341 tree_mod_pow2 (tree stmt
, tree operation
, tree op1
, tree op2
, int prob
,
342 gcov_type count
, gcov_type all
)
344 tree stmt1
, stmt2
, stmt3
, stmt4
;
345 tree tmp1
, tmp2
, tmp3
;
346 tree label_decl1
= create_artificial_label ();
347 tree label_decl2
= create_artificial_label ();
348 tree label_decl3
= create_artificial_label ();
349 tree label1
, label2
, label3
;
350 tree bb1end
, bb2end
, bb3end
;
351 basic_block bb
, bb2
, bb3
, bb4
;
352 tree optype
= TREE_TYPE (operation
);
353 edge e12
, e13
, e23
, e24
, e34
;
354 block_stmt_iterator bsi
;
355 tree result
= create_tmp_var (optype
, "PROF");
357 bb
= bb_for_stmt (stmt
);
358 bsi
= bsi_for_stmt (stmt
);
360 tmp1
= create_tmp_var (optype
, "PROF");
361 tmp2
= create_tmp_var (optype
, "PROF");
362 tmp3
= create_tmp_var (optype
, "PROF");
363 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp1
, fold_convert (optype
, op2
));
364 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp2
,
365 build2 (PLUS_EXPR
, optype
, op2
, integer_minus_one_node
));
366 stmt3
= build2 (MODIFY_EXPR
, optype
, tmp3
,
367 build2 (BIT_AND_EXPR
, optype
, tmp2
, tmp1
));
368 stmt4
= build3 (COND_EXPR
, void_type_node
,
369 build2 (NE_EXPR
, boolean_type_node
, tmp3
, integer_zero_node
),
370 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
371 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
372 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
373 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
374 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
375 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
378 /* tmp2 == op2-1 inherited from previous block */
379 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
380 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
381 build2 (BIT_AND_EXPR
, optype
, op1
, tmp2
));
382 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
383 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
386 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
387 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
388 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
389 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
390 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
393 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
394 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
397 /* Edge e23 connects bb2 to bb3, etc. */
398 e12
= split_block (bb
, bb1end
);
401 e23
= split_block (bb2
, bb2end
);
403 bb3
->count
= all
- count
;
404 e34
= split_block (bb3
, bb3end
);
408 e12
->flags
&= ~EDGE_FALLTHRU
;
409 e12
->flags
|= EDGE_FALSE_VALUE
;
410 e12
->probability
= prob
;
413 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
414 e13
->probability
= REG_BR_PROB_BASE
- prob
;
415 e13
->count
= all
- count
;
419 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
420 e24
->probability
= REG_BR_PROB_BASE
;
423 e34
->probability
= REG_BR_PROB_BASE
;
424 e34
->count
= all
- count
;
429 /* Do transform 2) on INSN if applicable. */
431 tree_mod_pow2_value_transform (tree stmt
)
433 stmt_ann_t ann
= get_stmt_ann (stmt
);
434 histogram_value histogram
;
436 gcov_type count
, wrong_values
, all
;
437 tree modify
, op
, op1
, op2
, result
, value
;
441 if (TREE_CODE (stmt
) == RETURN_EXPR
442 && TREE_OPERAND (stmt
, 0)
443 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
444 modify
= TREE_OPERAND (stmt
, 0);
445 if (TREE_CODE (modify
) != MODIFY_EXPR
)
447 op
= TREE_OPERAND (modify
, 1);
448 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
450 code
= TREE_CODE (op
);
452 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
455 op1
= TREE_OPERAND (op
, 0);
456 op2
= TREE_OPERAND (op
, 1);
457 if (!ann
->histograms
)
460 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
461 if (histogram
->type
== HIST_TYPE_POW2
)
467 value
= histogram
->hvalue
.value
;
468 wrong_values
= histogram
->hvalue
.counters
[0];
469 count
= histogram
->hvalue
.counters
[1];
471 /* We require that we hit a power of 2 at least half of all evaluations. */
472 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
)
477 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
478 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
481 /* Compute probability of taking the optimal path. */
482 all
= count
+ wrong_values
;
483 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
486 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
488 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
490 TREE_OPERAND (modify
, 1) = result
;
495 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
496 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
497 support. Currently only NCOUNTS==0 or 1 is supported and this is
498 built into this interface. The probabilities of taking the optimal
499 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
500 COUNT2/ALL respectively within roundoff error). This generates the
501 result into a temp and returns the temp; it does not replace or alter
502 the original STMT. */
503 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
506 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
507 int prob1
, int prob2
, int ncounts
,
508 gcov_type count1
, gcov_type count2
, gcov_type all
)
510 tree stmt1
, stmt2
, stmt3
;
512 tree label_decl1
= create_artificial_label ();
513 tree label_decl2
= create_artificial_label ();
514 tree label_decl3
= create_artificial_label ();
515 tree label1
, label2
, label3
;
516 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
517 basic_block bb
, bb2
, bb3
, bb4
;
518 tree optype
= TREE_TYPE (operation
);
519 edge e12
, e23
= 0, e24
, e34
, e14
;
520 block_stmt_iterator bsi
;
521 tree result
= create_tmp_var (optype
, "PROF");
523 bb
= bb_for_stmt (stmt
);
524 bsi
= bsi_for_stmt (stmt
);
526 tmp1
= create_tmp_var (optype
, "PROF");
527 stmt1
= build2 (MODIFY_EXPR
, optype
, result
, op1
);
528 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp1
, op2
);
529 stmt3
= build3 (COND_EXPR
, void_type_node
,
530 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
531 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
532 build1 (GOTO_EXPR
, void_type_node
,
533 ncounts
? label_decl1
: label_decl2
));
534 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
535 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
536 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
539 if (ncounts
) /* Assumed to be 0 or 1 */
541 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
542 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
543 build2 (MINUS_EXPR
, optype
, result
, tmp1
));
544 stmt2
= build3 (COND_EXPR
, void_type_node
,
545 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
546 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
547 build1 (GOTO_EXPR
, void_type_node
, label_decl2
));
548 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
549 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
550 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
555 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
556 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
557 build2 (TREE_CODE (operation
), optype
, result
, tmp1
));
558 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
559 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
562 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
563 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
566 /* Edge e23 connects bb2 to bb3, etc. */
567 /* However block 3 is optional; if it is not there, references
568 to 3 really refer to block 2. */
569 e12
= split_block (bb
, bb1end
);
571 bb2
->count
= all
- count1
;
573 if (ncounts
) /* Assumed to be 0 or 1. */
575 e23
= split_block (bb2
, bb2end
);
577 bb3
->count
= all
- count1
- count2
;
580 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
584 e12
->flags
&= ~EDGE_FALLTHRU
;
585 e12
->flags
|= EDGE_FALSE_VALUE
;
586 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
587 e12
->count
= all
- count1
;
589 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
590 e14
->probability
= prob1
;
593 if (ncounts
) /* Assumed to be 0 or 1. */
595 e23
->flags
&= ~EDGE_FALLTHRU
;
596 e23
->flags
|= EDGE_FALSE_VALUE
;
597 e23
->count
= all
- count1
- count2
;
598 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
600 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
601 e24
->probability
= prob2
;
605 e34
->probability
= REG_BR_PROB_BASE
;
606 e34
->count
= all
- count1
- count2
;
611 /* Do transforms 3) and 4) on INSN if applicable. */
613 tree_mod_subtract_transform (tree stmt
)
615 stmt_ann_t ann
= get_stmt_ann (stmt
);
616 histogram_value histogram
;
618 gcov_type count
, wrong_values
, all
;
619 tree modify
, op
, op1
, op2
, result
, value
;
624 if (TREE_CODE (stmt
) == RETURN_EXPR
625 && TREE_OPERAND (stmt
, 0)
626 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
627 modify
= TREE_OPERAND (stmt
, 0);
628 if (TREE_CODE (modify
) != MODIFY_EXPR
)
630 op
= TREE_OPERAND (modify
, 1);
631 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
633 code
= TREE_CODE (op
);
635 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
638 op1
= TREE_OPERAND (op
, 0);
639 op2
= TREE_OPERAND (op
, 1);
640 if (!ann
->histograms
)
643 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
644 if (histogram
->type
== HIST_TYPE_INTERVAL
)
650 value
= histogram
->hvalue
.value
;
653 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
654 all
+= histogram
->hvalue
.counters
[i
];
656 wrong_values
+= histogram
->hvalue
.counters
[i
];
657 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
660 /* Compute probability of taking the optimal path. */
661 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
664 /* We require that we use just subtractions in at least 50% of all
667 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
669 count
+= histogram
->hvalue
.counters
[i
];
670 if (count
* 2 >= all
)
673 if (i
== histogram
->hdata
.intvl
.steps
)
678 fprintf (dump_file
, "Mod subtract transformation on insn ");
679 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
682 /* Compute probability of taking the optimal path(s). */
683 prob1
= (histogram
->hvalue
.counters
[0] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
684 prob2
= (histogram
->hvalue
.counters
[1] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
686 /* In practice, "steps" is always 2. This interface reflects this,
687 and will need to be changed if "steps" can change. */
688 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
689 histogram
->hvalue
.counters
[0],
690 histogram
->hvalue
.counters
[1], all
);
692 TREE_OPERAND (modify
, 1) = result
;
697 struct value_prof_hooks
{
698 /* Find list of values for which we want to measure histograms. */
699 void (*find_values_to_profile
) (histogram_values
*);
701 /* Identify and exploit properties of values that are hard to analyze
702 statically. See value-prof.c for more detail. */
703 bool (*value_profile_transformations
) (void);
706 /* Find values inside STMT for that we want to measure histograms for
707 division/modulo optimization. */
709 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
711 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
712 histogram_value hist
;
714 if (TREE_CODE (stmt
) == RETURN_EXPR
)
715 assign
= TREE_OPERAND (stmt
, 0);
720 || TREE_CODE (assign
) != MODIFY_EXPR
)
722 lhs
= TREE_OPERAND (assign
, 0);
723 type
= TREE_TYPE (lhs
);
724 if (!INTEGRAL_TYPE_P (type
))
727 rhs
= TREE_OPERAND (assign
, 1);
728 switch (TREE_CODE (rhs
))
732 divisor
= TREE_OPERAND (rhs
, 1);
733 op0
= TREE_OPERAND (rhs
, 0);
735 VEC_reserve (histogram_value
, heap
, *values
, 3);
737 if (is_gimple_reg (divisor
))
739 /* Check for the case where the divisor is the same value most
741 hist
= ggc_alloc (sizeof (*hist
));
742 hist
->hvalue
.value
= divisor
;
743 hist
->hvalue
.stmt
= stmt
;
744 hist
->type
= HIST_TYPE_SINGLE_VALUE
;
745 VEC_quick_push (histogram_value
, *values
, hist
);
748 /* For mod, check whether it is not often a noop (or replaceable by
749 a few subtractions). */
750 if (TREE_CODE (rhs
) == TRUNC_MOD_EXPR
751 && TYPE_UNSIGNED (type
))
753 /* Check for a special case where the divisor is power of 2. */
754 hist
= ggc_alloc (sizeof (*hist
));
755 hist
->hvalue
.value
= divisor
;
756 hist
->hvalue
.stmt
= stmt
;
757 hist
->type
= HIST_TYPE_POW2
;
758 VEC_quick_push (histogram_value
, *values
, hist
);
760 hist
= ggc_alloc (sizeof (*hist
));
761 hist
->hvalue
.stmt
= stmt
;
763 = build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
764 hist
->type
= HIST_TYPE_INTERVAL
;
765 hist
->hdata
.intvl
.int_start
= 0;
766 hist
->hdata
.intvl
.steps
= 2;
767 VEC_quick_push (histogram_value
, *values
, hist
);
776 /* Find values inside STMT for that we want to measure histograms and adds
777 them to list VALUES. */
780 tree_values_to_profile (tree stmt
, histogram_values
*values
)
782 if (flag_value_profile_transformations
)
783 tree_divmod_values_to_profile (stmt
, values
);
787 tree_find_values_to_profile (histogram_values
*values
)
790 block_stmt_iterator bsi
;
792 histogram_value hist
;
796 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
797 tree_values_to_profile (bsi_stmt (bsi
), values
);
798 static_values
= *values
;
800 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
804 case HIST_TYPE_INTERVAL
:
807 fprintf (dump_file
, "Interval counter for tree ");
808 print_generic_expr (dump_file
, hist
->hvalue
.stmt
,
810 fprintf (dump_file
, ", range %d -- %d.\n",
811 hist
->hdata
.intvl
.int_start
,
812 (hist
->hdata
.intvl
.int_start
813 + hist
->hdata
.intvl
.steps
- 1));
815 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
821 fprintf (dump_file
, "Pow2 counter for tree ");
822 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
823 fprintf (dump_file
, ".\n");
825 hist
->n_counters
= 2;
828 case HIST_TYPE_SINGLE_VALUE
:
831 fprintf (dump_file
, "Single value counter for tree ");
832 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
833 fprintf (dump_file
, ".\n");
835 hist
->n_counters
= 3;
838 case HIST_TYPE_CONST_DELTA
:
841 fprintf (dump_file
, "Constant delta counter for tree ");
842 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
843 fprintf (dump_file
, ".\n");
845 hist
->n_counters
= 4;
854 static struct value_prof_hooks tree_value_prof_hooks
= {
855 tree_find_values_to_profile
,
856 tree_value_profile_transformations
860 tree_register_value_prof_hooks (void)
862 value_prof_hooks
= &tree_value_prof_hooks
;
863 gcc_assert (ir_type ());
866 /* IR-independent entry points. */
868 find_values_to_profile (histogram_values
*values
)
870 (value_prof_hooks
->find_values_to_profile
) (values
);
874 value_profile_transformations (void)
876 bool retval
= (value_prof_hooks
->value_profile_transformations
) ();
877 VEC_free (histogram_value
, heap
, static_values
);