00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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 #include "config.h"
00069 #include "system.h"
00070 #include "coretypes.h"
00071 #include "tm.h"
00072 #include "rtl.h"
00073 #include "regs.h"
00074 #include "flags.h"
00075 #include "timevar.h"
00076 #include "output.h"
00077 #include "cfglayout.h"
00078 #include "fibheap.h"
00079 #include "target.h"
00080 #include "function.h"
00081 #include "tm_p.h"
00082 #include "obstack.h"
00083 #include "expr.h"
00084 #include "params.h"
00085
00086
00087
00088
00089 #define N_ROUNDS 5
00090
00091
00092
00093
00094 #ifndef HAVE_return
00095 #define HAVE_return 0
00096 #define gen_return() NULL_RTX
00097 #endif
00098
00099
00100
00101 static int branch_threshold[N_ROUNDS] = {400, 200, 100, 0, 0};
00102
00103
00104 static int exec_threshold[N_ROUNDS] = {500, 200, 50, 0, 0};
00105
00106
00107
00108 #define DUPLICATION_THRESHOLD 100
00109
00110
00111 static int uncond_jump_length;
00112
00113
00114 typedef struct bbro_basic_block_data_def
00115 {
00116
00117 int start_of_trace;
00118
00119
00120 int end_of_trace;
00121
00122
00123 fibheap_t heap;
00124
00125
00126 fibnode_t node;
00127 } bbro_basic_block_data;
00128
00129
00130 static int array_size;
00131
00132
00133 static bbro_basic_block_data *bbd;
00134
00135
00136
00137 #define GET_ARRAY_SIZE(X) ((((X) / 4) + 1) * 5)
00138
00139
00140 #define FREE(P) (gcc_assert (P), free (P), P = 0)
00141
00142
00143 struct trace
00144 {
00145
00146 basic_block first, last;
00147
00148
00149 int round;
00150
00151
00152 int length;
00153 };
00154
00155
00156 int max_entry_frequency;
00157 gcov_type max_entry_count;
00158
00159
00160 static void find_traces (int *, struct trace *);
00161 static basic_block rotate_loop (edge, struct trace *, int);
00162 static void mark_bb_visited (basic_block, int);
00163 static void find_traces_1_round (int, int, gcov_type, struct trace *, int *,
00164 int, fibheap_t *, int);
00165 static basic_block copy_bb (basic_block, edge, basic_block, int);
00166 static fibheapkey_t bb_to_key (basic_block);
00167 static bool better_edge_p (basic_block, edge, int, int, int, int, edge);
00168 static void connect_traces (int, struct trace *);
00169 static bool copy_bb_p (basic_block, int);
00170 static int get_uncond_jump_length (void);
00171 static bool push_to_next_round_p (basic_block, int, int, int, gcov_type);
00172 static void add_unlikely_executed_notes (void);
00173 static void find_rarely_executed_basic_blocks_and_crossing_edges (edge *,
00174 int *,
00175 int *);
00176 static void mark_bb_for_unlikely_executed_section (basic_block);
00177 static void add_labels_and_missing_jumps (edge *, int);
00178 static void add_reg_crossing_jump_notes (void);
00179 static void fix_up_fall_thru_edges (void);
00180 static void fix_edges_for_rarely_executed_code (edge *, int);
00181 static void fix_crossing_conditional_branches (void);
00182 static void fix_crossing_unconditional_branches (void);
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 static bool
00193 push_to_next_round_p (basic_block bb, int round, int number_of_rounds,
00194 int exec_th, gcov_type count_th)
00195 {
00196 bool there_exists_another_round;
00197 bool cold_block;
00198 bool block_not_hot_enough;
00199 bool next_round_is_last;
00200
00201 there_exists_another_round = round < number_of_rounds - 1;
00202 next_round_is_last = round + 1 == number_of_rounds - 1;
00203
00204 cold_block = (flag_reorder_blocks_and_partition
00205 && BB_PARTITION (bb) == BB_COLD_PARTITION);
00206
00207 block_not_hot_enough = (bb->frequency < exec_th
00208 || bb->count < count_th
00209 || probably_never_executed_bb_p (bb));
00210
00211 if (flag_reorder_blocks_and_partition
00212 && next_round_is_last
00213 && BB_PARTITION (bb) != BB_COLD_PARTITION)
00214 return false;
00215 else if (there_exists_another_round
00216 && (cold_block || block_not_hot_enough))
00217 return true;
00218 else
00219 return false;
00220 }
00221
00222
00223
00224
00225
00226 static void
00227 find_traces (int *n_traces, struct trace *traces)
00228 {
00229 int i;
00230 int number_of_rounds;
00231 edge e;
00232 edge_iterator ei;
00233 fibheap_t heap;
00234
00235
00236
00237
00238
00239 number_of_rounds = N_ROUNDS - 1;
00240 if (flag_reorder_blocks_and_partition)
00241 number_of_rounds = N_ROUNDS;
00242
00243
00244 heap = fibheap_new ();
00245 max_entry_frequency = 0;
00246 max_entry_count = 0;
00247 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
00248 {
00249 bbd[e->dest->index].heap = heap;
00250 bbd[e->dest->index].node = fibheap_insert (heap, bb_to_key (e->dest),
00251 e->dest);
00252 if (e->dest->frequency > max_entry_frequency)
00253 max_entry_frequency = e->dest->frequency;
00254 if (e->dest->count > max_entry_count)
00255 max_entry_count = e->dest->count;
00256 }
00257
00258
00259 for (i = 0; i < number_of_rounds; i++)
00260 {
00261 gcov_type count_threshold;
00262
00263 if (dump_file)
00264 fprintf (dump_file, "STC - round %d\n", i + 1);
00265
00266 if (max_entry_count < INT_MAX / 1000)
00267 count_threshold = max_entry_count * exec_threshold[i] / 1000;
00268 else
00269 count_threshold = max_entry_count / 1000 * exec_threshold[i];
00270
00271 find_traces_1_round (REG_BR_PROB_BASE * branch_threshold[i] / 1000,
00272 max_entry_frequency * exec_threshold[i] / 1000,
00273 count_threshold, traces, n_traces, i, &heap,
00274 number_of_rounds);
00275 }
00276 fibheap_delete (heap);
00277
00278 if (dump_file)
00279 {
00280 for (i = 0; i < *n_traces; i++)
00281 {
00282 basic_block bb;
00283 fprintf (dump_file, "Trace %d (round %d): ", i + 1,
00284 traces[i].round + 1);
00285 for (bb = traces[i].first; bb != traces[i].last; bb = bb->rbi->next)
00286 fprintf (dump_file, "%d [%d] ", bb->index, bb->frequency);
00287 fprintf (dump_file, "%d [%d]\n", bb->index, bb->frequency);
00288 }
00289 fflush (dump_file);
00290 }
00291 }
00292
00293
00294
00295
00296 static basic_block
00297 rotate_loop (edge back_edge, struct trace *trace, int trace_n)
00298 {
00299 basic_block bb;
00300
00301
00302 basic_block best_bb = NULL;
00303 edge best_edge = NULL;
00304 int best_freq = -1;
00305 gcov_type best_count = -1;
00306
00307
00308 bool is_preferred = false;
00309
00310
00311 bb = back_edge->dest;
00312 do
00313 {
00314 edge e;
00315 edge_iterator ei;
00316
00317 FOR_EACH_EDGE (e, ei, bb->succs)
00318 if (e->dest != EXIT_BLOCK_PTR
00319 && e->dest->rbi->visited != trace_n
00320 && (e->flags & EDGE_CAN_FALLTHRU)
00321 && !(e->flags & EDGE_COMPLEX))
00322 {
00323 if (is_preferred)
00324 {
00325
00326 if (!e->dest->rbi->visited
00327 || bbd[e->dest->index].start_of_trace >= 0)
00328 {
00329
00330 int freq = EDGE_FREQUENCY (e);
00331 if (freq > best_freq || e->count > best_count)
00332 {
00333 best_freq = freq;
00334 best_count = e->count;
00335 best_edge = e;
00336 best_bb = bb;
00337 }
00338 }
00339 }
00340 else
00341 {
00342 if (!e->dest->rbi->visited
00343 || bbd[e->dest->index].start_of_trace >= 0)
00344 {
00345
00346 is_preferred = true;
00347 best_freq = EDGE_FREQUENCY (e);
00348 best_count = e->count;
00349 best_edge = e;
00350 best_bb = bb;
00351 }
00352 else
00353 {
00354 int freq = EDGE_FREQUENCY (e);
00355 if (!best_edge || freq > best_freq || e->count > best_count)
00356 {
00357 best_freq = freq;
00358 best_count = e->count;
00359 best_edge = e;
00360 best_bb = bb;
00361 }
00362 }
00363 }
00364 }
00365 bb = bb->rbi->next;
00366 }
00367 while (bb != back_edge->dest);
00368
00369 if (best_bb)
00370 {
00371
00372
00373 if (back_edge->dest == trace->first)
00374 {
00375 trace->first = best_bb->rbi->next;
00376 }
00377 else
00378 {
00379 basic_block prev_bb;
00380
00381 for (prev_bb = trace->first;
00382 prev_bb->rbi->next != back_edge->dest;
00383 prev_bb = prev_bb->rbi->next)
00384 ;
00385 prev_bb->rbi->next = best_bb->rbi->next;
00386
00387
00388 if (EDGE_COUNT (prev_bb->succs) == 1)
00389 {
00390 basic_block header = EDGE_SUCC (prev_bb, 0)->dest;
00391
00392
00393
00394 if (any_condjump_p (BB_END (header)) && copy_bb_p (header, 0)
00395 && !find_reg_note (BB_END (header), REG_CROSSING_JUMP,
00396 NULL_RTX))
00397 {
00398 copy_bb (header, EDGE_SUCC (prev_bb, 0), prev_bb, trace_n);
00399 }
00400 }
00401 }
00402 }
00403 else
00404 {
00405
00406 best_bb = back_edge->src;
00407 }
00408 best_bb->rbi->next = NULL;
00409 return best_bb;
00410 }
00411
00412
00413
00414 static void
00415 mark_bb_visited (basic_block bb, int trace)
00416 {
00417 bb->rbi->visited = trace;
00418 if (bbd[bb->index].heap)
00419 {
00420 fibheap_delete_node (bbd[bb->index].heap, bbd[bb->index].node);
00421 bbd[bb->index].heap = NULL;
00422 bbd[bb->index].node = NULL;
00423 }
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 static void
00435 find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
00436 struct trace *traces, int *n_traces, int round,
00437 fibheap_t *heap, int number_of_rounds)
00438 {
00439
00440
00441
00442 int last_round = N_ROUNDS - 1;
00443
00444
00445
00446 fibheap_t new_heap = fibheap_new ();
00447
00448 while (!fibheap_empty (*heap))
00449 {
00450 basic_block bb;
00451 struct trace *trace;
00452 edge best_edge, e;
00453 fibheapkey_t key;
00454 edge_iterator ei;
00455
00456 bb = fibheap_extract_min (*heap);
00457 bbd[bb->index].heap = NULL;
00458 bbd[bb->index].node = NULL;
00459
00460 if (dump_file)
00461 fprintf (dump_file, "Getting bb %d\n", bb->index);
00462
00463
00464
00465
00466
00467
00468 if (push_to_next_round_p (bb, round, number_of_rounds, exec_th,
00469 count_th))
00470 {
00471 int key = bb_to_key (bb);
00472 bbd[bb->index].heap = new_heap;
00473 bbd[bb->index].node = fibheap_insert (new_heap, key, bb);
00474
00475 if (dump_file)
00476 fprintf (dump_file,
00477 " Possible start point of next round: %d (key: %d)\n",
00478 bb->index, key);
00479 continue;
00480 }
00481
00482 trace = traces + *n_traces;
00483 trace->first = bb;
00484 trace->round = round;
00485 trace->length = 0;
00486 (*n_traces)++;
00487
00488 do
00489 {
00490 int prob, freq;
00491 bool ends_in_call;
00492
00493
00494 int best_prob = INT_MIN / 2;
00495 int best_freq = INT_MIN / 2;
00496
00497 best_edge = NULL;
00498 mark_bb_visited (bb, *n_traces);
00499 trace->length++;
00500
00501 if (dump_file)
00502 fprintf (dump_file, "Basic block %d was visited in trace %d\n",
00503 bb->index, *n_traces - 1);
00504
00505 ends_in_call = block_ends_with_call_p (bb);
00506
00507
00508 FOR_EACH_EDGE (e, ei, bb->succs)
00509 {
00510 gcc_assert (!(e->flags & EDGE_FAKE));
00511
00512 if (e->dest == EXIT_BLOCK_PTR)
00513 continue;
00514
00515 if (e->dest->rbi->visited
00516 && e->dest->rbi->visited != *n_traces)
00517 continue;
00518
00519 if (BB_PARTITION (e->dest) == BB_COLD_PARTITION
00520 && round < last_round)
00521 continue;
00522
00523 prob = e->probability;
00524 freq = EDGE_FREQUENCY (e);
00525
00526
00527
00528 if (ends_in_call)
00529 {
00530 if (e->flags & EDGE_CAN_FALLTHRU)
00531 {
00532 best_edge = e;
00533 best_prob = prob;
00534 best_freq = freq;
00535 }
00536 continue;
00537 }
00538
00539
00540
00541 if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX)
00542 || prob < branch_th || freq < exec_th || e->count < count_th)
00543 continue;
00544
00545
00546
00547
00548 if (better_edge_p (bb, e, prob, freq, best_prob, best_freq,
00549 best_edge))
00550 {
00551 best_edge = e;
00552 best_prob = prob;
00553 best_freq = freq;
00554 }
00555 }
00556
00557
00558
00559
00560 if (best_edge && EDGE_COUNT (best_edge->dest->preds) >= 2
00561 && copy_bb_p (best_edge->dest, 0))
00562 best_edge = NULL;
00563
00564
00565 FOR_EACH_EDGE (e, ei, bb->succs)
00566 {
00567 if (e == best_edge
00568 || e->dest == EXIT_BLOCK_PTR
00569 || e->dest->rbi->visited)
00570 continue;
00571
00572 key = bb_to_key (e->dest);
00573
00574 if (bbd[e->dest->index].heap)
00575 {
00576
00577 if (key != bbd[e->dest->index].node->key)
00578 {
00579 if (dump_file)
00580 {
00581 fprintf (dump_file,
00582 "Changing key for bb %d from %ld to %ld.\n",
00583 e->dest->index,
00584 (long) bbd[e->dest->index].node->key,
00585 key);
00586 }
00587 fibheap_replace_key (bbd[e->dest->index].heap,
00588 bbd[e->dest->index].node, key);
00589 }
00590 }
00591 else
00592 {
00593 fibheap_t which_heap = *heap;
00594
00595 prob = e->probability;
00596 freq = EDGE_FREQUENCY (e);
00597
00598 if (!(e->flags & EDGE_CAN_FALLTHRU)
00599 || (e->flags & EDGE_COMPLEX)
00600 || prob < branch_th || freq < exec_th
00601 || e->count < count_th)
00602 {
00603
00604
00605
00606
00607 if (push_to_next_round_p (e->dest, round,
00608 number_of_rounds,
00609 exec_th, count_th))
00610 which_heap = new_heap;
00611 }
00612
00613 bbd[e->dest->index].heap = which_heap;
00614 bbd[e->dest->index].node = fibheap_insert (which_heap,
00615 key, e->dest);
00616
00617 if (dump_file)
00618 {
00619 fprintf (dump_file,
00620 " Possible start of %s round: %d (key: %ld)\n",
00621 (which_heap == new_heap) ? "next" : "this",
00622 e->dest->index, (long) key);
00623 }
00624
00625 }
00626 }
00627
00628 if (best_edge)
00629 {
00630 if (best_edge->dest->rbi->visited == *n_traces)
00631 {
00632
00633 if (best_edge->dest != bb)
00634 {
00635 if (EDGE_FREQUENCY (best_edge)
00636 > 4 * best_edge->dest->frequency / 5)
00637 {
00638
00639
00640
00641
00642 if (best_edge->dest != ENTRY_BLOCK_PTR->next_bb)
00643 {
00644 if (dump_file)
00645 {
00646 fprintf (dump_file,
00647 "Rotating loop %d - %d\n",
00648 best_edge->dest->index, bb->index);
00649 }
00650 bb->rbi->next = best_edge->dest;
00651 bb = rotate_loop (best_edge, trace, *n_traces);
00652 }
00653 }
00654 else
00655 {
00656
00657
00658 if (EDGE_COUNT (bb->succs) == 1
00659 && copy_bb_p (best_edge->dest, !optimize_size))
00660 {
00661 bb = copy_bb (best_edge->dest, best_edge, bb,
00662 *n_traces);
00663 }
00664 }
00665 }
00666
00667
00668 break;
00669 }
00670 else
00671 {
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 FOR_EACH_EDGE (e, ei, bb->succs)
00694 if (e != best_edge
00695 && (e->flags & EDGE_CAN_FALLTHRU)
00696 && !(e->flags & EDGE_COMPLEX)
00697 && !e->dest->rbi->visited
00698 && EDGE_COUNT (e->dest->preds) == 1
00699 && !(e->flags & EDGE_CROSSING)
00700 && EDGE_COUNT (e->dest->succs) == 1
00701 && (EDGE_SUCC (e->dest, 0)->flags & EDGE_CAN_FALLTHRU)
00702 && !(EDGE_SUCC (e->dest, 0)->flags & EDGE_COMPLEX)
00703 && EDGE_SUCC (e->dest, 0)->dest == best_edge->dest
00704 && 2 * e->dest->frequency >= EDGE_FREQUENCY (best_edge))
00705 {
00706 best_edge = e;
00707 if (dump_file)
00708 fprintf (dump_file, "Selecting BB %d\n",
00709 best_edge->dest->index);
00710 break;
00711 }
00712
00713 bb->rbi->next = best_edge->dest;
00714 bb = best_edge->dest;
00715 }
00716 }
00717 }
00718 while (best_edge);
00719 trace->last = bb;
00720 bbd[trace->first->index].start_of_trace = *n_traces - 1;
00721 bbd[trace->last->index].end_of_trace = *n_traces - 1;
00722
00723
00724
00725
00726 FOR_EACH_EDGE (e, ei, bb->succs)
00727 {
00728 if (e->dest == EXIT_BLOCK_PTR
00729 || e->dest->rbi->visited)
00730 continue;
00731
00732 if (bbd[e->dest->index].heap)
00733 {
00734 key = bb_to_key (e->dest);
00735 if (key != bbd[e->dest->index].node->key)
00736 {
00737 if (dump_file)
00738 {
00739 fprintf (dump_file,
00740 "Changing key for bb %d from %ld to %ld.\n",
00741 e->dest->index,
00742 (long) bbd[e->dest->index].node->key, key);
00743 }
00744 fibheap_replace_key (bbd[e->dest->index].heap,
00745 bbd[e->dest->index].node,
00746 key);
00747 }
00748 }
00749 }
00750 }
00751
00752 fibheap_delete (*heap);
00753
00754
00755 *heap = new_heap;
00756 }
00757
00758
00759
00760
00761
00762 static basic_block
00763 copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
00764 {
00765 basic_block new_bb;
00766
00767 new_bb = duplicate_block (old_bb, e);
00768 BB_COPY_PARTITION (new_bb, old_bb);
00769
00770 gcc_assert (e->dest == new_bb);
00771 gcc_assert (!e->dest->rbi->visited);
00772
00773 if (dump_file)
00774 fprintf (dump_file,
00775 "Duplicated bb %d (created bb %d)\n",
00776 old_bb->index, new_bb->index);
00777 new_bb->rbi->visited = trace;
00778 new_bb->rbi->next = bb->rbi->next;
00779 bb->rbi->next = new_bb;
00780
00781 if (new_bb->index >= array_size || last_basic_block > array_size)
00782 {
00783 int i;
00784 int new_size;
00785
00786 new_size = MAX (last_basic_block, new_bb->index + 1);
00787 new_size = GET_ARRAY_SIZE (new_size);
00788 bbd = xrealloc (bbd, new_size * sizeof (bbro_basic_block_data));
00789 for (i = array_size; i < new_size; i++)
00790 {
00791 bbd[i].start_of_trace = -1;
00792 bbd[i].end_of_trace = -1;
00793 bbd[i].heap = NULL;
00794 bbd[i].node = NULL;
00795 }
00796 array_size = new_size;
00797
00798 if (dump_file)
00799 {
00800 fprintf (dump_file,
00801 "Growing the dynamic array to %d elements.\n",
00802 array_size);
00803 }
00804 }
00805
00806 return new_bb;
00807 }
00808
00809
00810
00811 static fibheapkey_t
00812 bb_to_key (basic_block bb)
00813 {
00814 edge e;
00815 edge_iterator ei;
00816 int priority = 0;
00817
00818
00819
00820 if (BB_PARTITION (bb) == BB_COLD_PARTITION
00821 || probably_never_executed_bb_p (bb))
00822 return BB_FREQ_MAX;
00823
00824
00825
00826 FOR_EACH_EDGE (e, ei, bb->preds)
00827 {
00828 if ((e->src != ENTRY_BLOCK_PTR && bbd[e->src->index].end_of_trace >= 0)
00829 || (e->flags & EDGE_DFS_BACK))
00830 {
00831 int edge_freq = EDGE_FREQUENCY (e);
00832
00833 if (edge_freq > priority)
00834 priority = edge_freq;
00835 }
00836 }
00837
00838 if (priority)
00839
00840 return -(100 * BB_FREQ_MAX + 100 * priority + bb->frequency);
00841 return -bb->frequency;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851 static bool
00852 better_edge_p (basic_block bb, edge e, int prob, int freq, int best_prob,
00853 int best_freq, edge cur_best_edge)
00854 {
00855 bool is_better_edge;
00856
00857
00858
00859 int diff_prob = best_prob / 10;
00860 int diff_freq = best_freq / 10;
00861
00862 if (prob > best_prob + diff_prob)
00863
00864 is_better_edge = true;
00865 else if (prob < best_prob - diff_prob)
00866
00867 is_better_edge = false;
00868 else if (freq < best_freq - diff_freq)
00869
00870
00871
00872
00873 is_better_edge = true;
00874 else if (freq > best_freq + diff_freq)
00875
00876 is_better_edge = false;
00877 else if (e->dest->prev_bb == bb)
00878
00879
00880 is_better_edge = true;
00881 else
00882 is_better_edge = false;
00883
00884
00885
00886
00887 if (!is_better_edge
00888 && flag_reorder_blocks_and_partition
00889 && cur_best_edge
00890 && (cur_best_edge->flags & EDGE_CROSSING)
00891 && !(e->flags & EDGE_CROSSING))
00892 is_better_edge = true;
00893
00894 return is_better_edge;
00895 }
00896
00897
00898
00899 static void
00900 connect_traces (int n_traces, struct trace *traces)
00901 {
00902 int i;
00903 int unconnected_hot_trace_count = 0;
00904 bool cold_connected = true;
00905 bool *connected;
00906 bool *cold_traces;
00907 int last_trace;
00908 int freq_threshold;
00909 gcov_type count_threshold;
00910
00911 freq_threshold = max_entry_frequency * DUPLICATION_THRESHOLD / 1000;
00912 if (max_entry_count < INT_MAX / 1000)
00913 count_threshold = max_entry_count * DUPLICATION_THRESHOLD / 1000;
00914 else
00915 count_threshold = max_entry_count / 1000 * DUPLICATION_THRESHOLD;
00916
00917 connected = xcalloc (n_traces, sizeof (bool));
00918 last_trace = -1;
00919
00920
00921
00922
00923
00924
00925
00926 cold_traces = xcalloc (n_traces, sizeof (bool));
00927
00928 if (flag_reorder_blocks_and_partition)
00929 for (i = 0; i < n_traces; i++)
00930 {
00931 if (BB_PARTITION (traces[i].first) == BB_COLD_PARTITION)
00932 {
00933 connected[i] = true;
00934 cold_traces[i] = true;
00935 cold_connected = false;
00936 }
00937 else
00938 unconnected_hot_trace_count++;
00939 }
00940
00941 for (i = 0; i < n_traces || !cold_connected ; i++)
00942 {
00943 int t = i;
00944 int t2;
00945 edge e, best;
00946 int best_len;
00947
00948
00949
00950
00951
00952
00953
00954
00955 if (flag_reorder_blocks_and_partition
00956 && (i >= n_traces || unconnected_hot_trace_count <= 0)
00957 && !cold_connected)
00958 {
00959 int j;
00960 int first_cold_trace = -1;
00961
00962 for (j = 0; j < n_traces; j++)
00963 if (cold_traces[j])
00964 {
00965 connected[j] = false;
00966 if (first_cold_trace == -1)
00967 first_cold_trace = j;
00968 }
00969 i = t = first_cold_trace;
00970 cold_connected = true;
00971 }
00972
00973 if (connected[t])
00974 continue;
00975
00976 connected[t] = true;
00977 if (unconnected_hot_trace_count > 0)
00978 unconnected_hot_trace_count--;
00979
00980
00981 for (t2 = t; t2 > 0;)
00982 {
00983 edge_iterator ei;
00984 best = NULL;
00985 best_len = 0;
00986 FOR_EACH_EDGE (e, ei, traces[t2].first->preds)
00987 {
00988 int si = e->src->index;
00989
00990 if (e->src != ENTRY_BLOCK_PTR
00991 && (e->flags & EDGE_CAN_FALLTHRU)
00992 && !(e->flags & EDGE_COMPLEX)
00993 && bbd[si].end_of_trace >= 0
00994 && !connected[bbd[si].end_of_trace]
00995 && (!best
00996 || e->probability > best->probability
00997 || (e->probability == best->probability
00998 && traces[bbd[si].end_of_trace].length > best_len)))
00999 {
01000 best = e;
01001 best_len = traces[bbd[si].end_of_trace].length;
01002 }
01003 }
01004 if (best)
01005 {
01006 best->src->rbi->next = best->dest;
01007 t2 = bbd[best->src->index].end_of_trace;
01008 connected[t2] = true;
01009
01010 if (unconnected_hot_trace_count > 0)
01011 unconnected_hot_trace_count--;
01012
01013 if (dump_file)
01014 {
01015 fprintf (dump_file, "Connection: %d %d\n",
01016 best->src->index, best->dest->index);
01017 }
01018 }
01019 else
01020 break;
01021 }
01022
01023 if (last_trace >= 0)
01024 traces[last_trace].last->rbi->next = traces[t2].first;
01025 last_trace = t;
01026
01027
01028 while (1)
01029 {
01030
01031 edge_iterator ei;
01032 best = NULL;
01033 best_len = 0;
01034 FOR_EACH_EDGE (e, ei, traces[t].last->succs)
01035 {
01036 int di = e->dest->index;
01037
01038 if (e->dest != EXIT_BLOCK_PTR
01039 && (e->flags & EDGE_CAN_FALLTHRU)
01040 && !(e->flags & EDGE_COMPLEX)
01041 && bbd[di].start_of_trace >= 0
01042 && !connected[bbd[di].start_of_trace]
01043 && (!best
01044 || e->probability > best->probability
01045 || (e->probability == best->probability
01046 && traces[bbd[di].start_of_trace].length > best_len)))
01047 {
01048 best = e;
01049 best_len = traces[bbd[di].start_of_trace].length;
01050 }
01051 }
01052
01053 if (best)
01054 {
01055 if (dump_file)
01056 {
01057 fprintf (dump_file, "Connection: %d %d\n",
01058 best->src->index, best->dest->index);
01059 }
01060 t = bbd[best->dest->index].start_of_trace;
01061 traces[last_trace].last->rbi->next = traces[t].first;
01062 connected[t] = true;
01063 if (unconnected_hot_trace_count > 0)
01064 unconnected_hot_trace_count--;
01065 last_trace = t;
01066 }
01067 else
01068 {
01069
01070 edge e2;
01071 basic_block next_bb = NULL;
01072 bool try_copy = false;
01073
01074 FOR_EACH_EDGE (e, ei, traces[t].last->succs)
01075 if (e->dest != EXIT_BLOCK_PTR
01076 && (e->flags & EDGE_CAN_FALLTHRU)
01077 && !(e->flags & EDGE_COMPLEX)
01078 && (!best || e->probability > best->probability))
01079 {
01080 edge_iterator ei;
01081 edge best2 = NULL;
01082 int best2_len = 0;
01083
01084
01085
01086
01087 if (bbd[e->dest->index].start_of_trace >= 0
01088 && traces[bbd[e->dest->index].start_of_trace].length
01089 == 1)
01090 {
01091 best = e;
01092 try_copy = true;
01093 continue;
01094 }
01095
01096 FOR_EACH_EDGE (e2, ei, e->dest->succs)
01097 {
01098 int di = e2->dest->index;
01099
01100 if (e2->dest == EXIT_BLOCK_PTR
01101 || ((e2->flags & EDGE_CAN_FALLTHRU)
01102 && !(e2->flags & EDGE_COMPLEX)
01103 && bbd[di].start_of_trace >= 0
01104 && !connected[bbd[di].start_of_trace]
01105 && (EDGE_FREQUENCY (e2) >= freq_threshold)
01106 && (e2->count >= count_threshold)
01107 && (!best2
01108 || e2->probability > best2->probability
01109 || (e2->probability == best2->probability
01110 && traces[bbd[di].start_of_trace].length
01111 > best2_len))))
01112 {
01113 best = e;
01114 best2 = e2;
01115 if (e2->dest != EXIT_BLOCK_PTR)
01116 best2_len = traces[bbd[di].start_of_trace].length;
01117 else
01118 best2_len = INT_MAX;
01119 next_bb = e2->dest;
01120 try_copy = true;
01121 }
01122 }
01123 }
01124
01125 if (flag_reorder_blocks_and_partition)
01126 try_copy = false;
01127
01128
01129
01130 if (try_copy
01131 && copy_bb_p (best->dest,
01132 !optimize_size
01133 && EDGE_FREQUENCY (best) >= freq_threshold
01134 && best->count >= count_threshold))
01135 {
01136 basic_block new_bb;
01137
01138 if (dump_file)
01139 {
01140 fprintf (dump_file, "Connection: %d %d ",
01141 traces[t].last->index, best->dest->index);
01142 if (!next_bb)
01143 fputc ('\n', dump_file);
01144 else if (next_bb == EXIT_BLOCK_PTR)
01145 fprintf (dump_file, "exit\n");
01146 else
01147 fprintf (dump_file, "%d\n", next_bb->index);
01148 }
01149
01150 new_bb = copy_bb (best->dest, best, traces[t].last, t);
01151 traces[t].last = new_bb;
01152 if (next_bb && next_bb != EXIT_BLOCK_PTR)
01153 {
01154 t = bbd[next_bb->index].start_of_trace;
01155 traces[last_trace].last->rbi->next = traces[t].first;
01156 connected[t] = true;
01157 if (unconnected_hot_trace_count > 0)
01158 unconnected_hot_trace_count--;
01159 last_trace = t;
01160 }
01161 else
01162 break;
01163 }
01164 else
01165 break;
01166 }
01167 }
01168 }
01169
01170 if (dump_file)
01171 {
01172 basic_block bb;
01173
01174 fprintf (dump_file, "Final order:\n");
01175 for (bb = traces[0].first; bb; bb = bb->rbi->next)
01176 fprintf (dump_file, "%d ", bb->index);
01177 fprintf (dump_file, "\n");
01178 fflush (dump_file);
01179 }
01180
01181 FREE (connected);
01182 FREE (cold_traces);
01183 }
01184
01185
01186
01187
01188 static bool
01189 copy_bb_p (basic_block bb, int code_may_grow)
01190 {
01191 int size = 0;
01192 int max_size = uncond_jump_length;
01193 rtx insn;
01194
01195 if (!bb->frequency)
01196 return false;
01197 if (EDGE_COUNT (bb->preds) < 2)
01198 return false;
01199 if (!can_duplicate_block_p (bb))
01200 return false;
01201
01202
01203 if (EDGE_COUNT (bb->succs) > 8)
01204 return false;
01205
01206 if (code_may_grow && maybe_hot_bb_p (bb))
01207 max_size *= 8;
01208
01209 FOR_BB_INSNS (bb, insn)
01210 {
01211 if (INSN_P (insn))
01212 size += get_attr_length (insn);
01213 }
01214
01215 if (size <= max_size)
01216 return true;
01217
01218 if (dump_file)
01219 {
01220 fprintf (dump_file,
01221 "Block %d can't be copied because its size = %d.\n",
01222 bb->index, size);
01223 }
01224
01225 return false;
01226 }
01227
01228
01229
01230 static int
01231 get_uncond_jump_length (void)
01232 {
01233 rtx label, jump;
01234 int length;
01235
01236 label = emit_label_before (gen_label_rtx (), get_insns ());
01237 jump = emit_jump_insn (gen_jump (label));
01238
01239 length = get_attr_length (jump);
01240
01241 delete_insn (jump);
01242 delete_insn (label);
01243 return length;
01244 }
01245
01246 static void
01247 add_unlikely_executed_notes (void)
01248 {
01249 basic_block bb;
01250
01251
01252
01253 FOR_EACH_BB (bb)
01254 if (BB_PARTITION (bb) == BB_COLD_PARTITION)
01255 mark_bb_for_unlikely_executed_section (bb);
01256 }
01257
01258
01259
01260
01261
01262 static void
01263 find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
01264 int *n_crossing_edges,
01265 int *max_idx)
01266 {
01267 basic_block bb;
01268 bool has_hot_blocks = false;
01269 edge e;
01270 int i;
01271 edge_iterator ei;
01272
01273
01274
01275 FOR_EACH_BB (bb)
01276 {
01277 if (probably_never_executed_bb_p (bb))
01278 BB_SET_PARTITION (bb, BB_COLD_PARTITION);
01279 else
01280 {
01281 BB_SET_PARTITION (bb, BB_HOT_PARTITION);
01282 has_hot_blocks = true;
01283 }
01284 }
01285
01286
01287
01288
01289
01290 if (has_hot_blocks)
01291 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
01292 if (e->dest->index >= 0)
01293 {
01294 BB_SET_PARTITION (e->dest, BB_HOT_PARTITION);
01295 break;
01296 }
01297
01298
01299
01300 i = 0;
01301 if (targetm.have_named_sections)
01302 {
01303 FOR_EACH_BB (bb)
01304 FOR_EACH_EDGE (e, ei, bb->succs)
01305 {
01306 if (e->src != ENTRY_BLOCK_PTR
01307 && e->dest != EXIT_BLOCK_PTR
01308 && BB_PARTITION (e->src) != BB_PARTITION (e->dest))
01309 {
01310 e->flags |= EDGE_CROSSING;
01311 if (i == *max_idx)
01312 {
01313 *max_idx *= 2;
01314 crossing_edges = xrealloc (crossing_edges,
01315 (*max_idx) * sizeof (edge));
01316 }
01317 crossing_edges[i++] = e;
01318 }
01319 else
01320 e->flags &= ~EDGE_CROSSING;
01321 }
01322 }
01323 *n_crossing_edges = i;
01324 }
01325
01326
01327
01328
01329
01330 static void
01331 mark_bb_for_unlikely_executed_section (basic_block bb)
01332 {
01333 rtx cur_insn;
01334 rtx insert_insn = NULL;
01335 rtx new_note;
01336
01337
01338
01339 for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
01340 cur_insn = NEXT_INSN (cur_insn))
01341 if (GET_CODE (cur_insn) == NOTE
01342 && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
01343 {
01344 insert_insn = cur_insn;
01345 break;
01346 }
01347
01348
01349
01350 gcc_assert (insert_insn);
01351
01352
01353
01354 new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
01355 insert_insn);
01356 NOTE_BASIC_BLOCK (new_note) = bb;
01357 }
01358
01359
01360
01361
01362
01363 static void
01364 add_labels_and_missing_jumps (edge *crossing_edges, int n_crossing_edges)
01365 {
01366 int i;
01367 basic_block src;
01368 basic_block dest;
01369 rtx label;
01370 rtx barrier;
01371 rtx new_jump;
01372
01373 for (i=0; i < n_crossing_edges; i++)
01374 {
01375 if (crossing_edges[i])
01376 {
01377 src = crossing_edges[i]->src;
01378 dest = crossing_edges[i]->dest;
01379
01380
01381
01382 if (dest && (dest != EXIT_BLOCK_PTR))
01383 {
01384 label = block_label (dest);
01385
01386
01387
01388 if (src && (src != ENTRY_BLOCK_PTR))
01389 {
01390 if (!JUMP_P (BB_END (src)))
01391
01392 {
01393
01394 gcc_assert (EDGE_COUNT (src->succs) == 1);
01395
01396
01397 label = block_label (dest);
01398
01399 new_jump = emit_jump_insn_after (gen_jump (label),
01400 BB_END (src));
01401 barrier = emit_barrier_after (new_jump);
01402 JUMP_LABEL (new_jump) = label;
01403 LABEL_NUSES (label) += 1;
01404 src->rbi->footer = unlink_insn_chain (barrier, barrier);
01405
01406 crossing_edges[i]->flags &= ~EDGE_FALLTHRU;
01407 }
01408 }
01409 }
01410 }
01411 }
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 static void
01424 fix_up_fall_thru_edges (void)
01425 {
01426 basic_block cur_bb;
01427 basic_block new_bb;
01428 edge succ1;
01429 edge succ2;
01430 edge fall_thru;
01431 edge cond_jump = NULL;
01432 edge e;
01433 bool cond_jump_crosses;
01434 int invert_worked;
01435 rtx old_jump;
01436 rtx fall_thru_label;
01437 rtx barrier;
01438
01439 FOR_EACH_BB (cur_bb)
01440 {
01441 fall_thru = NULL;
01442 if (EDGE_COUNT (cur_bb->succs) > 0)
01443 succ1 = EDGE_SUCC (cur_bb, 0);
01444 else
01445 succ1 = NULL;
01446
01447 if (EDGE_COUNT (cur_bb->succs) > 1)
01448 succ2 = EDGE_SUCC (cur_bb, 1);
01449 else
01450 succ2 = NULL;
01451
01452
01453
01454 if (succ1
01455 && (succ1->flags & EDGE_FALLTHRU))
01456 {
01457 fall_thru = succ1;
01458 cond_jump = succ2;
01459 }
01460 else if (succ2
01461 && (succ2->flags & EDGE_FALLTHRU))
01462 {
01463 fall_thru = succ2;
01464 cond_jump = succ1;
01465 }
01466
01467 if (fall_thru && (fall_thru->dest != EXIT_BLOCK_PTR))
01468 {
01469
01470
01471 if (fall_thru->flags & EDGE_CROSSING)
01472 {
01473
01474
01475
01476 cond_jump_crosses = true;
01477 invert_worked = 0;
01478 old_jump = BB_END (cur_bb);
01479
01480
01481
01482 if (cond_jump)
01483 {
01484 if (!(cond_jump->flags & EDGE_CROSSING))
01485 cond_jump_crosses = false;
01486
01487
01488
01489
01490
01491
01492
01493 if (!cond_jump_crosses
01494 && cur_bb->rbi->next == cond_jump->dest)
01495 {
01496
01497
01498
01499 fall_thru_label = block_label (fall_thru->dest);
01500
01501 if (old_jump && fall_thru_label)
01502 invert_worked = invert_jump (old_jump,
01503 fall_thru_label,0);
01504 if (invert_worked)
01505 {
01506 fall_thru->flags &= ~EDGE_FALLTHRU;
01507 cond_jump->flags |= EDGE_FALLTHRU;
01508 update_br_prob_note (cur_bb);
01509 e = fall_thru;
01510 fall_thru = cond_jump;
01511 cond_jump = e;
01512 cond_jump->flags |= EDGE_CROSSING;
01513 fall_thru->flags &= ~EDGE_CROSSING;
01514 }
01515 }
01516 }
01517
01518 if (cond_jump_crosses || !invert_worked)
01519 {
01520
01521
01522
01523
01524
01525 new_bb = force_nonfallthru (fall_thru);
01526
01527 if (new_bb)
01528 {
01529 new_bb->rbi->next = cur_bb->rbi->next;
01530 cur_bb->rbi->next = new_bb;
01531
01532
01533
01534
01535 BB_COPY_PARTITION (new_bb, cur_bb);
01536 EDGE_SUCC (new_bb, 0)->flags |= EDGE_CROSSING;
01537 }
01538
01539
01540
01541 if (new_bb)
01542 {
01543 barrier = emit_barrier_after (BB_END (new_bb));
01544 new_bb->rbi->footer = unlink_insn_chain (barrier,
01545 barrier);
01546 }
01547 else
01548 {
01549 barrier = emit_barrier_after (BB_END (cur_bb));
01550 cur_bb->rbi->footer = unlink_insn_chain (barrier,
01551 barrier);
01552 }
01553 }
01554 }
01555 }
01556 }
01557 }
01558
01559
01560
01561
01562
01563
01564
01565 static basic_block
01566 find_jump_block (basic_block jump_dest)
01567 {
01568 basic_block source_bb = NULL;
01569 edge e;
01570 rtx insn;
01571 edge_iterator ei;
01572
01573 FOR_EACH_EDGE (e, ei, jump_dest->preds)
01574 if (e->flags & EDGE_CROSSING)
01575 {
01576 basic_block src = e->src;
01577
01578
01579
01580
01581
01582 if (LABEL_P (BB_HEAD (src)))
01583 for (insn = BB_HEAD (src);
01584 !INSN_P (insn) && insn != NEXT_INSN (BB_END (src));
01585 insn = NEXT_INSN (insn))
01586 {
01587 if (INSN_P (insn)
01588 && insn == BB_END (src)
01589 && JUMP_P (insn)
01590 && !any_condjump_p (insn))
01591 {
01592 source_bb = src;
01593 break;
01594 }
01595 }
01596
01597 if (source_bb)
01598 break;
01599 }
01600
01601 return source_bb;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610 static void
01611 fix_crossing_conditional_branches (void)
01612 {
01613 basic_block cur_bb;
01614 basic_block new_bb;
01615 basic_block last_bb;
01616 basic_block dest;
01617 basic_block prev_bb;
01618 edge succ1;
01619 edge succ2;
01620 edge crossing_edge;
01621 edge new_edge;
01622 rtx old_jump;
01623 rtx set_src;
01624 rtx old_label = NULL_RTX;
01625 rtx new_label;
01626 rtx new_jump;
01627 rtx barrier;
01628
01629 last_bb = EXIT_BLOCK_PTR->prev_bb;
01630
01631 FOR_EACH_BB (cur_bb)
01632 {
01633 crossing_edge = NULL;
01634 if (EDGE_COUNT (cur_bb->succs) > 0)
01635 succ1 = EDGE_SUCC (cur_bb, 0);
01636 else
01637 succ1 = NULL;
01638
01639 if (EDGE_COUNT (cur_bb->succs) > 1)
01640 succ2 = EDGE_SUCC (cur_bb, 1);
01641 else
01642 succ2 = NULL;
01643
01644
01645
01646
01647 if (succ1 && (succ1->flags & EDGE_CROSSING))
01648 crossing_edge = succ1;
01649 else if (succ2 && (succ2->flags & EDGE_CROSSING))
01650 crossing_edge = succ2;
01651
01652 if (crossing_edge)
01653 {
01654 old_jump = BB_END (cur_bb);
01655
01656
01657
01658
01659 set_src = NULL_RTX;
01660
01661 if (any_condjump_p (old_jump))
01662 {
01663 if (GET_CODE (PATTERN (old_jump)) == SET)
01664 set_src = SET_SRC (PATTERN (old_jump));
01665 else if (GET_CODE (PATTERN (old_jump)) == PARALLEL)
01666 {
01667 set_src = XVECEXP (PATTERN (old_jump), 0,0);
01668 if (GET_CODE (set_src) == SET)
01669 set_src = SET_SRC (set_src);
01670 else
01671 set_src = NULL_RTX;
01672 }
01673 }
01674
01675 if (set_src && (GET_CODE (set_src) == IF_THEN_ELSE))
01676 {
01677 if (GET_CODE (XEXP (set_src, 1)) == PC)
01678 old_label = XEXP (set_src, 2);
01679 else if (GET_CODE (XEXP (set_src, 2)) == PC)
01680 old_label = XEXP (set_src, 1);
01681
01682
01683
01684
01685
01686 new_bb = find_jump_block (crossing_edge->dest);
01687
01688 if (new_bb)
01689 new_label = block_label (new_bb);
01690 else
01691 {
01692
01693
01694
01695 new_bb = create_basic_block (NULL, NULL, last_bb);
01696 new_bb->rbi->next = last_bb->rbi->next;
01697 last_bb->rbi->next = new_bb;
01698 prev_bb = last_bb;
01699 last_bb = new_bb;
01700
01701
01702
01703 new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
01704 new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
01705 COPY_REG_SET (new_bb->global_live_at_end,
01706 prev_bb->global_live_at_end);
01707 COPY_REG_SET (new_bb->global_live_at_start,
01708 prev_bb->global_live_at_end);
01709
01710
01711
01712 new_label = gen_label_rtx ();
01713 emit_label_before (new_label, BB_HEAD (new_bb));
01714 BB_HEAD (new_bb) = new_label;
01715
01716 if (GET_CODE (old_label) == LABEL_REF)
01717 {
01718 old_label = JUMP_LABEL (old_jump);
01719 new_jump = emit_jump_insn_after (gen_jump
01720 (old_label),
01721 BB_END (new_bb));
01722 }
01723 else
01724 {
01725 gcc_assert (HAVE_return
01726 && GET_CODE (old_label) == RETURN);
01727 new_jump = emit_jump_insn_after (gen_return (),
01728 BB_END (new_bb));
01729 }
01730
01731 barrier = emit_barrier_after (new_jump);
01732 JUMP_LABEL (new_jump) = old_label;
01733 new_bb->rbi->footer = unlink_insn_chain (barrier,
01734 barrier);
01735
01736
01737
01738 BB_COPY_PARTITION (new_bb, cur_bb);
01739 }
01740
01741
01742
01743 redirect_jump (old_jump, new_label, 0);
01744
01745
01746
01747 dest = crossing_edge->dest;
01748
01749 redirect_edge_succ (crossing_edge, new_bb);
01750
01751
01752
01753
01754
01755 if (EDGE_COUNT (new_bb->succs) == 0)
01756 new_edge = make_edge (new_bb, dest, 0);
01757 else
01758 new_edge = EDGE_SUCC (new_bb, 0);
01759
01760 crossing_edge->flags &= ~EDGE_CROSSING;
01761 new_edge->flags |= EDGE_CROSSING;
01762 }
01763 }
01764 }
01765 }
01766
01767
01768
01769
01770 static void
01771 fix_crossing_unconditional_branches (void)
01772 {
01773 basic_block cur_bb;
01774 rtx last_insn;
01775 rtx label;
01776 rtx label_addr;
01777 rtx indirect_jump_sequence;
01778 rtx jump_insn = NULL_RTX;
01779 rtx new_reg;
01780 rtx cur_insn;
01781 edge succ;
01782
01783 FOR_EACH_BB (cur_bb)
01784 {
01785 last_insn = BB_END (cur_bb);
01786 succ = EDGE_SUCC (cur_bb, 0);
01787
01788
01789
01790
01791 if (JUMP_P (last_insn)
01792 && (succ->flags & EDGE_CROSSING))
01793 {
01794 rtx label2, table;
01795
01796 gcc_assert (!any_condjump_p (last_insn));
01797
01798
01799
01800 if (!computed_jump_p (last_insn)
01801 && !tablejump_p (last_insn, &label2, &table))
01802 {
01803
01804
01805
01806
01807 label = JUMP_LABEL (last_insn);
01808 label_addr = gen_rtx_LABEL_REF (Pmode, label);
01809 LABEL_NUSES (label) += 1;
01810
01811
01812
01813 new_reg = gen_reg_rtx (Pmode);
01814
01815
01816
01817 start_sequence ();
01818 emit_move_insn (new_reg, label_addr);
01819 emit_indirect_jump (new_reg);
01820 indirect_jump_sequence = get_insns ();
01821 end_sequence ();
01822
01823
01824
01825
01826 for (cur_insn = indirect_jump_sequence; cur_insn;
01827 cur_insn = NEXT_INSN (cur_insn))
01828 {
01829 BLOCK_FOR_INSN (cur_insn) = cur_bb;
01830 if (JUMP_P (cur_insn))
01831 jump_insn = cur_insn;
01832 }
01833
01834
01835
01836
01837 emit_insn_before (indirect_jump_sequence, last_insn);
01838 delete_insn (last_insn);
01839
01840
01841
01842
01843 BB_END (cur_bb) = jump_insn;
01844 }
01845 }
01846 }
01847 }
01848
01849
01850
01851 static void
01852 add_reg_crossing_jump_notes (void)
01853 {
01854 basic_block bb;
01855 edge e;
01856 edge_iterator ei;
01857
01858 FOR_EACH_BB (bb)
01859 FOR_EACH_EDGE (e, ei, bb->succs)
01860 if ((e->flags & EDGE_CROSSING)
01861 && JUMP_P (BB_END (e->src)))
01862 REG_NOTES (BB_END (e->src)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP,
01863 NULL_RTX,
01864 REG_NOTES (BB_END
01865 (e->src)));
01866 }
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899 static void
01900 fix_edges_for_rarely_executed_code (edge *crossing_edges,
01901 int n_crossing_edges)
01902 {
01903
01904
01905
01906 add_labels_and_missing_jumps (crossing_edges, n_crossing_edges);
01907
01908
01909
01910
01911
01912 fix_up_fall_thru_edges ();
01913
01914
01915
01916
01917
01918
01919
01920
01921 if (targetm.have_named_sections)
01922 {
01923
01924
01925
01926
01927 if (!HAS_LONG_COND_BRANCH)
01928 fix_crossing_conditional_branches ();
01929
01930
01931
01932
01933
01934
01935
01936 if (!HAS_LONG_UNCOND_BRANCH)
01937 {
01938 fix_crossing_unconditional_branches ();
01939 reg_scan (get_insns(), max_reg_num ());
01940 }
01941
01942 add_reg_crossing_jump_notes ();
01943 }
01944 }
01945
01946
01947
01948
01949 void
01950 reorder_basic_blocks (unsigned int flags)
01951 {
01952 int n_traces;
01953 int i;
01954 struct trace *traces;
01955
01956 if (n_basic_blocks <= 1)
01957 return;
01958
01959 if (targetm.cannot_modify_jumps_p ())
01960 return;
01961
01962 timevar_push (TV_REORDER_BLOCKS);
01963
01964 cfg_layout_initialize (flags);
01965
01966 set_edge_can_fallthru_flag ();
01967 mark_dfs_back_edges ();
01968
01969
01970
01971 if (uncond_jump_length == 0)
01972 uncond_jump_length = get_uncond_jump_length ();
01973
01974
01975 array_size = GET_ARRAY_SIZE (last_basic_block);
01976 bbd = xmalloc (array_size * sizeof (bbro_basic_block_data));
01977 for (i = 0; i < array_size; i++)
01978 {
01979 bbd[i].start_of_trace = -1;
01980 bbd[i].end_of_trace = -1;
01981 bbd[i].heap = NULL;
01982 bbd[i].node = NULL;
01983 }
01984
01985 traces = xmalloc (n_basic_blocks * sizeof (struct trace));
01986 n_traces = 0;
01987 find_traces (&n_traces, traces);
01988 connect_traces (n_traces, traces);
01989 FREE (traces);
01990 FREE (bbd);
01991
01992 if (dump_file)
01993 dump_flow_info (dump_file);
01994
01995 if (flag_reorder_blocks_and_partition
01996 && targetm.have_named_sections)
01997 add_unlikely_executed_notes ();
01998
01999 cfg_layout_finalize ();
02000
02001 timevar_pop (TV_REORDER_BLOCKS);
02002 }
02003
02004
02005
02006
02007
02008
02009
02010 void
02011 duplicate_computed_gotos (void)
02012 {
02013 basic_block bb, new_bb;
02014 bitmap candidates;
02015 int max_size;
02016
02017 if (n_basic_blocks <= 1)
02018 return;
02019
02020 if (targetm.cannot_modify_jumps_p ())
02021 return;
02022
02023 timevar_push (TV_REORDER_BLOCKS);
02024
02025 cfg_layout_initialize (0);
02026
02027
02028
02029
02030 if (uncond_jump_length == 0)
02031 uncond_jump_length = get_uncond_jump_length ();
02032
02033 max_size = uncond_jump_length * PARAM_VALUE (PARAM_MAX_GOTO_DUPLICATION_INSNS);
02034 candidates = BITMAP_ALLOC (NULL);
02035
02036
02037
02038
02039 FOR_EACH_BB (bb)
02040 {
02041 rtx insn;
02042 edge e;
02043 edge_iterator ei;
02044 int size, all_flags;
02045
02046
02047 if (bb->next_bb != EXIT_BLOCK_PTR)
02048 bb->rbi->next = bb->next_bb;
02049
02050
02051 if (!computed_jump_p (BB_END (bb)))
02052 continue;
02053
02054
02055 if (find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX)
02056 || !can_duplicate_block_p (bb))
02057 continue;
02058
02059
02060 size = 0;
02061 FOR_BB_INSNS (bb, insn)
02062 if (INSN_P (insn))
02063 {
02064 size += get_attr_length (insn);
02065 if (size > max_size)
02066 break;
02067 }
02068 if (size > max_size)
02069 continue;
02070
02071
02072 all_flags = 0;
02073 FOR_EACH_EDGE (e, ei, bb->preds)
02074 all_flags |= e->flags;
02075 if (all_flags & EDGE_COMPLEX)
02076 continue;
02077
02078 bitmap_set_bit (candidates, bb->index);
02079 }
02080
02081
02082 if (bitmap_empty_p (candidates))
02083 goto done;
02084
02085
02086 FOR_EACH_BB (bb)
02087 {
02088 if (bb->rbi->visited)
02089 continue;
02090
02091 bb->rbi->visited = 1;
02092
02093
02094
02095
02096 if (EDGE_COUNT(bb->succs) != 1
02097 || EDGE_SUCC(bb,0)->dest == EXIT_BLOCK_PTR
02098 || EDGE_SUCC(bb,0)->dest == bb->next_bb
02099 || EDGE_COUNT(EDGE_SUCC(bb,0)->dest->preds) <= 1)
02100 continue;
02101
02102
02103 if (!bitmap_bit_p (candidates, EDGE_SUCC(bb,0)->dest->index))
02104 continue;
02105
02106 new_bb = duplicate_block (EDGE_SUCC(bb,0)->dest, EDGE_SUCC(bb,0));
02107 new_bb->rbi->next = bb->rbi->next;
02108 bb->rbi->next = new_bb;
02109 new_bb->rbi->visited = 1;
02110 }
02111
02112 done:
02113 cfg_layout_finalize ();
02114
02115 BITMAP_FREE (candidates);
02116
02117 timevar_pop (TV_REORDER_BLOCKS);
02118 }
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179 void
02180 partition_hot_cold_basic_blocks (void)
02181 {
02182 basic_block cur_bb;
02183 edge *crossing_edges;
02184 int n_crossing_edges;
02185 int max_edges = 2 * last_basic_block;
02186
02187 if (n_basic_blocks <= 1)
02188 return;
02189
02190 crossing_edges = xcalloc (max_edges, sizeof (edge));
02191
02192 cfg_layout_initialize (0);
02193
02194 FOR_EACH_BB (cur_bb)
02195 if (cur_bb->index >= 0
02196 && cur_bb->next_bb->index >= 0)
02197 cur_bb->rbi->next = cur_bb->next_bb;
02198
02199 find_rarely_executed_basic_blocks_and_crossing_edges (crossing_edges,
02200 &n_crossing_edges,
02201 &max_edges);
02202
02203 if (n_crossing_edges > 0)
02204 fix_edges_for_rarely_executed_code (crossing_edges, n_crossing_edges);
02205
02206 free (crossing_edges);
02207
02208 cfg_layout_finalize();
02209 }