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 /* In this file value profile based optimizations are placed. Currently the
50 following optimizations are implemented (for more detailed descriptions
51 see comments at value_profile_transformations):
53 1) Division/modulo specialization. Provided that we can determine that the
54 operands of the division have some special properties, we may use it to
55 produce more effective code.
56 2) Speculative prefetching. If we are able to determine that the difference
57 between addresses accessed by a memory reference is usually constant, we
58 may add the prefetch instructions.
59 FIXME: This transformation was removed together with RTL based value
62 Every such optimization should add its requirements for profiled values to
63 insn_values_to_profile function. This function is called from branch_prob
64 in profile.c and the requested values are instrumented by it in the first
65 compilation with -fprofile-arcs. The optimization may then read the
66 gathered data in the second compilation with -fbranch-probabilities.
68 The measured data is pointed to from the histograms
69 field of the statement annotation of the instrumented insns. It is
70 kept as a linked list of struct histogram_value_t's, which contain the
71 same information as above. */
74 static tree
tree_divmod_fixed_value (tree
, tree
, tree
, tree
,
75 tree
, int, gcov_type
, gcov_type
);
76 static tree
tree_mod_pow2 (tree
, tree
, tree
, tree
, int, gcov_type
, gcov_type
);
77 static tree
tree_mod_subtract (tree
, tree
, tree
, tree
, int, int, int,
78 gcov_type
, gcov_type
, gcov_type
);
79 static bool tree_divmod_fixed_value_transform (tree
);
80 static bool tree_mod_pow2_value_transform (tree
);
81 static bool tree_mod_subtract_transform (tree
);
83 /* The overall number of invocations of the counter should match execution count
84 of basic block. Report it as error rather than internal error as it might
85 mean that user has misused the profile somehow. */
87 check_counter (tree stmt
, const char * name
, gcov_type all
, gcov_type bb_count
)
92 locus
= (stmt
!= NULL
&& EXPR_HAS_LOCATION (stmt
)
94 : &DECL_SOURCE_LOCATION (current_function_decl
));
95 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
96 locus
, name
, (int)all
, (int)bb_count
);
102 /* Tree based transformations. */
104 tree_value_profile_transformations (void)
107 block_stmt_iterator bsi
;
108 bool changed
= false;
112 /* Ignore cold areas -- we are enlarging the code. */
113 if (!maybe_hot_bb_p (bb
))
116 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
118 tree stmt
= bsi_stmt (bsi
);
119 stmt_ann_t ann
= get_stmt_ann (stmt
);
120 histogram_value th
= ann
->histograms
;
126 fprintf (dump_file
, "Trying transformations on insn ");
127 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
130 /* Transformations: */
131 /* The order of things in this conditional controls which
132 transformation is used when more than one is applicable. */
133 /* It is expected that any code added by the transformations
134 will be added before the current statement, and that the
135 current statement remain valid (although possibly
136 modified) upon return. */
137 if (flag_value_profile_transformations
138 && (tree_mod_subtract_transform (stmt
)
139 || tree_divmod_fixed_value_transform (stmt
)
140 || tree_mod_pow2_value_transform (stmt
)))
143 /* Original statement may no longer be in the same block. */
144 bb
= bb_for_stmt (stmt
);
147 /* Free extra storage from compute_value_histograms. */
150 free (th
->hvalue
.counters
);
151 th
= th
->hvalue
.next
;
165 /* Generate code for transformation 1 (with OPERATION, operands OP1
166 and OP2, whose value is expected to be VALUE, parent modify-expr STMT and
167 probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
168 within roundoff error). This generates the result into a temp and returns
169 the temp; it does not replace or alter the original STMT. */
171 tree_divmod_fixed_value (tree stmt
, tree operation
,
172 tree op1
, tree op2
, tree value
, int prob
, gcov_type count
,
175 tree stmt1
, stmt2
, stmt3
;
176 tree tmp1
, tmp2
, tmpv
;
177 tree label_decl1
= create_artificial_label ();
178 tree label_decl2
= create_artificial_label ();
179 tree label_decl3
= create_artificial_label ();
180 tree label1
, label2
, label3
;
181 tree bb1end
, bb2end
, bb3end
;
182 basic_block bb
, bb2
, bb3
, bb4
;
183 tree optype
= TREE_TYPE (operation
);
184 edge e12
, e13
, e23
, e24
, e34
;
185 block_stmt_iterator bsi
;
187 bb
= bb_for_stmt (stmt
);
188 bsi
= bsi_for_stmt (stmt
);
190 tmpv
= create_tmp_var (optype
, "PROF");
191 tmp1
= create_tmp_var (optype
, "PROF");
192 stmt1
= build2 (MODIFY_EXPR
, optype
, tmpv
, fold_convert (optype
, value
));
193 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp1
, op2
);
194 stmt3
= build3 (COND_EXPR
, void_type_node
,
195 build2 (NE_EXPR
, boolean_type_node
, tmp1
, tmpv
),
196 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
197 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
198 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
199 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
200 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
203 tmp2
= create_tmp_var (optype
, "PROF");
204 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
205 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp2
,
206 build2 (TREE_CODE (operation
), optype
, op1
, tmpv
));
207 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
208 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
211 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
212 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp2
,
213 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
214 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
215 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
218 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
219 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
222 /* Edge e23 connects bb2 to bb3, etc. */
223 e12
= split_block (bb
, bb1end
);
226 e23
= split_block (bb2
, bb2end
);
228 bb3
->count
= all
- count
;
229 e34
= split_block (bb3
, bb3end
);
233 e12
->flags
&= ~EDGE_FALLTHRU
;
234 e12
->flags
|= EDGE_FALSE_VALUE
;
235 e12
->probability
= prob
;
238 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
239 e13
->probability
= REG_BR_PROB_BASE
- prob
;
240 e13
->count
= all
- count
;
244 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
245 e24
->probability
= REG_BR_PROB_BASE
;
248 e34
->probability
= REG_BR_PROB_BASE
;
249 e34
->count
= all
- count
;
254 /* Do transform 1) on INSN if applicable. */
256 tree_divmod_fixed_value_transform (tree stmt
)
258 stmt_ann_t ann
= get_stmt_ann (stmt
);
259 histogram_value histogram
;
261 gcov_type val
, count
, all
;
262 tree modify
, op
, op1
, op2
, result
, value
, tree_val
;
266 if (TREE_CODE (stmt
) == RETURN_EXPR
267 && TREE_OPERAND (stmt
, 0)
268 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
269 modify
= TREE_OPERAND (stmt
, 0);
270 if (TREE_CODE (modify
) != MODIFY_EXPR
)
272 op
= TREE_OPERAND (modify
, 1);
273 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
275 code
= TREE_CODE (op
);
277 if (code
!= TRUNC_DIV_EXPR
&& code
!= TRUNC_MOD_EXPR
)
280 op1
= TREE_OPERAND (op
, 0);
281 op2
= TREE_OPERAND (op
, 1);
282 if (!ann
->histograms
)
285 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
286 if (histogram
->type
== HIST_TYPE_SINGLE_VALUE
)
292 value
= histogram
->hvalue
.value
;
293 val
= histogram
->hvalue
.counters
[0];
294 count
= histogram
->hvalue
.counters
[1];
295 all
= histogram
->hvalue
.counters
[2];
297 /* We require that count is at least half of all; this means
298 that for the transformation to fire the value must be constant
299 at least 50% of time (and 75% gives the guarantee of usage). */
300 if (simple_cst_equal (op2
, value
) != 1 || 2 * count
< all
)
303 if (check_counter (stmt
, "value", all
, bb_for_stmt (stmt
)->count
))
306 /* Compute probability of taking the optimal path. */
307 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
309 tree_val
= build_int_cst_wide (get_gcov_type (),
310 (unsigned HOST_WIDE_INT
) val
,
311 val
>> (HOST_BITS_PER_WIDE_INT
- 1) >> 1);
312 result
= tree_divmod_fixed_value (stmt
, op
, op1
, op2
, tree_val
, prob
, count
, all
);
316 fprintf (dump_file
, "Div/mod by constant ");
317 print_generic_expr (dump_file
, value
, TDF_SLIM
);
318 fprintf (dump_file
, "=");
319 print_generic_expr (dump_file
, tree_val
, TDF_SLIM
);
320 fprintf (dump_file
, " transformation on insn ");
321 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
324 TREE_OPERAND (modify
, 1) = result
;
329 /* Generate code for transformation 2 (with OPERATION, operands OP1
330 and OP2, parent modify-expr STMT and probability of taking the optimal
331 path PROB, which is equivalent to COUNT/ALL within roundoff error).
332 This generates the result into a temp and returns
333 the temp; it does not replace or alter the original STMT. */
335 tree_mod_pow2 (tree stmt
, tree operation
, tree op1
, tree op2
, int prob
,
336 gcov_type count
, gcov_type all
)
338 tree stmt1
, stmt2
, stmt3
, stmt4
;
339 tree tmp1
, tmp2
, tmp3
;
340 tree label_decl1
= create_artificial_label ();
341 tree label_decl2
= create_artificial_label ();
342 tree label_decl3
= create_artificial_label ();
343 tree label1
, label2
, label3
;
344 tree bb1end
, bb2end
, bb3end
;
345 basic_block bb
, bb2
, bb3
, bb4
;
346 tree optype
= TREE_TYPE (operation
);
347 edge e12
, e13
, e23
, e24
, e34
;
348 block_stmt_iterator bsi
;
349 tree result
= create_tmp_var (optype
, "PROF");
351 bb
= bb_for_stmt (stmt
);
352 bsi
= bsi_for_stmt (stmt
);
354 tmp1
= create_tmp_var (optype
, "PROF");
355 tmp2
= create_tmp_var (optype
, "PROF");
356 tmp3
= create_tmp_var (optype
, "PROF");
357 stmt1
= build2 (MODIFY_EXPR
, optype
, tmp1
, fold_convert (optype
, op2
));
358 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp2
,
359 build2 (PLUS_EXPR
, optype
, op2
, integer_minus_one_node
));
360 stmt3
= build2 (MODIFY_EXPR
, optype
, tmp3
,
361 build2 (BIT_AND_EXPR
, optype
, tmp2
, tmp1
));
362 stmt4
= build3 (COND_EXPR
, void_type_node
,
363 build2 (NE_EXPR
, boolean_type_node
, tmp3
, integer_zero_node
),
364 build1 (GOTO_EXPR
, void_type_node
, label_decl2
),
365 build1 (GOTO_EXPR
, void_type_node
, label_decl1
));
366 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
367 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
368 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
369 bsi_insert_before (&bsi
, stmt4
, BSI_SAME_STMT
);
372 /* tmp2 == op2-1 inherited from previous block */
373 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
374 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
375 build2 (BIT_AND_EXPR
, optype
, op1
, tmp2
));
376 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
377 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
380 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
381 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
382 build2 (TREE_CODE (operation
), optype
, op1
, op2
));
383 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
384 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
387 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
388 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
391 /* Edge e23 connects bb2 to bb3, etc. */
392 e12
= split_block (bb
, bb1end
);
395 e23
= split_block (bb2
, bb2end
);
397 bb3
->count
= all
- count
;
398 e34
= split_block (bb3
, bb3end
);
402 e12
->flags
&= ~EDGE_FALLTHRU
;
403 e12
->flags
|= EDGE_FALSE_VALUE
;
404 e12
->probability
= prob
;
407 e13
= make_edge (bb
, bb3
, EDGE_TRUE_VALUE
);
408 e13
->probability
= REG_BR_PROB_BASE
- prob
;
409 e13
->count
= all
- count
;
413 e24
= make_edge (bb2
, bb4
, EDGE_FALLTHRU
);
414 e24
->probability
= REG_BR_PROB_BASE
;
417 e34
->probability
= REG_BR_PROB_BASE
;
418 e34
->count
= all
- count
;
423 /* Do transform 2) on INSN if applicable. */
425 tree_mod_pow2_value_transform (tree stmt
)
427 stmt_ann_t ann
= get_stmt_ann (stmt
);
428 histogram_value histogram
;
430 gcov_type count
, wrong_values
, all
;
431 tree modify
, op
, op1
, op2
, result
, value
;
435 if (TREE_CODE (stmt
) == RETURN_EXPR
436 && TREE_OPERAND (stmt
, 0)
437 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
438 modify
= TREE_OPERAND (stmt
, 0);
439 if (TREE_CODE (modify
) != MODIFY_EXPR
)
441 op
= TREE_OPERAND (modify
, 1);
442 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
444 code
= TREE_CODE (op
);
446 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
449 op1
= TREE_OPERAND (op
, 0);
450 op2
= TREE_OPERAND (op
, 1);
451 if (!ann
->histograms
)
454 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
455 if (histogram
->type
== HIST_TYPE_POW2
)
461 value
= histogram
->hvalue
.value
;
462 wrong_values
= histogram
->hvalue
.counters
[0];
463 count
= histogram
->hvalue
.counters
[1];
465 /* We require that we hit a power of 2 at least half of all evaluations. */
466 if (simple_cst_equal (op2
, value
) != 1 || count
< wrong_values
)
471 fprintf (dump_file
, "Mod power of 2 transformation on insn ");
472 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
475 /* Compute probability of taking the optimal path. */
476 all
= count
+ wrong_values
;
477 if (check_counter (stmt
, "pow2", all
, bb_for_stmt (stmt
)->count
))
480 prob
= (count
* REG_BR_PROB_BASE
+ all
/ 2) / all
;
482 result
= tree_mod_pow2 (stmt
, op
, op1
, op2
, prob
, count
, all
);
484 TREE_OPERAND (modify
, 1) = result
;
489 /* Generate code for transformations 3 and 4 (with OPERATION, operands OP1
490 and OP2, parent modify-expr STMT, and NCOUNTS the number of cases to
491 support. Currently only NCOUNTS==0 or 1 is supported and this is
492 built into this interface. The probabilities of taking the optimal
493 paths are PROB1 and PROB2, which are equivalent to COUNT1/ALL and
494 COUNT2/ALL respectively within roundoff error). This generates the
495 result into a temp and returns the temp; it does not replace or alter
496 the original STMT. */
497 /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
500 tree_mod_subtract (tree stmt
, tree operation
, tree op1
, tree op2
,
501 int prob1
, int prob2
, int ncounts
,
502 gcov_type count1
, gcov_type count2
, gcov_type all
)
504 tree stmt1
, stmt2
, stmt3
;
506 tree label_decl1
= create_artificial_label ();
507 tree label_decl2
= create_artificial_label ();
508 tree label_decl3
= create_artificial_label ();
509 tree label1
, label2
, label3
;
510 tree bb1end
, bb2end
= NULL_TREE
, bb3end
;
511 basic_block bb
, bb2
, bb3
, bb4
;
512 tree optype
= TREE_TYPE (operation
);
513 edge e12
, e23
= 0, e24
, e34
, e14
;
514 block_stmt_iterator bsi
;
515 tree result
= create_tmp_var (optype
, "PROF");
517 bb
= bb_for_stmt (stmt
);
518 bsi
= bsi_for_stmt (stmt
);
520 tmp1
= create_tmp_var (optype
, "PROF");
521 stmt1
= build2 (MODIFY_EXPR
, optype
, result
, op1
);
522 stmt2
= build2 (MODIFY_EXPR
, optype
, tmp1
, op2
);
523 stmt3
= build3 (COND_EXPR
, void_type_node
,
524 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
525 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
526 build1 (GOTO_EXPR
, void_type_node
,
527 ncounts
? label_decl1
: label_decl2
));
528 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
529 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
530 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
533 if (ncounts
) /* Assumed to be 0 or 1 */
535 label1
= build1 (LABEL_EXPR
, void_type_node
, label_decl1
);
536 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
537 build2 (MINUS_EXPR
, optype
, result
, tmp1
));
538 stmt2
= build3 (COND_EXPR
, void_type_node
,
539 build2 (LT_EXPR
, boolean_type_node
, result
, tmp1
),
540 build1 (GOTO_EXPR
, void_type_node
, label_decl3
),
541 build1 (GOTO_EXPR
, void_type_node
, label_decl2
));
542 bsi_insert_before (&bsi
, label1
, BSI_SAME_STMT
);
543 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
544 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
549 label2
= build1 (LABEL_EXPR
, void_type_node
, label_decl2
);
550 stmt1
= build2 (MODIFY_EXPR
, optype
, result
,
551 build2 (TREE_CODE (operation
), optype
, result
, tmp1
));
552 bsi_insert_before (&bsi
, label2
, BSI_SAME_STMT
);
553 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
556 label3
= build1 (LABEL_EXPR
, void_type_node
, label_decl3
);
557 bsi_insert_before (&bsi
, label3
, BSI_SAME_STMT
);
560 /* Edge e23 connects bb2 to bb3, etc. */
561 /* However block 3 is optional; if it is not there, references
562 to 3 really refer to block 2. */
563 e12
= split_block (bb
, bb1end
);
565 bb2
->count
= all
- count1
;
567 if (ncounts
) /* Assumed to be 0 or 1. */
569 e23
= split_block (bb2
, bb2end
);
571 bb3
->count
= all
- count1
- count2
;
574 e34
= split_block (ncounts
? bb3
: bb2
, bb3end
);
578 e12
->flags
&= ~EDGE_FALLTHRU
;
579 e12
->flags
|= EDGE_FALSE_VALUE
;
580 e12
->probability
= REG_BR_PROB_BASE
- prob1
;
581 e12
->count
= all
- count1
;
583 e14
= make_edge (bb
, bb4
, EDGE_TRUE_VALUE
);
584 e14
->probability
= prob1
;
587 if (ncounts
) /* Assumed to be 0 or 1. */
589 e23
->flags
&= ~EDGE_FALLTHRU
;
590 e23
->flags
|= EDGE_FALSE_VALUE
;
591 e23
->count
= all
- count1
- count2
;
592 e23
->probability
= REG_BR_PROB_BASE
- prob2
;
594 e24
= make_edge (bb2
, bb4
, EDGE_TRUE_VALUE
);
595 e24
->probability
= prob2
;
599 e34
->probability
= REG_BR_PROB_BASE
;
600 e34
->count
= all
- count1
- count2
;
605 /* Do transforms 3) and 4) on INSN if applicable. */
607 tree_mod_subtract_transform (tree stmt
)
609 stmt_ann_t ann
= get_stmt_ann (stmt
);
610 histogram_value histogram
;
612 gcov_type count
, wrong_values
, all
;
613 tree modify
, op
, op1
, op2
, result
, value
;
618 if (TREE_CODE (stmt
) == RETURN_EXPR
619 && TREE_OPERAND (stmt
, 0)
620 && TREE_CODE (TREE_OPERAND (stmt
, 0)) == MODIFY_EXPR
)
621 modify
= TREE_OPERAND (stmt
, 0);
622 if (TREE_CODE (modify
) != MODIFY_EXPR
)
624 op
= TREE_OPERAND (modify
, 1);
625 if (!INTEGRAL_TYPE_P (TREE_TYPE (op
)))
627 code
= TREE_CODE (op
);
629 if (code
!= TRUNC_MOD_EXPR
|| !TYPE_UNSIGNED (TREE_TYPE (op
)))
632 op1
= TREE_OPERAND (op
, 0);
633 op2
= TREE_OPERAND (op
, 1);
634 if (!ann
->histograms
)
637 for (histogram
= ann
->histograms
; histogram
; histogram
= histogram
->hvalue
.next
)
638 if (histogram
->type
== HIST_TYPE_INTERVAL
)
644 value
= histogram
->hvalue
.value
;
647 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
648 all
+= histogram
->hvalue
.counters
[i
];
650 wrong_values
+= histogram
->hvalue
.counters
[i
];
651 wrong_values
+= histogram
->hvalue
.counters
[i
+1];
654 /* Compute probability of taking the optimal path. */
655 if (check_counter (stmt
, "interval", all
, bb_for_stmt (stmt
)->count
))
658 /* We require that we use just subtractions in at least 50% of all
661 for (i
= 0; i
< histogram
->hdata
.intvl
.steps
; i
++)
663 count
+= histogram
->hvalue
.counters
[i
];
664 if (count
* 2 >= all
)
667 if (i
== histogram
->hdata
.intvl
.steps
)
672 fprintf (dump_file
, "Mod subtract transformation on insn ");
673 print_generic_stmt (dump_file
, stmt
, TDF_SLIM
);
676 /* Compute probability of taking the optimal path(s). */
677 prob1
= (histogram
->hvalue
.counters
[0] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
678 prob2
= (histogram
->hvalue
.counters
[1] * REG_BR_PROB_BASE
+ all
/ 2) / all
;
680 /* In practice, "steps" is always 2. This interface reflects this,
681 and will need to be changed if "steps" can change. */
682 result
= tree_mod_subtract (stmt
, op
, op1
, op2
, prob1
, prob2
, i
,
683 histogram
->hvalue
.counters
[0],
684 histogram
->hvalue
.counters
[1], all
);
686 TREE_OPERAND (modify
, 1) = result
;
691 struct value_prof_hooks
{
692 /* Find list of values for which we want to measure histograms. */
693 void (*find_values_to_profile
) (histogram_values
*);
695 /* Identify and exploit properties of values that are hard to analyze
696 statically. See value-prof.c for more detail. */
697 bool (*value_profile_transformations
) (void);
700 /* Find values inside STMT for that we want to measure histograms for
701 division/modulo optimization. */
703 tree_divmod_values_to_profile (tree stmt
, histogram_values
*values
)
705 tree assign
, lhs
, rhs
, divisor
, op0
, type
;
706 histogram_value hist
;
708 if (TREE_CODE (stmt
) == RETURN_EXPR
)
709 assign
= TREE_OPERAND (stmt
, 0);
714 || TREE_CODE (assign
) != MODIFY_EXPR
)
716 lhs
= TREE_OPERAND (assign
, 0);
717 type
= TREE_TYPE (lhs
);
718 if (!INTEGRAL_TYPE_P (type
))
721 rhs
= TREE_OPERAND (assign
, 1);
722 switch (TREE_CODE (rhs
))
726 divisor
= TREE_OPERAND (rhs
, 1);
727 op0
= TREE_OPERAND (rhs
, 0);
729 VEC_reserve (histogram_value
, heap
, *values
, 3);
731 if (is_gimple_reg (divisor
))
733 /* Check for the case where the divisor is the same value most
735 hist
= ggc_alloc (sizeof (*hist
));
736 hist
->hvalue
.value
= divisor
;
737 hist
->hvalue
.stmt
= stmt
;
738 hist
->type
= HIST_TYPE_SINGLE_VALUE
;
739 VEC_quick_push (histogram_value
, *values
, hist
);
742 /* For mod, check whether it is not often a noop (or replaceable by
743 a few subtractions). */
744 if (TREE_CODE (rhs
) == TRUNC_MOD_EXPR
745 && TYPE_UNSIGNED (type
))
747 /* Check for a special case where the divisor is power of 2. */
748 hist
= ggc_alloc (sizeof (*hist
));
749 hist
->hvalue
.value
= divisor
;
750 hist
->hvalue
.stmt
= stmt
;
751 hist
->type
= HIST_TYPE_POW2
;
752 VEC_quick_push (histogram_value
, *values
, hist
);
754 hist
= ggc_alloc (sizeof (*hist
));
755 hist
->hvalue
.stmt
= stmt
;
757 = build2 (TRUNC_DIV_EXPR
, type
, op0
, divisor
);
758 hist
->type
= HIST_TYPE_INTERVAL
;
759 hist
->hdata
.intvl
.int_start
= 0;
760 hist
->hdata
.intvl
.steps
= 2;
761 VEC_quick_push (histogram_value
, *values
, hist
);
770 /* Find values inside STMT for that we want to measure histograms and adds
771 them to list VALUES. */
774 tree_values_to_profile (tree stmt
, histogram_values
*values
)
776 if (flag_value_profile_transformations
)
777 tree_divmod_values_to_profile (stmt
, values
);
781 tree_find_values_to_profile (histogram_values
*values
)
784 block_stmt_iterator bsi
;
786 histogram_value hist
;
790 for (bsi
= bsi_start (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
791 tree_values_to_profile (bsi_stmt (bsi
), values
);
793 for (i
= 0; VEC_iterate (histogram_value
, *values
, i
, hist
); i
++)
797 case HIST_TYPE_INTERVAL
:
800 fprintf (dump_file
, "Interval counter for tree ");
801 print_generic_expr (dump_file
, hist
->hvalue
.stmt
,
803 fprintf (dump_file
, ", range %d -- %d.\n",
804 hist
->hdata
.intvl
.int_start
,
805 (hist
->hdata
.intvl
.int_start
806 + hist
->hdata
.intvl
.steps
- 1));
808 hist
->n_counters
= hist
->hdata
.intvl
.steps
+ 2;
814 fprintf (dump_file
, "Pow2 counter for tree ");
815 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
816 fprintf (dump_file
, ".\n");
818 hist
->n_counters
= 2;
821 case HIST_TYPE_SINGLE_VALUE
:
824 fprintf (dump_file
, "Single value counter for tree ");
825 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
826 fprintf (dump_file
, ".\n");
828 hist
->n_counters
= 3;
831 case HIST_TYPE_CONST_DELTA
:
834 fprintf (dump_file
, "Constant delta counter for tree ");
835 print_generic_expr (dump_file
, hist
->hvalue
.stmt
, TDF_SLIM
);
836 fprintf (dump_file
, ".\n");
838 hist
->n_counters
= 4;
847 static struct value_prof_hooks tree_value_prof_hooks
= {
848 tree_find_values_to_profile
,
849 tree_value_profile_transformations
853 tree_register_value_prof_hooks (void)
855 value_prof_hooks
= &tree_value_prof_hooks
;
856 gcc_assert (ir_type ());
859 /* IR-independent entry points. */
861 find_values_to_profile (histogram_values
*values
)
863 (value_prof_hooks
->find_values_to_profile
) (values
);
867 value_profile_transformations (void)
869 return (value_prof_hooks
->value_profile_transformations
) ();