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
;
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 tmp2
= create_tmp_var (optype
, "PROF");
361 tmp3
= create_tmp_var (optype
, "PROF");
362 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp2
,
363 build2 (PLUS_EXPR
, optype
, op2
, build_int_cst (optype
, -1)));
364 stmt3
= build2 (MODIFY_EXPR
, optype
, tmp3
,
365 build2 (BIT_AND_EXPR
, optype
, tmp2
, op2
));
366 stmt4
= build3 (COND_EXPR
, void_type_node
,
367 build2 (NE_EXPR
, boolean_type_node
,
368 tmp3
, build_int_cst (optype
, 0)),
369 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
370 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
371 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
372 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
373 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
376 /* tmp2 == op2-1 inherited from previous block */
377 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
378 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
379 build2 (BIT_AND_EXPR
, optype
, op1
, tmp2
));
380 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
381 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
384 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
385 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
386 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
387 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
388 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
391 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
392 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
395 /* Edge e23 connects bb2 to bb3, etc. */
396 e12
= split_block (bb
, bb1end
);
399 e23
= split_block (bb2
, bb2end
);
401 bb3
->count
= all
- count
;
402 e34
= split_block (bb3
, bb3end
);
406 e12
->flags
&= ~EDGE_FALLTHRU
;
407 e12
->flags
|= EDGE_FALSE_VALUE
;
408 e12
->probability
= prob
;
411 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
412 e13
->probability
= REG_BR_PROB_BASE
- prob
;
413 e13
->count
= all
- count
;
417 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
418 e24
->probability
= REG_BR_PROB_BASE
;
421 e34
->probability
= REG_BR_PROB_BASE
;
422 e34
->count
= all
- count
;
427 /* Do transform 2) on INSN if applicable. */
429 tree_mod_pow2_value_transform (tree stmt
)
431 stmt_ann_t ann
= get_stmt_ann (stmt
);
432 histogram_value histogram
;
434 gcov_type count
, wrong_values
, all
;
435 tree modify
, op
, op1
, op2
, result
, value
;
439 if (TREE_CODE (stmt
) == RETURN_EXPR
440 && TREE_OPERAND (stmt
, 0)
441 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
442 modify
= TREE_OPERAND (stmt
, 0);
443 if (TREE_CODE (modify
) != MODIFY_EXPR
)
445 op
= TREE_OPERAND (modify
, 1);
446 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
448 code
= TREE_CODE (op
);
450 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
453 op1
= TREE_OPERAND (op
, 0);
454 op2
= TREE_OPERAND (op
, 1);
455 if (!ann
->histograms
)
458 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
459 if (histogram
->type
== HIST_TYPE_POW2
)
465 value
= histogram
->hvalue
.value
;
466 wrong_values
= histogram
->hvalue
.counters
[0];
467 count
= histogram
->hvalue
.counters
[1];
469 /* We require that we hit a power of 2 at least half of all evaluations. */
470 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
)
475 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
476 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
479 /* Compute probability of taking the optimal path. */
480 all
= count
+ wrong_values
;
481 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
484 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
486 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
488 TREE_OPERAND (modify
, 1) = result
;
493 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
494 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
495 support. Currently only NCOUNTS==0 or 1 is supported and this is
496 built into this interface. The probabilities of taking the optimal
497 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
498 COUNT2/ALL respectively within roundoff error). This generates the
499 result into a temp and returns the temp; it does not replace or alter
500 the original STMT. */
501 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
504 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
505 int prob1
, int prob2
, int ncounts
,
506 gcov_type count1
, gcov_type count2
, gcov_type all
)
508 tree stmt1
, stmt2
, stmt3
;
510 tree label_decl1
= create_artificial_label ();
511 tree label_decl2
= create_artificial_label ();
512 tree label_decl3
= create_artificial_label ();
513 tree label1
, label2
, label3
;
514 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
515 basic_block bb
, bb2
, bb3
, bb4
;
516 tree optype
= TREE_TYPE (operation
);
517 edge e12
, e23
= 0, e24
, e34
, e14
;
518 block_stmt_iterator bsi
;
519 tree result
= create_tmp_var (optype
, "PROF");
521 bb
= bb_for_stmt (stmt
);
522 bsi
= bsi_for_stmt (stmt
);
524 tmp1
= create_tmp_var (optype
, "PROF");
525 stmt1
= build2 (MODIFY_EXPR
, optype
, result
, op1
);
526 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp1
, op2
);
527 stmt3
= build3 (COND_EXPR
, void_type_node
,
528 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
529 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
530 build1 (GOTO_EXPR
, void_type_node
,
531 ncounts
? label_decl1
: label_decl2
));
532 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
533 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
534 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
537 if (ncounts
) /* Assumed to be 0 or 1 */
539 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
540 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
541 build2 (MINUS_EXPR
, optype
, result
, tmp1
));
542 stmt2
= build3 (COND_EXPR
, void_type_node
,
543 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
544 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
545 build1 (GOTO_EXPR
, void_type_node
, label_decl2
));
546 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
547 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
548 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
553 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
554 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
555 build2 (TREE_CODE (operation
), optype
, result
, tmp1
));
556 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
557 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
560 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
561 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
564 /* Edge e23 connects bb2 to bb3, etc. */
565 /* However block 3 is optional; if it is not there, references
566 to 3 really refer to block 2. */
567 e12
= split_block (bb
, bb1end
);
569 bb2
->count
= all
- count1
;
571 if (ncounts
) /* Assumed to be 0 or 1. */
573 e23
= split_block (bb2
, bb2end
);
575 bb3
->count
= all
- count1
- count2
;
578 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
582 e12
->flags
&= ~EDGE_FALLTHRU
;
583 e12
->flags
|= EDGE_FALSE_VALUE
;
584 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
585 e12
->count
= all
- count1
;
587 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
588 e14
->probability
= prob1
;
591 if (ncounts
) /* Assumed to be 0 or 1. */
593 e23
->flags
&= ~EDGE_FALLTHRU
;
594 e23
->flags
|= EDGE_FALSE_VALUE
;
595 e23
->count
= all
- count1
- count2
;
596 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
598 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
599 e24
->probability
= prob2
;
603 e34
->probability
= REG_BR_PROB_BASE
;
604 e34
->count
= all
- count1
- count2
;
609 /* Do transforms 3) and 4) on INSN if applicable. */
611 tree_mod_subtract_transform (tree stmt
)
613 stmt_ann_t ann
= get_stmt_ann (stmt
);
614 histogram_value histogram
;
616 gcov_type count
, wrong_values
, all
;
617 tree modify
, op
, op1
, op2
, result
, value
;
622 if (TREE_CODE (stmt
) == RETURN_EXPR
623 && TREE_OPERAND (stmt
, 0)
624 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
625 modify
= TREE_OPERAND (stmt
, 0);
626 if (TREE_CODE (modify
) != MODIFY_EXPR
)
628 op
= TREE_OPERAND (modify
, 1);
629 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
631 code
= TREE_CODE (op
);
633 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
636 op1
= TREE_OPERAND (op
, 0);
637 op2
= TREE_OPERAND (op
, 1);
638 if (!ann
->histograms
)
641 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
642 if (histogram
->type
== HIST_TYPE_INTERVAL
)
648 value
= histogram
->hvalue
.value
;
651 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
652 all
+= histogram
->hvalue
.counters
[i
];
654 wrong_values
+= histogram
->hvalue
.counters
[i
];
655 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
658 /* Compute probability of taking the optimal path. */
659 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
662 /* We require that we use just subtractions in at least 50% of all
665 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
667 count
+= histogram
->hvalue
.counters
[i
];
668 if (count
* 2 >= all
)
671 if (i
== histogram
->hdata
.intvl
.steps
)
676 fprintf (dump_file
, "Mod subtract transformation on insn ");
677 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
680 /* Compute probability of taking the optimal path(s). */
681 prob1
= (histogram
->hvalue
.counters
[0] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
682 prob2
= (histogram
->hvalue
.counters
[1] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
684 /* In practice, "steps" is always 2. This interface reflects this,
685 and will need to be changed if "steps" can change. */
686 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
687 histogram
->hvalue
.counters
[0],
688 histogram
->hvalue
.counters
[1], all
);
690 TREE_OPERAND (modify
, 1) = result
;
695 struct value_prof_hooks
{
696 /* Find list of values for which we want to measure histograms. */
697 void (*find_values_to_profile
) (histogram_values
*);
699 /* Identify and exploit properties of values that are hard to analyze
700 statically. See value-prof.c for more detail. */
701 bool (*value_profile_transformations
) (void);
704 /* Find values inside STMT for that we want to measure histograms for
705 division/modulo optimization. */
707 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
709 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
710 histogram_value hist
;
712 if (TREE_CODE (stmt
) == RETURN_EXPR
)
713 assign
= TREE_OPERAND (stmt
, 0);
718 || TREE_CODE (assign
) != MODIFY_EXPR
)
720 lhs
= TREE_OPERAND (assign
, 0);
721 type
= TREE_TYPE (lhs
);
722 if (!INTEGRAL_TYPE_P (type
))
725 rhs
= TREE_OPERAND (assign
, 1);
726 switch (TREE_CODE (rhs
))
730 divisor
= TREE_OPERAND (rhs
, 1);
731 op0
= TREE_OPERAND (rhs
, 0);
733 VEC_reserve (histogram_value
, heap
, *values
, 3);
735 if (is_gimple_reg (divisor
))
737 /* Check for the case where the divisor is the same value most
739 hist
= ggc_alloc (sizeof (*hist
));
740 hist
->hvalue
.value
= divisor
;
741 hist
->hvalue
.stmt
= stmt
;
742 hist
->type
= HIST_TYPE_SINGLE_VALUE
;
743 VEC_quick_push (histogram_value
, *values
, hist
);
746 /* For mod, check whether it is not often a noop (or replaceable by
747 a few subtractions). */
748 if (TREE_CODE (rhs
) == TRUNC_MOD_EXPR
749 && TYPE_UNSIGNED (type
))
751 /* Check for a special case where the divisor is power of 2. */
752 hist
= ggc_alloc (sizeof (*hist
));
753 hist
->hvalue
.value
= divisor
;
754 hist
->hvalue
.stmt
= stmt
;
755 hist
->type
= HIST_TYPE_POW2
;
756 VEC_quick_push (histogram_value
, *values
, hist
);
758 hist
= ggc_alloc (sizeof (*hist
));
759 hist
->hvalue
.stmt
= stmt
;
761 = build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
762 hist
->type
= HIST_TYPE_INTERVAL
;
763 hist
->hdata
.intvl
.int_start
= 0;
764 hist
->hdata
.intvl
.steps
= 2;
765 VEC_quick_push (histogram_value
, *values
, hist
);
774 /* Find values inside STMT for that we want to measure histograms and adds
775 them to list VALUES. */
778 tree_values_to_profile (tree stmt
, histogram_values
*values
)
780 if (flag_value_profile_transformations
)
781 tree_divmod_values_to_profile (stmt
, values
);
785 tree_find_values_to_profile (histogram_values
*values
)
788 block_stmt_iterator bsi
;
790 histogram_value hist
;
794 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
795 tree_values_to_profile (bsi_stmt (bsi
), values
);
796 static_values
= *values
;
798 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
802 case HIST_TYPE_INTERVAL
:
805 fprintf (dump_file
, "Interval counter for tree ");
806 print_generic_expr (dump_file
, hist
->hvalue
.stmt
,
808 fprintf (dump_file
, ", range %d -- %d.\n",
809 hist
->hdata
.intvl
.int_start
,
810 (hist
->hdata
.intvl
.int_start
811 + hist
->hdata
.intvl
.steps
- 1));
813 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
819 fprintf (dump_file
, "Pow2 counter for tree ");
820 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
821 fprintf (dump_file
, ".\n");
823 hist
->n_counters
= 2;
826 case HIST_TYPE_SINGLE_VALUE
:
829 fprintf (dump_file
, "Single value counter for tree ");
830 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
831 fprintf (dump_file
, ".\n");
833 hist
->n_counters
= 3;
836 case HIST_TYPE_CONST_DELTA
:
839 fprintf (dump_file
, "Constant delta counter for tree ");
840 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
841 fprintf (dump_file
, ".\n");
843 hist
->n_counters
= 4;
852 static struct value_prof_hooks tree_value_prof_hooks
= {
853 tree_find_values_to_profile
,
854 tree_value_profile_transformations
858 tree_register_value_prof_hooks (void)
860 value_prof_hooks
= &tree_value_prof_hooks
;
861 gcc_assert (ir_type ());
864 /* IR-independent entry points. */
866 find_values_to_profile (histogram_values
*values
)
868 (value_prof_hooks
->find_values_to_profile
) (values
);
872 value_profile_transformations (void)
874 bool retval
= (value_prof_hooks
->value_profile_transformations
) ();
875 VEC_free (histogram_value
, heap
, static_values
);