00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "rtl.h"
00026 #include "expr.h"
00027 #include "hard-reg-set.h"
00028 #include "basic-block.h"
00029 #include "value-prof.h"
00030 #include "output.h"
00031 #include "flags.h"
00032 #include "insn-config.h"
00033 #include "recog.h"
00034 #include "optabs.h"
00035 #include "regs.h"
00036 #include "ggc.h"
00037 #include "tree-flow.h"
00038 #include "tree-flow-inline.h"
00039 #include "diagnostic.h"
00040 #include "coverage.h"
00041 #include "tree.h"
00042 #include "gcov-io.h"
00043 #include "timevar.h"
00044 #include "tree-pass.h"
00045 #include "toplev.h"
00046
00047 static struct value_prof_hooks *value_prof_hooks;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static tree tree_divmod_fixed_value (tree, tree, tree, tree,
00075 tree, int, gcov_type, gcov_type);
00076 static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
00077 static tree tree_mod_subtract (tree, tree, tree, tree, int, int, int,
00078 gcov_type, gcov_type, gcov_type);
00079 static bool tree_divmod_fixed_value_transform (tree);
00080 static bool tree_mod_pow2_value_transform (tree);
00081 static bool tree_mod_subtract_transform (tree);
00082
00083
00084
00085
00086 static bool
00087 check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
00088 {
00089 if (all != bb_count)
00090 {
00091 location_t * locus;
00092 locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
00093 ? EXPR_LOCUS (stmt)
00094 : &DECL_SOURCE_LOCATION (current_function_decl));
00095 error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
00096 locus, name, (int)all, (int)bb_count);
00097 return true;
00098 }
00099 return false;
00100 }
00101
00102
00103 static bool
00104 tree_value_profile_transformations (void)
00105 {
00106 basic_block bb;
00107 block_stmt_iterator bsi;
00108 bool changed = false;
00109
00110 FOR_EACH_BB (bb)
00111 {
00112
00113 if (!maybe_hot_bb_p (bb))
00114 continue;
00115
00116 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00117 {
00118 tree stmt = bsi_stmt (bsi);
00119 stmt_ann_t ann = get_stmt_ann (stmt);
00120 histogram_value th = ann->histograms;
00121 if (!th)
00122 continue;
00123
00124 if (dump_file)
00125 {
00126 fprintf (dump_file, "Trying transformations on insn ");
00127 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 if (flag_value_profile_transformations
00138 && (tree_mod_subtract_transform (stmt)
00139 || tree_divmod_fixed_value_transform (stmt)
00140 || tree_mod_pow2_value_transform (stmt)))
00141 {
00142 changed = true;
00143
00144 if (bb != bb_for_stmt (stmt))
00145 {
00146 bb = bb_for_stmt (stmt);
00147 bsi = bsi_for_stmt (stmt);
00148 }
00149 }
00150
00151
00152 while (th)
00153 {
00154 free (th->hvalue.counters);
00155 th = th->hvalue.next;
00156 }
00157 ann->histograms = 0;
00158 }
00159 }
00160
00161 if (changed)
00162 {
00163 counts_to_freqs ();
00164 }
00165
00166 return changed;
00167 }
00168
00169
00170
00171
00172
00173
00174 static tree
00175 tree_divmod_fixed_value (tree stmt, tree operation,
00176 tree op1, tree op2, tree value, int prob, gcov_type count,
00177 gcov_type all)
00178 {
00179 tree stmt1, stmt2, stmt3;
00180 tree tmp1, tmp2, tmpv;
00181 tree label_decl1 = create_artificial_label ();
00182 tree label_decl2 = create_artificial_label ();
00183 tree label_decl3 = create_artificial_label ();
00184 tree label1, label2, label3;
00185 tree bb1end, bb2end, bb3end;
00186 basic_block bb, bb2, bb3, bb4;
00187 tree optype = TREE_TYPE (operation);
00188 edge e12, e13, e23, e24, e34;
00189 block_stmt_iterator bsi;
00190
00191 bb = bb_for_stmt (stmt);
00192 bsi = bsi_for_stmt (stmt);
00193
00194 tmpv = create_tmp_var (optype, "PROF");
00195 tmp1 = create_tmp_var (optype, "PROF");
00196 stmt1 = build2 (MODIFY_EXPR, optype, tmpv, fold_convert (optype, value));
00197 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
00198 stmt3 = build3 (COND_EXPR, void_type_node,
00199 build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
00200 build1 (GOTO_EXPR, void_type_node, label_decl2),
00201 build1 (GOTO_EXPR, void_type_node, label_decl1));
00202 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00203 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
00204 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
00205 bb1end = stmt3;
00206
00207 tmp2 = create_tmp_var (optype, "PROF");
00208 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
00209 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
00210 build2 (TREE_CODE (operation), optype, op1, tmpv));
00211 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
00212 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00213 bb2end = stmt1;
00214
00215 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
00216 stmt1 = build2 (MODIFY_EXPR, optype, tmp2,
00217 build2 (TREE_CODE (operation), optype, op1, op2));
00218 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
00219 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00220 bb3end = stmt1;
00221
00222 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
00223 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
00224
00225
00226
00227 e12 = split_block (bb, bb1end);
00228 bb2 = e12->dest;
00229 bb2->count = count;
00230 e23 = split_block (bb2, bb2end);
00231 bb3 = e23->dest;
00232 bb3->count = all - count;
00233 e34 = split_block (bb3, bb3end);
00234 bb4 = e34->dest;
00235 bb4->count = all;
00236
00237 e12->flags &= ~EDGE_FALLTHRU;
00238 e12->flags |= EDGE_FALSE_VALUE;
00239 e12->probability = prob;
00240 e12->count = count;
00241
00242 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
00243 e13->probability = REG_BR_PROB_BASE - prob;
00244 e13->count = all - count;
00245
00246 remove_edge (e23);
00247
00248 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
00249 e24->probability = REG_BR_PROB_BASE;
00250 e24->count = count;
00251
00252 e34->probability = REG_BR_PROB_BASE;
00253 e34->count = all - count;
00254
00255 return tmp2;
00256 }
00257
00258
00259 static bool
00260 tree_divmod_fixed_value_transform (tree stmt)
00261 {
00262 stmt_ann_t ann = get_stmt_ann (stmt);
00263 histogram_value histogram;
00264 enum tree_code code;
00265 gcov_type val, count, all;
00266 tree modify, op, op1, op2, result, value, tree_val;
00267 int prob;
00268
00269 modify = stmt;
00270 if (TREE_CODE (stmt) == RETURN_EXPR
00271 && TREE_OPERAND (stmt, 0)
00272 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
00273 modify = TREE_OPERAND (stmt, 0);
00274 if (TREE_CODE (modify) != MODIFY_EXPR)
00275 return false;
00276 op = TREE_OPERAND (modify, 1);
00277 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
00278 return false;
00279 code = TREE_CODE (op);
00280
00281 if (code != TRUNC_DIV_EXPR && code != TRUNC_MOD_EXPR)
00282 return false;
00283
00284 op1 = TREE_OPERAND (op, 0);
00285 op2 = TREE_OPERAND (op, 1);
00286 if (!ann->histograms)
00287 return false;
00288
00289 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
00290 if (histogram->type == HIST_TYPE_SINGLE_VALUE)
00291 break;
00292
00293 if (!histogram)
00294 return false;
00295
00296 value = histogram->hvalue.value;
00297 val = histogram->hvalue.counters[0];
00298 count = histogram->hvalue.counters[1];
00299 all = histogram->hvalue.counters[2];
00300
00301
00302
00303
00304 if (simple_cst_equal (op2, value) != 1 || 2 * count < all)
00305 return false;
00306
00307 if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
00308 return false;
00309
00310
00311 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
00312
00313 tree_val = build_int_cst_wide (get_gcov_type (),
00314 (unsigned HOST_WIDE_INT) val,
00315 val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
00316 result = tree_divmod_fixed_value (stmt, op, op1, op2, tree_val, prob, count, all);
00317
00318 if (dump_file)
00319 {
00320 fprintf (dump_file, "Div/mod by constant ");
00321 print_generic_expr (dump_file, value, TDF_SLIM);
00322 fprintf (dump_file, "=");
00323 print_generic_expr (dump_file, tree_val, TDF_SLIM);
00324 fprintf (dump_file, " transformation on insn ");
00325 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00326 }
00327
00328 TREE_OPERAND (modify, 1) = result;
00329
00330 return true;
00331 }
00332
00333
00334
00335
00336
00337
00338 static tree
00339 tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
00340 gcov_type count, gcov_type all)
00341 {
00342 tree stmt1, stmt2, stmt3, stmt4;
00343 tree tmp2, tmp3;
00344 tree label_decl1 = create_artificial_label ();
00345 tree label_decl2 = create_artificial_label ();
00346 tree label_decl3 = create_artificial_label ();
00347 tree label1, label2, label3;
00348 tree bb1end, bb2end, bb3end;
00349 basic_block bb, bb2, bb3, bb4;
00350 tree optype = TREE_TYPE (operation);
00351 edge e12, e13, e23, e24, e34;
00352 block_stmt_iterator bsi;
00353 tree result = create_tmp_var (optype, "PROF");
00354
00355 bb = bb_for_stmt (stmt);
00356 bsi = bsi_for_stmt (stmt);
00357
00358 tmp2 = create_tmp_var (optype, "PROF");
00359 tmp3 = create_tmp_var (optype, "PROF");
00360 stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
00361 build2 (PLUS_EXPR, optype, op2, build_int_cst (optype, -1)));
00362 stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
00363 build2 (BIT_AND_EXPR, optype, tmp2, op2));
00364 stmt4 = build3 (COND_EXPR, void_type_node,
00365 build2 (NE_EXPR, boolean_type_node,
00366 tmp3, build_int_cst (optype, 0)),
00367 build1 (GOTO_EXPR, void_type_node, label_decl2),
00368 build1 (GOTO_EXPR, void_type_node, label_decl1));
00369 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
00370 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
00371 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
00372 bb1end = stmt4;
00373
00374
00375 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
00376 stmt1 = build2 (MODIFY_EXPR, optype, result,
00377 build2 (BIT_AND_EXPR, optype, op1, tmp2));
00378 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
00379 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00380 bb2end = stmt1;
00381
00382 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
00383 stmt1 = build2 (MODIFY_EXPR, optype, result,
00384 build2 (TREE_CODE (operation), optype, op1, op2));
00385 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
00386 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00387 bb3end = stmt1;
00388
00389 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
00390 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
00391
00392
00393
00394 e12 = split_block (bb, bb1end);
00395 bb2 = e12->dest;
00396 bb2->count = count;
00397 e23 = split_block (bb2, bb2end);
00398 bb3 = e23->dest;
00399 bb3->count = all - count;
00400 e34 = split_block (bb3, bb3end);
00401 bb4 = e34->dest;
00402 bb4->count = all;
00403
00404 e12->flags &= ~EDGE_FALLTHRU;
00405 e12->flags |= EDGE_FALSE_VALUE;
00406 e12->probability = prob;
00407 e12->count = count;
00408
00409 e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
00410 e13->probability = REG_BR_PROB_BASE - prob;
00411 e13->count = all - count;
00412
00413 remove_edge (e23);
00414
00415 e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
00416 e24->probability = REG_BR_PROB_BASE;
00417 e24->count = count;
00418
00419 e34->probability = REG_BR_PROB_BASE;
00420 e34->count = all - count;
00421
00422 return result;
00423 }
00424
00425
00426 static bool
00427 tree_mod_pow2_value_transform (tree stmt)
00428 {
00429 stmt_ann_t ann = get_stmt_ann (stmt);
00430 histogram_value histogram;
00431 enum tree_code code;
00432 gcov_type count, wrong_values, all;
00433 tree modify, op, op1, op2, result, value;
00434 int prob;
00435
00436 modify = stmt;
00437 if (TREE_CODE (stmt) == RETURN_EXPR
00438 && TREE_OPERAND (stmt, 0)
00439 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
00440 modify = TREE_OPERAND (stmt, 0);
00441 if (TREE_CODE (modify) != MODIFY_EXPR)
00442 return false;
00443 op = TREE_OPERAND (modify, 1);
00444 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
00445 return false;
00446 code = TREE_CODE (op);
00447
00448 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
00449 return false;
00450
00451 op1 = TREE_OPERAND (op, 0);
00452 op2 = TREE_OPERAND (op, 1);
00453 if (!ann->histograms)
00454 return false;
00455
00456 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
00457 if (histogram->type == HIST_TYPE_POW2)
00458 break;
00459
00460 if (!histogram)
00461 return false;
00462
00463 value = histogram->hvalue.value;
00464 wrong_values = histogram->hvalue.counters[0];
00465 count = histogram->hvalue.counters[1];
00466
00467
00468 if (simple_cst_equal (op2, value) != 1 || count < wrong_values)
00469 return false;
00470
00471 if (dump_file)
00472 {
00473 fprintf (dump_file, "Mod power of 2 transformation on insn ");
00474 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00475 }
00476
00477
00478 all = count + wrong_values;
00479 if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
00480 return false;
00481
00482 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
00483
00484 result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
00485
00486 TREE_OPERAND (modify, 1) = result;
00487
00488 return true;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 static tree
00502 tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
00503 int prob1, int prob2, int ncounts,
00504 gcov_type count1, gcov_type count2, gcov_type all)
00505 {
00506 tree stmt1, stmt2, stmt3;
00507 tree tmp1;
00508 tree label_decl1 = create_artificial_label ();
00509 tree label_decl2 = create_artificial_label ();
00510 tree label_decl3 = create_artificial_label ();
00511 tree label1, label2, label3;
00512 tree bb1end, bb2end = NULL_TREE, bb3end;
00513 basic_block bb, bb2, bb3, bb4;
00514 tree optype = TREE_TYPE (operation);
00515 edge e12, e23 = 0, e24, e34, e14;
00516 block_stmt_iterator bsi;
00517 tree result = create_tmp_var (optype, "PROF");
00518
00519 bb = bb_for_stmt (stmt);
00520 bsi = bsi_for_stmt (stmt);
00521
00522 tmp1 = create_tmp_var (optype, "PROF");
00523 stmt1 = build2 (MODIFY_EXPR, optype, result, op1);
00524 stmt2 = build2 (MODIFY_EXPR, optype, tmp1, op2);
00525 stmt3 = build3 (COND_EXPR, void_type_node,
00526 build2 (LT_EXPR, boolean_type_node, result, tmp1),
00527 build1 (GOTO_EXPR, void_type_node, label_decl3),
00528 build1 (GOTO_EXPR, void_type_node,
00529 ncounts ? label_decl1 : label_decl2));
00530 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00531 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
00532 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
00533 bb1end = stmt3;
00534
00535 if (ncounts)
00536 {
00537 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
00538 stmt1 = build2 (MODIFY_EXPR, optype, result,
00539 build2 (MINUS_EXPR, optype, result, tmp1));
00540 stmt2 = build3 (COND_EXPR, void_type_node,
00541 build2 (LT_EXPR, boolean_type_node, result, tmp1),
00542 build1 (GOTO_EXPR, void_type_node, label_decl3),
00543 build1 (GOTO_EXPR, void_type_node, label_decl2));
00544 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
00545 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00546 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
00547 bb2end = stmt2;
00548 }
00549
00550
00551 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
00552 stmt1 = build2 (MODIFY_EXPR, optype, result,
00553 build2 (TREE_CODE (operation), optype, result, tmp1));
00554 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
00555 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
00556 bb3end = stmt1;
00557
00558 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
00559 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
00560
00561
00562
00563
00564
00565 e12 = split_block (bb, bb1end);
00566 bb2 = e12->dest;
00567 bb2->count = all - count1;
00568
00569 if (ncounts)
00570 {
00571 e23 = split_block (bb2, bb2end);
00572 bb3 = e23->dest;
00573 bb3->count = all - count1 - count2;
00574 }
00575
00576 e34 = split_block (ncounts ? bb3 : bb2, bb3end);
00577 bb4 = e34->dest;
00578 bb4->count = all;
00579
00580 e12->flags &= ~EDGE_FALLTHRU;
00581 e12->flags |= EDGE_FALSE_VALUE;
00582 e12->probability = REG_BR_PROB_BASE - prob1;
00583 e12->count = all - count1;
00584
00585 e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
00586 e14->probability = prob1;
00587 e14->count = count1;
00588
00589 if (ncounts)
00590 {
00591 e23->flags &= ~EDGE_FALLTHRU;
00592 e23->flags |= EDGE_FALSE_VALUE;
00593 e23->count = all - count1 - count2;
00594 e23->probability = REG_BR_PROB_BASE - prob2;
00595
00596 e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
00597 e24->probability = prob2;
00598 e24->count = count2;
00599 }
00600
00601 e34->probability = REG_BR_PROB_BASE;
00602 e34->count = all - count1 - count2;
00603
00604 return result;
00605 }
00606
00607
00608 static bool
00609 tree_mod_subtract_transform (tree stmt)
00610 {
00611 stmt_ann_t ann = get_stmt_ann (stmt);
00612 histogram_value histogram;
00613 enum tree_code code;
00614 gcov_type count, wrong_values, all;
00615 tree modify, op, op1, op2, result, value;
00616 int prob1, prob2;
00617 unsigned int i;
00618
00619 modify = stmt;
00620 if (TREE_CODE (stmt) == RETURN_EXPR
00621 && TREE_OPERAND (stmt, 0)
00622 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
00623 modify = TREE_OPERAND (stmt, 0);
00624 if (TREE_CODE (modify) != MODIFY_EXPR)
00625 return false;
00626 op = TREE_OPERAND (modify, 1);
00627 if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
00628 return false;
00629 code = TREE_CODE (op);
00630
00631 if (code != TRUNC_MOD_EXPR || !TYPE_UNSIGNED (TREE_TYPE (op)))
00632 return false;
00633
00634 op1 = TREE_OPERAND (op, 0);
00635 op2 = TREE_OPERAND (op, 1);
00636 if (!ann->histograms)
00637 return false;
00638
00639 for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
00640 if (histogram->type == HIST_TYPE_INTERVAL)
00641 break;
00642
00643 if (!histogram)
00644 return false;
00645
00646 value = histogram->hvalue.value;
00647 all = 0;
00648 wrong_values = 0;
00649 for (i = 0; i < histogram->hdata.intvl.steps; i++)
00650 all += histogram->hvalue.counters[i];
00651
00652 wrong_values += histogram->hvalue.counters[i];
00653 wrong_values += histogram->hvalue.counters[i+1];
00654 all += wrong_values;
00655
00656
00657 if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
00658 return false;
00659
00660
00661
00662 count = 0;
00663 for (i = 0; i < histogram->hdata.intvl.steps; i++)
00664 {
00665 count += histogram->hvalue.counters[i];
00666 if (count * 2 >= all)
00667 break;
00668 }
00669 if (i == histogram->hdata.intvl.steps)
00670 return false;
00671
00672 if (dump_file)
00673 {
00674 fprintf (dump_file, "Mod subtract transformation on insn ");
00675 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00676 }
00677
00678
00679 prob1 = (histogram->hvalue.counters[0] * REG_BR_PROB_BASE + all / 2) / all;
00680 prob2 = (histogram->hvalue.counters[1] * REG_BR_PROB_BASE + all / 2) / all;
00681
00682
00683
00684 result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
00685 histogram->hvalue.counters[0],
00686 histogram->hvalue.counters[1], all);
00687
00688 TREE_OPERAND (modify, 1) = result;
00689
00690 return true;
00691 }
00692
00693 struct value_prof_hooks {
00694
00695 void (*find_values_to_profile) (histogram_values *);
00696
00697
00698
00699 bool (*value_profile_transformations) (void);
00700 };
00701
00702
00703
00704 static void
00705 tree_divmod_values_to_profile (tree stmt, histogram_values *values)
00706 {
00707 tree assign, lhs, rhs, divisor, op0, type;
00708 histogram_value hist;
00709
00710 if (TREE_CODE (stmt) == RETURN_EXPR)
00711 assign = TREE_OPERAND (stmt, 0);
00712 else
00713 assign = stmt;
00714
00715 if (!assign
00716 || TREE_CODE (assign) != MODIFY_EXPR)
00717 return;
00718 lhs = TREE_OPERAND (assign, 0);
00719 type = TREE_TYPE (lhs);
00720 if (!INTEGRAL_TYPE_P (type))
00721 return;
00722
00723 rhs = TREE_OPERAND (assign, 1);
00724 switch (TREE_CODE (rhs))
00725 {
00726 case TRUNC_DIV_EXPR:
00727 case TRUNC_MOD_EXPR:
00728 divisor = TREE_OPERAND (rhs, 1);
00729 op0 = TREE_OPERAND (rhs, 0);
00730
00731 VEC_reserve (histogram_value, heap, *values, 3);
00732
00733 if (is_gimple_reg (divisor))
00734 {
00735
00736
00737 hist = ggc_alloc (sizeof (*hist));
00738 hist->hvalue.value = divisor;
00739 hist->hvalue.stmt = stmt;
00740 hist->type = HIST_TYPE_SINGLE_VALUE;
00741 VEC_quick_push (histogram_value, *values, hist);
00742 }
00743
00744
00745
00746 if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
00747 && TYPE_UNSIGNED (type))
00748 {
00749
00750 hist = ggc_alloc (sizeof (*hist));
00751 hist->hvalue.value = divisor;
00752 hist->hvalue.stmt = stmt;
00753 hist->type = HIST_TYPE_POW2;
00754 VEC_quick_push (histogram_value, *values, hist);
00755
00756 hist = ggc_alloc (sizeof (*hist));
00757 hist->hvalue.stmt = stmt;
00758 hist->hvalue.value
00759 = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
00760 hist->type = HIST_TYPE_INTERVAL;
00761 hist->hdata.intvl.int_start = 0;
00762 hist->hdata.intvl.steps = 2;
00763 VEC_quick_push (histogram_value, *values, hist);
00764 }
00765 return;
00766
00767 default:
00768 return;
00769 }
00770 }
00771
00772
00773
00774
00775 static void
00776 tree_values_to_profile (tree stmt, histogram_values *values)
00777 {
00778 if (flag_value_profile_transformations)
00779 tree_divmod_values_to_profile (stmt, values);
00780 }
00781
00782 static void
00783 tree_find_values_to_profile (histogram_values *values)
00784 {
00785 basic_block bb;
00786 block_stmt_iterator bsi;
00787 unsigned i;
00788 histogram_value hist;
00789
00790 *values = NULL;
00791 FOR_EACH_BB (bb)
00792 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00793 tree_values_to_profile (bsi_stmt (bsi), values);
00794
00795 for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
00796 {
00797 switch (hist->type)
00798 {
00799 case HIST_TYPE_INTERVAL:
00800 if (dump_file)
00801 {
00802 fprintf (dump_file, "Interval counter for tree ");
00803 print_generic_expr (dump_file, hist->hvalue.stmt,
00804 TDF_SLIM);
00805 fprintf (dump_file, ", range %d -- %d.\n",
00806 hist->hdata.intvl.int_start,
00807 (hist->hdata.intvl.int_start
00808 + hist->hdata.intvl.steps - 1));
00809 }
00810 hist->n_counters = hist->hdata.intvl.steps + 2;
00811 break;
00812
00813 case HIST_TYPE_POW2:
00814 if (dump_file)
00815 {
00816 fprintf (dump_file, "Pow2 counter for tree ");
00817 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
00818 fprintf (dump_file, ".\n");
00819 }
00820 hist->n_counters = 2;
00821 break;
00822
00823 case HIST_TYPE_SINGLE_VALUE:
00824 if (dump_file)
00825 {
00826 fprintf (dump_file, "Single value counter for tree ");
00827 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
00828 fprintf (dump_file, ".\n");
00829 }
00830 hist->n_counters = 3;
00831 break;
00832
00833 case HIST_TYPE_CONST_DELTA:
00834 if (dump_file)
00835 {
00836 fprintf (dump_file, "Constant delta counter for tree ");
00837 print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
00838 fprintf (dump_file, ".\n");
00839 }
00840 hist->n_counters = 4;
00841 break;
00842
00843 default:
00844 gcc_unreachable ();
00845 }
00846 }
00847 }
00848
00849 static struct value_prof_hooks tree_value_prof_hooks = {
00850 tree_find_values_to_profile,
00851 tree_value_profile_transformations
00852 };
00853
00854 void
00855 tree_register_value_prof_hooks (void)
00856 {
00857 value_prof_hooks = &tree_value_prof_hooks;
00858 gcc_assert (ir_type ());
00859 }
00860
00861
00862 void
00863 find_values_to_profile (histogram_values *values)
00864 {
00865 (value_prof_hooks->find_values_to_profile) (values);
00866 }
00867
00868 bool
00869 value_profile_transformations (void)
00870 {
00871 return (value_prof_hooks->value_profile_transformations) ();
00872 }
00873
00874