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