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
00038 static struct value_prof_hooks *value_prof_hooks;
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #ifndef NOPREFETCH_RANGE_MIN
00071 #define NOPREFETCH_RANGE_MIN (-16)
00072 #endif
00073 #ifndef NOPREFETCH_RANGE_MAX
00074 #define NOPREFETCH_RANGE_MAX 32
00075 #endif
00076
00077 static void insn_divmod_values_to_profile (rtx, histogram_values *);
00078 #ifdef HAVE_prefetch
00079 static bool insn_prefetch_values_to_profile (rtx, histogram_values *);
00080 static int find_mem_reference_1 (rtx *, void *);
00081 static void find_mem_reference_2 (rtx, rtx, void *);
00082 static bool find_mem_reference (rtx, rtx *, int *);
00083 #endif
00084
00085 static void insn_values_to_profile (rtx, histogram_values *);
00086 static rtx gen_divmod_fixed_value (enum machine_mode, enum rtx_code, rtx, rtx,
00087 rtx, gcov_type, int);
00088 static rtx gen_mod_pow2 (enum machine_mode, enum rtx_code, rtx, rtx, rtx, int);
00089 static rtx gen_mod_subtract (enum machine_mode, enum rtx_code, rtx, rtx, rtx,
00090 int, int, int);
00091 #ifdef HAVE_prefetch
00092 static rtx gen_speculative_prefetch (rtx, gcov_type, int);
00093 #endif
00094 static bool divmod_fixed_value_transform (rtx insn);
00095 static bool mod_pow2_value_transform (rtx);
00096 static bool mod_subtract_transform (rtx);
00097 #ifdef HAVE_prefetch
00098 static bool speculative_prefetching_transform (rtx);
00099 #endif
00100
00101
00102
00103 static void
00104 insn_divmod_values_to_profile (rtx insn, histogram_values *values)
00105 {
00106 rtx set, set_src, op1, op2;
00107 enum machine_mode mode;
00108 histogram_value hist;
00109
00110 if (!INSN_P (insn))
00111 return;
00112
00113 set = single_set (insn);
00114 if (!set)
00115 return;
00116
00117 mode = GET_MODE (SET_DEST (set));
00118 if (!INTEGRAL_MODE_P (mode))
00119 return;
00120
00121 set_src = SET_SRC (set);
00122 switch (GET_CODE (set_src))
00123 {
00124 case DIV:
00125 case MOD:
00126 case UDIV:
00127 case UMOD:
00128 op1 = XEXP (set_src, 0);
00129 op2 = XEXP (set_src, 1);
00130 if (side_effects_p (op2))
00131 return;
00132
00133
00134 if ((GET_CODE (set_src) == UMOD) && !CONSTANT_P (op2))
00135 {
00136 hist = ggc_alloc (sizeof (*hist));
00137 hist->value = op2;
00138 hist->seq = NULL_RTX;
00139 hist->mode = mode;
00140 hist->insn = insn;
00141 hist->type = HIST_TYPE_POW2;
00142 hist->hdata.pow2.may_be_other = 1;
00143 VEC_safe_push (histogram_value, *values, hist);
00144 }
00145
00146
00147 if (!CONSTANT_P (op2))
00148 {
00149 hist = ggc_alloc (sizeof (*hist));
00150 hist->value = op2;
00151 hist->mode = mode;
00152 hist->seq = NULL_RTX;
00153 hist->insn = insn;
00154 hist->type = HIST_TYPE_SINGLE_VALUE;
00155 VEC_safe_push (histogram_value, *values, hist);
00156 }
00157
00158
00159
00160 if (GET_CODE (set_src) == UMOD && !side_effects_p (op1))
00161 {
00162 rtx tmp;
00163
00164 hist = ggc_alloc (sizeof (*hist));
00165 start_sequence ();
00166 tmp = simplify_gen_binary (DIV, mode, copy_rtx (op1), copy_rtx (op2));
00167 hist->value = force_operand (tmp, NULL_RTX);
00168 hist->seq = get_insns ();
00169 end_sequence ();
00170 hist->mode = mode;
00171 hist->insn = insn;
00172 hist->type = HIST_TYPE_INTERVAL;
00173 hist->hdata.intvl.int_start = 0;
00174 hist->hdata.intvl.steps = 2;
00175 hist->hdata.intvl.may_be_less = 1;
00176 hist->hdata.intvl.may_be_more = 1;
00177 VEC_safe_push (histogram_value, *values, hist);
00178 }
00179 return;
00180
00181 default:
00182 return;
00183 }
00184 }
00185
00186 #ifdef HAVE_prefetch
00187
00188
00189
00190
00191
00192
00193 static int
00194 find_mem_reference_1 (rtx *expr, void *ret)
00195 {
00196 rtx *mem = ret;
00197
00198 if (GET_CODE (*expr) == MEM)
00199 {
00200 *mem = *expr;
00201 return 1;
00202 }
00203 return 0;
00204 }
00205
00206
00207
00208
00209
00210 static int fmr2_write;
00211 static void
00212 find_mem_reference_2 (rtx expr, rtx pat ATTRIBUTE_UNUSED, void *mem)
00213 {
00214 if (expr == mem)
00215 fmr2_write = true;
00216 }
00217
00218
00219
00220
00221
00222 static bool
00223 find_mem_reference (rtx insn, rtx *mem, int *write)
00224 {
00225 *mem = NULL_RTX;
00226 for_each_rtx (&PATTERN (insn), find_mem_reference_1, mem);
00227
00228 if (!*mem)
00229 return false;
00230
00231 fmr2_write = false;
00232 note_stores (PATTERN (insn), find_mem_reference_2, *mem);
00233 *write = fmr2_write;
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241 static bool
00242 insn_prefetch_values_to_profile (rtx insn, histogram_values *values)
00243 {
00244 rtx mem, address;
00245 int write;
00246 histogram_value hist;
00247
00248
00249 if (GET_CODE (insn) != INSN)
00250 return false;
00251
00252 if (!find_mem_reference (insn, &mem, &write))
00253 return false;
00254
00255 address = XEXP (mem, 0);
00256 if (side_effects_p (address))
00257 return false;
00258
00259 if (CONSTANT_P (address))
00260 return false;
00261
00262 hist = ggc_alloc (sizeof (*hist));
00263 hist->value = address;
00264 hist->mode = GET_MODE (address);
00265 hist->seq = NULL_RTX;
00266 hist->insn = insn;
00267 hist->type = HIST_TYPE_CONST_DELTA;
00268 VEC_safe_push (histogram_value, *values, hist);
00269
00270 return true;
00271 }
00272 #endif
00273
00274
00275 static void
00276 insn_values_to_profile (rtx insn, histogram_values *values)
00277 {
00278 if (flag_value_profile_transformations)
00279 insn_divmod_values_to_profile (insn, values);
00280
00281 #ifdef HAVE_prefetch
00282 if (flag_speculative_prefetching)
00283 insn_prefetch_values_to_profile (insn, values);
00284 #endif
00285 }
00286
00287
00288 static void
00289 rtl_find_values_to_profile (histogram_values *values)
00290 {
00291 rtx insn;
00292 unsigned i, libcall_level;
00293
00294 life_analysis (NULL, PROP_DEATH_NOTES);
00295
00296 *values = VEC_alloc (histogram_value, 0);
00297 libcall_level = 0;
00298 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00299 {
00300 if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
00301 libcall_level++;
00302
00303
00304
00305
00306 if (!libcall_level)
00307 insn_values_to_profile (insn, values);
00308
00309 if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
00310 {
00311 gcc_assert (libcall_level > 0);
00312 libcall_level--;
00313 }
00314 }
00315 gcc_assert (libcall_level == 0);
00316
00317 for (i = 0; i < VEC_length (histogram_value, *values); i++)
00318 {
00319 histogram_value hist = VEC_index (histogram_value, *values, i);
00320
00321 switch (hist->type)
00322 {
00323 case HIST_TYPE_INTERVAL:
00324 if (dump_file)
00325 fprintf (dump_file,
00326 "Interval counter for insn %d, range %d -- %d.\n",
00327 INSN_UID ((rtx)hist->insn),
00328 hist->hdata.intvl.int_start,
00329 (hist->hdata.intvl.int_start
00330 + hist->hdata.intvl.steps - 1));
00331 hist->n_counters = hist->hdata.intvl.steps +
00332 (hist->hdata.intvl.may_be_less ? 1 : 0) +
00333 (hist->hdata.intvl.may_be_more ? 1 : 0);
00334 break;
00335
00336 case HIST_TYPE_POW2:
00337 if (dump_file)
00338 fprintf (dump_file,
00339 "Pow2 counter for insn %d.\n",
00340 INSN_UID ((rtx)hist->insn));
00341 hist->n_counters
00342 = GET_MODE_BITSIZE (hist->mode)
00343 + (hist->hdata.pow2.may_be_other ? 1 : 0);
00344 break;
00345
00346 case HIST_TYPE_SINGLE_VALUE:
00347 if (dump_file)
00348 fprintf (dump_file,
00349 "Single value counter for insn %d.\n",
00350 INSN_UID ((rtx)hist->insn));
00351 hist->n_counters = 3;
00352 break;
00353
00354 case HIST_TYPE_CONST_DELTA:
00355 if (dump_file)
00356 fprintf (dump_file,
00357 "Constant delta counter for insn %d.\n",
00358 INSN_UID ((rtx)hist->insn));
00359 hist->n_counters = 4;
00360 break;
00361
00362 default:
00363 abort ();
00364 }
00365 }
00366 allocate_reg_info (max_reg_num (), FALSE, FALSE);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 static bool
00467 rtl_value_profile_transformations (void)
00468 {
00469 rtx insn, next;
00470 int changed = false;
00471
00472 for (insn = get_insns (); insn; insn = next)
00473 {
00474 next = NEXT_INSN (insn);
00475
00476 if (!INSN_P (insn))
00477 continue;
00478
00479
00480 if (!find_reg_note (insn, REG_VALUE_PROFILE, 0))
00481 continue;
00482
00483
00484 if (!maybe_hot_bb_p (BLOCK_FOR_INSN (insn)))
00485 continue;
00486
00487 if (dump_file)
00488 {
00489 fprintf (dump_file, "Trying transformations on insn %d\n",
00490 INSN_UID (insn));
00491 print_rtl_single (dump_file, insn);
00492 }
00493
00494
00495 if (flag_value_profile_transformations
00496 && (mod_subtract_transform (insn)
00497 || divmod_fixed_value_transform (insn)
00498 || mod_pow2_value_transform (insn)))
00499 changed = true;
00500 #ifdef HAVE_prefetch
00501 if (flag_speculative_prefetching
00502 && speculative_prefetching_transform (insn))
00503 changed = true;
00504 #endif
00505 }
00506
00507 if (changed)
00508 {
00509 commit_edge_insertions ();
00510 allocate_reg_info (max_reg_num (), FALSE, FALSE);
00511 }
00512
00513 return changed;
00514 }
00515
00516
00517
00518
00519 static rtx
00520 gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
00521 rtx target, rtx op1, rtx op2, gcov_type value,
00522 int prob)
00523 {
00524 rtx tmp, tmp1, jump;
00525 rtx neq_label = gen_label_rtx ();
00526 rtx end_label = gen_label_rtx ();
00527 rtx sequence;
00528
00529 start_sequence ();
00530
00531 if (!REG_P (op2))
00532 {
00533 tmp = gen_reg_rtx (mode);
00534 emit_move_insn (tmp, copy_rtx (op2));
00535 }
00536 else
00537 tmp = op2;
00538
00539 do_compare_rtx_and_jump (tmp, GEN_INT (value), NE, 0, mode, NULL_RTX,
00540 NULL_RTX, neq_label);
00541
00542
00543 jump = get_last_insn ();
00544 REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
00545 GEN_INT (REG_BR_PROB_BASE - prob),
00546 REG_NOTES (jump));
00547
00548 tmp1 = simplify_gen_binary (operation, mode,
00549 copy_rtx (op1), GEN_INT (value));
00550 tmp1 = force_operand (tmp1, target);
00551 if (tmp1 != target)
00552 emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
00553
00554 emit_jump_insn (gen_jump (end_label));
00555 emit_barrier ();
00556
00557 emit_label (neq_label);
00558 tmp1 = simplify_gen_binary (operation, mode,
00559 copy_rtx (op1), copy_rtx (tmp));
00560 tmp1 = force_operand (tmp1, target);
00561 if (tmp1 != target)
00562 emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
00563
00564 emit_label (end_label);
00565
00566 sequence = get_insns ();
00567 end_sequence ();
00568 rebuild_jump_labels (sequence);
00569 return sequence;
00570 }
00571
00572
00573 static bool
00574 divmod_fixed_value_transform (rtx insn)
00575 {
00576 rtx set, set_src, set_dest, op1, op2, value, histogram;
00577 enum rtx_code code;
00578 enum machine_mode mode;
00579 gcov_type val, count, all;
00580 edge e;
00581 int prob;
00582
00583 set = single_set (insn);
00584 if (!set)
00585 return false;
00586
00587 set_src = SET_SRC (set);
00588 set_dest = SET_DEST (set);
00589 code = GET_CODE (set_src);
00590 mode = GET_MODE (set_dest);
00591
00592 if (code != DIV && code != MOD && code != UDIV && code != UMOD)
00593 return false;
00594 op1 = XEXP (set_src, false);
00595 op2 = XEXP (set_src, 1);
00596
00597 for (histogram = REG_NOTES (insn);
00598 histogram;
00599 histogram = XEXP (histogram, 1))
00600 if (REG_NOTE_KIND (histogram) == REG_VALUE_PROFILE
00601 && XEXP (XEXP (histogram, 0), 0) == GEN_INT (HIST_TYPE_SINGLE_VALUE))
00602 break;
00603
00604 if (!histogram)
00605 return false;
00606
00607 histogram = XEXP (XEXP (histogram, 0), 1);
00608 value = XEXP (histogram, 0);
00609 histogram = XEXP (histogram, 1);
00610 val = INTVAL (XEXP (histogram, 0));
00611 histogram = XEXP (histogram, 1);
00612 count = INTVAL (XEXP (histogram, 0));
00613 histogram = XEXP (histogram, 1);
00614 all = INTVAL (XEXP (histogram, 0));
00615
00616
00617
00618
00619 if (!rtx_equal_p (op2, value) || 2 * count < all)
00620 return false;
00621
00622 if (dump_file)
00623 fprintf (dump_file, "Div/mod by constant transformation on insn %d\n",
00624 INSN_UID (insn));
00625
00626
00627 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
00628
00629 e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
00630 delete_insn (insn);
00631
00632 insert_insn_on_edge (
00633 gen_divmod_fixed_value (mode, code, set_dest,
00634 op1, op2, val, prob), e);
00635
00636 return true;
00637 }
00638
00639
00640
00641 static rtx
00642 gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
00643 rtx op1, rtx op2, int prob)
00644 {
00645 rtx tmp, tmp1, tmp2, tmp3, jump;
00646 rtx neq_label = gen_label_rtx ();
00647 rtx end_label = gen_label_rtx ();
00648 rtx sequence;
00649
00650 start_sequence ();
00651
00652 if (!REG_P (op2))
00653 {
00654 tmp = gen_reg_rtx (mode);
00655 emit_move_insn (tmp, copy_rtx (op2));
00656 }
00657 else
00658 tmp = op2;
00659
00660 tmp1 = expand_simple_binop (mode, PLUS, tmp, constm1_rtx, NULL_RTX,
00661 0, OPTAB_WIDEN);
00662 tmp2 = expand_simple_binop (mode, AND, tmp, tmp1, NULL_RTX,
00663 0, OPTAB_WIDEN);
00664 do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
00665 NULL_RTX, neq_label);
00666
00667
00668 jump = get_last_insn ();
00669 REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
00670 GEN_INT (REG_BR_PROB_BASE - prob),
00671 REG_NOTES (jump));
00672
00673 tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
00674 0, OPTAB_WIDEN);
00675 if (tmp3 != target)
00676 emit_move_insn (copy_rtx (target), tmp3);
00677 emit_jump_insn (gen_jump (end_label));
00678 emit_barrier ();
00679
00680 emit_label (neq_label);
00681 tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), copy_rtx (tmp));
00682 tmp1 = force_operand (tmp1, target);
00683 if (tmp1 != target)
00684 emit_move_insn (target, tmp1);
00685
00686 emit_label (end_label);
00687
00688 sequence = get_insns ();
00689 end_sequence ();
00690 rebuild_jump_labels (sequence);
00691 return sequence;
00692 }
00693
00694
00695 static bool
00696 mod_pow2_value_transform (rtx insn)
00697 {
00698 rtx set, set_src, set_dest, op1, op2, value, histogram;
00699 enum rtx_code code;
00700 enum machine_mode mode;
00701 gcov_type wrong_values, count;
00702 edge e;
00703 int i, all, prob;
00704
00705 set = single_set (insn);
00706 if (!set)
00707 return false;
00708
00709 set_src = SET_SRC (set);
00710 set_dest = SET_DEST (set);
00711 code = GET_CODE (set_src);
00712 mode = GET_MODE (set_dest);
00713
00714 if (code != UMOD)
00715 return false;
00716 op1 = XEXP (set_src, 0);
00717 op2 = XEXP (set_src, 1);
00718
00719 for (histogram = REG_NOTES (insn);
00720 histogram;
00721 histogram = XEXP (histogram, 1))
00722 if (REG_NOTE_KIND (histogram) == REG_VALUE_PROFILE
00723 && XEXP (XEXP (histogram, 0), 0) == GEN_INT (HIST_TYPE_POW2))
00724 break;
00725
00726 if (!histogram)
00727 return false;
00728
00729 histogram = XEXP (XEXP (histogram, 0), 1);
00730 value = XEXP (histogram, 0);
00731 histogram = XEXP (histogram, 1);
00732 wrong_values =INTVAL (XEXP (histogram, 0));
00733 histogram = XEXP (histogram, 1);
00734
00735 count = 0;
00736 for (i = 0; i < GET_MODE_BITSIZE (mode); i++)
00737 {
00738 count += INTVAL (XEXP (histogram, 0));
00739 histogram = XEXP (histogram, 1);
00740 }
00741
00742 if (!rtx_equal_p (op2, value))
00743 return false;
00744
00745
00746 if (count < wrong_values)
00747 return false;
00748
00749 if (dump_file)
00750 fprintf (dump_file, "Mod power of 2 transformation on insn %d\n",
00751 INSN_UID (insn));
00752
00753
00754 all = count + wrong_values;
00755 prob = (count * REG_BR_PROB_BASE + all / 2) / all;
00756
00757 e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
00758 delete_insn (insn);
00759
00760 insert_insn_on_edge (
00761 gen_mod_pow2 (mode, code, set_dest, op1, op2, prob), e);
00762
00763 return true;
00764 }
00765
00766
00767
00768
00769 static rtx
00770 gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
00771 rtx target, rtx op1, rtx op2, int sub, int prob1, int prob2)
00772 {
00773 rtx tmp, tmp1, jump;
00774 rtx end_label = gen_label_rtx ();
00775 rtx sequence;
00776 int i;
00777
00778 start_sequence ();
00779
00780 if (!REG_P (op2))
00781 {
00782 tmp = gen_reg_rtx (mode);
00783 emit_move_insn (tmp, copy_rtx (op2));
00784 }
00785 else
00786 tmp = op2;
00787
00788 emit_move_insn (target, copy_rtx (op1));
00789 do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
00790 NULL_RTX, end_label);
00791
00792
00793 jump = get_last_insn ();
00794 REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
00795 GEN_INT (prob1), REG_NOTES (jump));
00796
00797 for (i = 0; i < sub; i++)
00798 {
00799 tmp1 = expand_simple_binop (mode, MINUS, target, tmp, target,
00800 0, OPTAB_WIDEN);
00801 if (tmp1 != target)
00802 emit_move_insn (target, tmp1);
00803 do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
00804 NULL_RTX, end_label);
00805
00806
00807 jump = get_last_insn ();
00808 REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
00809 GEN_INT (prob2), REG_NOTES (jump));
00810 }
00811
00812 tmp1 = simplify_gen_binary (operation, mode, copy_rtx (target), copy_rtx (tmp));
00813 tmp1 = force_operand (tmp1, target);
00814 if (tmp1 != target)
00815 emit_move_insn (target, tmp1);
00816
00817 emit_label (end_label);
00818
00819 sequence = get_insns ();
00820 end_sequence ();
00821 rebuild_jump_labels (sequence);
00822 return sequence;
00823 }
00824
00825
00826 static bool
00827 mod_subtract_transform (rtx insn)
00828 {
00829 rtx set, set_src, set_dest, op1, op2, value, histogram;
00830 enum rtx_code code;
00831 enum machine_mode mode;
00832 gcov_type wrong_values, counts[2], count, all;
00833 edge e;
00834 int i, prob1, prob2;
00835
00836 set = single_set (insn);
00837 if (!set)
00838 return false;
00839
00840 set_src = SET_SRC (set);
00841 set_dest = SET_DEST (set);
00842 code = GET_CODE (set_src);
00843 mode = GET_MODE (set_dest);
00844
00845 if (code != UMOD)
00846 return false;
00847 op1 = XEXP (set_src, 0);
00848 op2 = XEXP (set_src, 1);
00849
00850 for (histogram = REG_NOTES (insn);
00851 histogram;
00852 histogram = XEXP (histogram, 1))
00853 if (REG_NOTE_KIND (histogram) == REG_VALUE_PROFILE
00854 && XEXP (XEXP (histogram, 0), 0) == GEN_INT (HIST_TYPE_INTERVAL))
00855 break;
00856
00857 if (!histogram)
00858 return false;
00859
00860 histogram = XEXP (XEXP (histogram, 0), 1);
00861 value = XEXP (histogram, 0);
00862 histogram = XEXP (histogram, 1);
00863
00864 all = 0;
00865 for (i = 0; i < 2; i++)
00866 {
00867 counts[i] = INTVAL (XEXP (histogram, 0));
00868 all += counts[i];
00869 histogram = XEXP (histogram, 1);
00870 }
00871 wrong_values = INTVAL (XEXP (histogram, 0));
00872 histogram = XEXP (histogram, 1);
00873 wrong_values += INTVAL (XEXP (histogram, 0));
00874 all += wrong_values;
00875
00876
00877
00878 count = 0;
00879 for (i = 0; i < 2; i++)
00880 {
00881 count += counts[i];
00882 if (count * 2 >= all)
00883 break;
00884 }
00885
00886 if (i == 2)
00887 return false;
00888
00889 if (dump_file)
00890 fprintf (dump_file, "Mod subtract transformation on insn %d\n",
00891 INSN_UID (insn));
00892
00893
00894 prob1 = (counts[0] * REG_BR_PROB_BASE + all / 2) / all;
00895 prob2 = (counts[1] * REG_BR_PROB_BASE + all / 2) / all;
00896
00897 e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
00898 delete_insn (insn);
00899
00900 insert_insn_on_edge (
00901 gen_mod_subtract (mode, code, set_dest,
00902 op1, op2, i, prob1, prob2), e);
00903
00904 return true;
00905 }
00906
00907 #ifdef HAVE_prefetch
00908
00909
00910
00911 static rtx
00912 gen_speculative_prefetch (rtx address, gcov_type delta, int write)
00913 {
00914 rtx tmp;
00915 rtx sequence;
00916
00917
00918
00919 start_sequence ();
00920 if (offsettable_address_p (0, VOIDmode, address))
00921 tmp = plus_constant (copy_rtx (address), delta);
00922 else
00923 {
00924 tmp = simplify_gen_binary (PLUS, Pmode,
00925 copy_rtx (address), GEN_INT (delta));
00926 tmp = force_operand (tmp, NULL);
00927 }
00928 if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
00929 (tmp, insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
00930 tmp = force_reg (Pmode, tmp);
00931 emit_insn (gen_prefetch (tmp, GEN_INT (write), GEN_INT (3)));
00932 sequence = get_insns ();
00933 end_sequence ();
00934
00935 return sequence;
00936 }
00937
00938
00939
00940 static bool
00941 speculative_prefetching_transform (rtx insn)
00942 {
00943 rtx histogram, value;
00944 gcov_type val, count, all;
00945 edge e;
00946 rtx mem, address;
00947 int write;
00948
00949 if (!maybe_hot_bb_p (BLOCK_FOR_INSN (insn)))
00950 return false;
00951
00952 if (!find_mem_reference (insn, &mem, &write))
00953 return false;
00954
00955 address = XEXP (mem, 0);
00956 if (side_effects_p (address))
00957 return false;
00958
00959 if (CONSTANT_P (address))
00960 return false;
00961
00962 for (histogram = REG_NOTES (insn);
00963 histogram;
00964 histogram = XEXP (histogram, 1))
00965 if (REG_NOTE_KIND (histogram) == REG_VALUE_PROFILE
00966 && XEXP (XEXP (histogram, 0), 0) == GEN_INT (HIST_TYPE_CONST_DELTA))
00967 break;
00968
00969 if (!histogram)
00970 return false;
00971
00972 histogram = XEXP (XEXP (histogram, 0), 1);
00973 value = XEXP (histogram, 0);
00974 histogram = XEXP (histogram, 1);
00975
00976 histogram = XEXP (histogram, 1);
00977 val = INTVAL (XEXP (histogram, 0));
00978 histogram = XEXP (histogram, 1);
00979 count = INTVAL (XEXP (histogram, 0));
00980 histogram = XEXP (histogram, 1);
00981 all = INTVAL (XEXP (histogram, 0));
00982
00983
00984
00985
00986
00987 if (all < 4)
00988 return false;
00989
00990
00991
00992
00993 if (!rtx_equal_p (address, value) || 2 * count < all)
00994 return false;
00995
00996
00997
00998 if (val >= NOPREFETCH_RANGE_MIN && val <= NOPREFETCH_RANGE_MAX)
00999 return false;
01000
01001 if (dump_file)
01002 fprintf (dump_file, "Speculative prefetching for insn %d\n",
01003 INSN_UID (insn));
01004
01005 e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
01006
01007 insert_insn_on_edge (gen_speculative_prefetch (address, val, write), e);
01008
01009 return true;
01010 }
01011 #endif
01012
01013
01014
01015 struct value_prof_hooks {
01016
01017 void (*find_values_to_profile) (histogram_values *);
01018
01019
01020
01021 bool (*value_profile_transformations) (void);
01022 };
01023
01024
01025 static struct value_prof_hooks rtl_value_prof_hooks =
01026 {
01027 rtl_find_values_to_profile,
01028 rtl_value_profile_transformations
01029 };
01030
01031 void
01032 rtl_register_value_prof_hooks (void)
01033 {
01034 value_prof_hooks = &rtl_value_prof_hooks;
01035 if (ir_type ())
01036 abort ();
01037 }
01038
01039
01040 static void
01041 tree_find_values_to_profile (histogram_values *values ATTRIBUTE_UNUSED)
01042 {
01043 abort ();
01044 }
01045
01046 static bool
01047 tree_value_profile_transformations (void)
01048 {
01049 abort ();
01050 }
01051
01052 static struct value_prof_hooks tree_value_prof_hooks = {
01053 tree_find_values_to_profile,
01054 tree_value_profile_transformations
01055 };
01056
01057 void
01058 tree_register_value_prof_hooks (void)
01059 {
01060 value_prof_hooks = &tree_value_prof_hooks;
01061 if (!ir_type ())
01062 abort ();
01063 }
01064
01065
01066 void
01067 find_values_to_profile (histogram_values *values)
01068 {
01069 (value_prof_hooks->find_values_to_profile) (values);
01070 }
01071
01072 bool
01073 value_profile_transformations (void)
01074 {
01075 return (value_prof_hooks->value_profile_transformations) ();
01076 }
01077