Index: gcc/Makefile.in =================================================================== RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v retrieving revision 1.1455 diff -c -3 -p -r1.1455 Makefile.in *** gcc/Makefile.in 21 Mar 2005 17:58:06 -0000 1.1455 --- gcc/Makefile.in 22 Mar 2005 00:03:16 -0000 *************** rtlanal.o : rtlanal.c $(CONFIG_H) $(SYST *** 1877,1883 **** varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \ $(FLAGS_H) function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \ output.h $(C_PRAGMA_H) toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \ ! $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(CFGLAYOUT_H) $(TREE_GIMPLE_H) \ $(FLAGS_H) function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \ --- 1877,1883 ---- varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \ $(FLAGS_H) function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \ output.h $(C_PRAGMA_H) toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \ ! $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h $(BASIC_BLOCK_H) function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(CFGLAYOUT_H) $(TREE_GIMPLE_H) \ $(FLAGS_H) function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \ *************** lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) *** 2176,2182 **** $(RTL_H) $(GGC_H) gt-lists.h bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \ ! $(TARGET_H) function.h $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ $(BASIC_BLOCK_H) hard-reg-set.h output.h $(CFGLAYOUT_H) $(FLAGS_H) $(TIMEVAR_H) \ $(PARAMS_H) $(COVERAGE_H) --- 2176,2182 ---- $(RTL_H) $(GGC_H) gt-lists.h bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \ ! $(TARGET_H) function.h $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) errors.h tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ $(BASIC_BLOCK_H) hard-reg-set.h output.h $(CFGLAYOUT_H) $(FLAGS_H) $(TIMEVAR_H) \ $(PARAMS_H) $(COVERAGE_H) *************** STAGEPROFILE_FLAGS_TO_PASS = \ *** 3731,3737 **** # Files never linked into the final executable produces warnings about missing # profile. STAGEFEEDBACK_FLAGS_TO_PASS = \ ! CFLAGS="$(BOOT_CFLAGS) -fprofile-use" # Only build the C compiler for stage1, because that is the only one that # we can guarantee will build with the native compiler, and also it is the --- 3731,3737 ---- # Files never linked into the final executable produces warnings about missing # profile. STAGEFEEDBACK_FLAGS_TO_PASS = \ ! CFLAGS="$(BOOT_CFLAGS) -fprofile-use -freorder-blocks-and-partition" # Only build the C compiler for stage1, because that is the only one that # we can guarantee will build with the native compiler, and also it is the Index: gcc/bb-reorder.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/bb-reorder.c,v retrieving revision 1.95 diff -c -3 -p -r1.95 bb-reorder.c *** gcc/bb-reorder.c 21 Mar 2005 22:11:11 -0000 1.95 --- gcc/bb-reorder.c 22 Mar 2005 00:03:16 -0000 *************** *** 81,86 **** --- 81,87 ---- #include "tm_p.h" #include "obstack.h" #include "expr.h" + #include "errors.h" #include "params.h" /* The number of rounds. In most cases there will only be 4 rounds, but *************** typedef struct bbro_basic_block_data_def *** 119,124 **** --- 120,128 ---- /* Which trace is the bb end of (-1 means it is not an end of a trace). */ int end_of_trace; + /* Which trace is the bb in? */ + int in_trace; + /* Which heap is BB in (if any)? */ fibheap_t heap; *************** static void connect_traces (int, struct *** 169,179 **** static bool copy_bb_p (basic_block, int); static int get_uncond_jump_length (void); static bool push_to_next_round_p (basic_block, int, int, int, gcov_type); - static void add_unlikely_executed_notes (void); static void find_rarely_executed_basic_blocks_and_crossing_edges (edge *, int *, int *); - static void mark_bb_for_unlikely_executed_section (basic_block); static void add_labels_and_missing_jumps (edge *, int); static void add_reg_crossing_jump_notes (void); static void fix_up_fall_thru_edges (void); --- 173,181 ---- *************** push_to_next_round_p (basic_block bb, in *** 194,219 **** int exec_th, gcov_type count_th) { bool there_exists_another_round; - bool cold_block; bool block_not_hot_enough; - bool next_round_is_last; there_exists_another_round = round < number_of_rounds - 1; - next_round_is_last = round + 1 == number_of_rounds - 1; - - cold_block = (flag_reorder_blocks_and_partition - && BB_PARTITION (bb) == BB_COLD_PARTITION); block_not_hot_enough = (bb->frequency < exec_th || bb->count < count_th || probably_never_executed_bb_p (bb)); ! if (flag_reorder_blocks_and_partition ! && next_round_is_last ! && BB_PARTITION (bb) != BB_COLD_PARTITION) ! return false; ! else if (there_exists_another_round ! && (cold_block || block_not_hot_enough)) return true; else return false; --- 196,211 ---- int exec_th, gcov_type count_th) { bool there_exists_another_round; bool block_not_hot_enough; there_exists_another_round = round < number_of_rounds - 1; block_not_hot_enough = (bb->frequency < exec_th || bb->count < count_th || probably_never_executed_bb_p (bb)); ! if (there_exists_another_round ! && block_not_hot_enough) return true; else return false; *************** find_traces (int *n_traces, struct trace *** 237,244 **** cold blocks (and ONLY the cold blocks). */ number_of_rounds = N_ROUNDS - 1; - if (flag_reorder_blocks_and_partition) - number_of_rounds = N_ROUNDS; /* Insert entry points of function into heap. */ heap = fibheap_new (); --- 229,234 ---- *************** find_traces_1_round (int branch_th, int *** 434,444 **** struct trace *traces, int *n_traces, int round, fibheap_t *heap, int number_of_rounds) { - /* The following variable refers to the last round in which non-"cold" - blocks may be collected into a trace. */ - - int last_round = N_ROUNDS - 1; - /* Heap for discarded basic blocks which are possible starting points for the next round. */ fibheap_t new_heap = fibheap_new (); --- 424,429 ---- *************** find_traces_1_round (int branch_th, int *** 481,486 **** --- 466,472 ---- trace->first = bb; trace->round = round; trace->length = 0; + bbd[bb->index].in_trace = *n_traces; (*n_traces)++; do *************** find_traces_1_round (int branch_th, int *** 514,521 **** && e->dest->rbi->visited != *n_traces) continue; ! if (BB_PARTITION (e->dest) == BB_COLD_PARTITION ! && round < last_round) continue; prob = e->probability; --- 500,506 ---- && e->dest->rbi->visited != *n_traces) continue; ! if (BB_PARTITION (e->dest) != BB_PARTITION (bb)) continue; prob = e->probability; *************** find_traces_1_round (int branch_th, int *** 646,651 **** --- 631,638 ---- best_edge->dest->index, bb->index); } bb->rbi->next = best_edge->dest; + bbd[best_edge->dest->index].in_trace = + (*n_traces) - 1; bb = rotate_loop (best_edge, trace, *n_traces); } } *************** find_traces_1_round (int branch_th, int *** 658,663 **** --- 645,651 ---- { bb = copy_bb (best_edge->dest, best_edge, bb, *n_traces); + trace->length++; } } } *************** find_traces_1_round (int branch_th, int *** 695,701 **** && !e->dest->rbi->visited && single_pred_p (e->dest) && !(e->flags & EDGE_CROSSING) ! && single_succ_p (e->dest) == 1 && (single_succ_edge (e->dest)->flags & EDGE_CAN_FALLTHRU) && !(single_succ_edge (e->dest)->flags & EDGE_COMPLEX) --- 683,689 ---- && !e->dest->rbi->visited && single_pred_p (e->dest) && !(e->flags & EDGE_CROSSING) ! && single_succ_p (e->dest) && (single_succ_edge (e->dest)->flags & EDGE_CAN_FALLTHRU) && !(single_succ_edge (e->dest)->flags & EDGE_COMPLEX) *************** find_traces_1_round (int branch_th, int *** 710,715 **** --- 698,704 ---- } bb->rbi->next = best_edge->dest; + bbd[best_edge->dest->index].in_trace = (*n_traces) - 1; bb = best_edge->dest; } } *************** copy_bb (basic_block old_bb, edge e, bas *** 788,793 **** --- 777,783 ---- for (i = array_size; i < new_size; i++) { bbd[i].start_of_trace = -1; + bbd[i].in_trace = -1; bbd[i].end_of_trace = -1; bbd[i].heap = NULL; bbd[i].node = NULL; *************** copy_bb (basic_block old_bb, edge e, bas *** 802,807 **** --- 792,799 ---- } } + bbd[new_bb->index].in_trace = trace; + return new_bb; } *************** static void *** 899,909 **** connect_traces (int n_traces, struct trace *traces) { int i; - int unconnected_hot_trace_count = 0; - bool cold_connected = true; bool *connected; ! bool *cold_traces; int last_trace; int freq_threshold; gcov_type count_threshold; --- 891,901 ---- connect_traces (int n_traces, struct trace *traces) { int i; bool *connected; ! bool two_passes; int last_trace; + int current_pass; + int current_partition; int freq_threshold; gcov_type count_threshold; *************** connect_traces (int n_traces, struct tra *** 915,980 **** connected = xcalloc (n_traces, sizeof (bool)); last_trace = -1; ! ! /* If we are partitioning hot/cold basic blocks, mark the cold ! traces as already connected, to remove them from consideration ! for connection to the hot traces. After the hot traces have all ! been connected (determined by "unconnected_hot_trace_count"), we ! will go back and connect the cold traces. */ ! ! cold_traces = xcalloc (n_traces, sizeof (bool)); if (flag_reorder_blocks_and_partition) ! for (i = 0; i < n_traces; i++) ! { ! if (BB_PARTITION (traces[i].first) == BB_COLD_PARTITION) ! { ! connected[i] = true; ! cold_traces[i] = true; ! cold_connected = false; ! } ! else ! unconnected_hot_trace_count++; ! } ! ! for (i = 0; i < n_traces || !cold_connected ; i++) { int t = i; int t2; edge e, best; int best_len; ! /* If we are partitioning hot/cold basic blocks, check to see ! if all the hot traces have been connected. If so, go back ! and mark the cold traces as unconnected so we can connect ! them up too. Re-set "i" to the first (unconnected) cold ! trace. Use flag "cold_connected" to make sure we don't do ! this step more than once. */ ! ! if (flag_reorder_blocks_and_partition ! && (i >= n_traces || unconnected_hot_trace_count <= 0) ! && !cold_connected) { ! int j; ! int first_cold_trace = -1; ! ! for (j = 0; j < n_traces; j++) ! if (cold_traces[j]) ! { ! connected[j] = false; ! if (first_cold_trace == -1) ! first_cold_trace = j; ! } ! i = t = first_cold_trace; ! cold_connected = true; } ! if (connected[t]) continue; connected[t] = true; - if (unconnected_hot_trace_count > 0) - unconnected_hot_trace_count--; /* Find the predecessor traces. */ for (t2 = t; t2 > 0;) --- 907,953 ---- connected = xcalloc (n_traces, sizeof (bool)); last_trace = -1; ! current_pass = 1; ! current_partition = BB_PARTITION (traces[0].first); ! two_passes = false; if (flag_reorder_blocks_and_partition) ! for (i = 0; i < n_traces && !two_passes; i++) ! if (BB_PARTITION (traces[0].first) ! != BB_PARTITION (traces[i].first)) ! two_passes = true; ! ! for (i = 0; i < n_traces || (two_passes && current_pass == 1) ; i++) { int t = i; int t2; edge e, best; int best_len; ! if (i >= n_traces) { ! if (two_passes && current_pass == 1) ! { ! i = 0; ! t = i; ! current_pass = 2; ! if (current_partition == BB_HOT_PARTITION) ! current_partition = BB_COLD_PARTITION; ! else ! current_partition = BB_HOT_PARTITION; ! } ! else ! abort (); } ! if (connected[t]) continue; + if (two_passes + && BB_PARTITION (traces[t].first) != current_partition) + continue; + connected[t] = true; /* Find the predecessor traces. */ for (t2 = t; t2 > 0;) *************** connect_traces (int n_traces, struct tra *** 991,996 **** --- 964,970 ---- && !(e->flags & EDGE_COMPLEX) && bbd[si].end_of_trace >= 0 && !connected[bbd[si].end_of_trace] + && (BB_PARTITION (e->src) == current_partition) && (!best || e->probability > best->probability || (e->probability == best->probability *************** connect_traces (int n_traces, struct tra *** 1006,1014 **** t2 = bbd[best->src->index].end_of_trace; connected[t2] = true; - if (unconnected_hot_trace_count > 0) - unconnected_hot_trace_count--; - if (dump_file) { fprintf (dump_file, "Connection: %d %d\n", --- 980,985 ---- *************** connect_traces (int n_traces, struct tra *** 1039,1044 **** --- 1010,1016 ---- && !(e->flags & EDGE_COMPLEX) && bbd[di].start_of_trace >= 0 && !connected[bbd[di].start_of_trace] + && (BB_PARTITION (e->dest) == current_partition) && (!best || e->probability > best->probability || (e->probability == best->probability *************** connect_traces (int n_traces, struct tra *** 1059,1066 **** t = bbd[best->dest->index].start_of_trace; traces[last_trace].last->rbi->next = traces[t].first; connected[t] = true; - if (unconnected_hot_trace_count > 0) - unconnected_hot_trace_count--; last_trace = t; } else --- 1031,1036 ---- *************** connect_traces (int n_traces, struct tra *** 1101,1106 **** --- 1071,1077 ---- && !(e2->flags & EDGE_COMPLEX) && bbd[di].start_of_trace >= 0 && !connected[bbd[di].start_of_trace] + && (BB_PARTITION (e2->dest) == current_partition) && (EDGE_FREQUENCY (e2) >= freq_threshold) && (e2->count >= count_threshold) && (!best2 *************** connect_traces (int n_traces, struct tra *** 1153,1160 **** t = bbd[next_bb->index].start_of_trace; traces[last_trace].last->rbi->next = traces[t].first; connected[t] = true; - if (unconnected_hot_trace_count > 0) - unconnected_hot_trace_count--; last_trace = t; } else --- 1124,1129 ---- *************** connect_traces (int n_traces, struct tra *** 1178,1184 **** } FREE (connected); - FREE (cold_traces); } /* Return true when BB can and should be copied. CODE_MAY_GROW is true --- 1147,1152 ---- *************** get_uncond_jump_length (void) *** 1242,1259 **** return length; } - static void - add_unlikely_executed_notes (void) - { - basic_block bb; - - /* Add the UNLIKELY_EXECUTED_NOTES to each cold basic block. */ - - FOR_EACH_BB (bb) - if (BB_PARTITION (bb) == BB_COLD_PARTITION) - mark_bb_for_unlikely_executed_section (bb); - } - /* Find the basic blocks that are rarely executed and need to be moved to a separate section of the .o file (to cut down on paging and improve cache locality). */ --- 1210,1215 ---- *************** find_rarely_executed_basic_blocks_and_cr *** 1282,1299 **** } } - /* Since all "hot" basic blocks will eventually be scheduled before all - cold basic blocks, make *sure* the real function entry block is in - the hot partition (if there is one). */ - - if (has_hot_blocks) - FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) - if (e->dest->index >= 0) - { - BB_SET_PARTITION (e->dest, BB_HOT_PARTITION); - break; - } - /* Mark every edge that crosses between sections. */ i = 0; --- 1238,1243 ---- *************** find_rarely_executed_basic_blocks_and_cr *** 1322,1360 **** *n_crossing_edges = i; } - /* Add NOTE_INSN_UNLIKELY_EXECUTED_CODE to top of basic block. This note - is later used to mark the basic block to be put in the - unlikely-to-be-executed section of the .o file. */ - - static void - mark_bb_for_unlikely_executed_section (basic_block bb) - { - rtx cur_insn; - rtx insert_insn = NULL; - rtx new_note; - - /* Insert new NOTE immediately after BASIC_BLOCK note. */ - - for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb)); - cur_insn = NEXT_INSN (cur_insn)) - if (GET_CODE (cur_insn) == NOTE - && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK) - { - insert_insn = cur_insn; - break; - } - - /* If basic block does not contain a NOTE_INSN_BASIC_BLOCK, there is - a major problem. */ - gcc_assert (insert_insn); - - /* Insert note and assign basic block number to it. */ - - new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE, - insert_insn); - NOTE_BASIC_BLOCK (new_note) = bb; - } - /* If any destination of a crossing edge does not have a label, add label; Convert any fall-through crossing edges (for blocks that do not contain a jump) to unconditional jumps. */ --- 1266,1271 ---- *************** fix_crossing_unconditional_branches (voi *** 1782,1787 **** --- 1693,1702 ---- FOR_EACH_BB (cur_bb) { last_insn = BB_END (cur_bb); + + if (EDGE_COUNT (cur_bb->succs) < 1) + continue; + succ = EDGE_SUCC (cur_bb, 0); /* Check to see if bb ends in a crossing (unconditional) jump. At *************** add_reg_crossing_jump_notes (void) *** 1864,1882 **** (e->src))); } ! /* Basic blocks containing NOTE_INSN_UNLIKELY_EXECUTED_CODE will be ! put in a separate section of the .o file, to reduce paging and ! improve cache performance (hopefully). This can result in bits of ! code from the same function being widely separated in the .o file. ! However this is not obvious to the current bb structure. Therefore ! we must take care to ensure that: 1). There are no fall_thru edges ! that cross between sections; 2). For those architectures which ! have "short" conditional branches, all conditional branches that ! attempt to cross between sections are converted to unconditional ! branches; and, 3). For those architectures which have "short" ! unconditional branches, all unconditional branches that attempt ! to cross between sections are converted to indirect jumps. ! The code for fixing up fall_thru edges that cross between hot and cold basic blocks does so by creating new basic blocks containing unconditional branches to the appropriate label in the "other" --- 1779,1797 ---- (e->src))); } ! /* Hot and cold basic blocks are partitioneed and put in separate ! sections of the .o file, to reduce paging and improve cache ! performance (hopefully). This can result in bits of code from the ! same function being widely separated in the .o file. However this ! is not obvious to the current bb structure. Therefore we must take ! care to ensure that: 1). There are no fall_thru edges that cross ! between sections; 2). For those architectures which have "short" ! conditional branches, all conditional branches that attempt to ! cross between sections are converted to unconditional branches; ! and, 3). For those architectures which have "short" unconditional ! branches, all unconditional branches that attempt to cross between ! sections are converted to indirect jumps. ! The code for fixing up fall_thru edges that cross between hot and cold basic blocks does so by creating new basic blocks containing unconditional branches to the appropriate label in the "other" *************** fix_edges_for_rarely_executed_code (edge *** 1942,1947 **** --- 1857,1900 ---- } } + /* Verify, in the basic block chain, that there is at most one switch + between hot/cold partitions. This is modelled on + rtl_verify_flow_info_1, but it cannot go inside that function + because this condition will not be true until after + reorder_basic_blocks is called. */ + + static void + verify_hot_cold_block_grouping (void) + { + basic_block bb; + int err = 0; + bool switched_sections = false; + int current_partition = 0; + + FOR_EACH_BB (bb) + { + if (!current_partition) + current_partition = BB_PARTITION (bb); + if (BB_PARTITION (bb) != current_partition) + { + if (switched_sections) + { + error ("Multiple hot/cold transitions found (bb %i)", + bb->index); + err = 1; + } + else + { + switched_sections = true; + current_partition = BB_PARTITION (bb); + } + } + } + + if (err) + internal_error ("verify_hot_cold_block_grouping failed"); + } + /* Reorder basic blocks. The main entry point to this file. FLAGS is the set of flags to pass to cfg_layout_initialize(). */ *************** reorder_basic_blocks (unsigned int flags *** 1976,1981 **** --- 1929,1935 ---- for (i = 0; i < array_size; i++) { bbd[i].start_of_trace = -1; + bbd[i].in_trace = -1; bbd[i].end_of_trace = -1; bbd[i].heap = NULL; bbd[i].node = NULL; *************** reorder_basic_blocks (unsigned int flags *** 1991,2005 **** if (dump_file) dump_flow_info (dump_file); - if (flag_reorder_blocks_and_partition - && targetm.have_named_sections) - add_unlikely_executed_notes (); - cfg_layout_finalize (); timevar_pop (TV_REORDER_BLOCKS); } /* Duplicate the blocks containing computed gotos. This basically unfactors computed gotos that were factored early on in the compilation process to speed up edge based data flow. We used to not unfactoring them again, --- 1945,1986 ---- if (dump_file) dump_flow_info (dump_file); cfg_layout_finalize (); + verify_hot_cold_block_grouping (); timevar_pop (TV_REORDER_BLOCKS); } + /* Determine which partition the first basic block in the function + belongs to, then find the first basic block in the current function + that belongs to a different section, and insert a + NOTE_INSN_SWITCH_TEXT_SECTIONS note immediately before it in the + instruction stream. When writing out the assembly code, + encountering this note will make the compiler switch between the + hot and cold text sections. */ + + void + insert_section_boundary_note (void) + { + basic_block bb; + rtx new_note; + int first_partition = 0; + + if (flag_reorder_blocks_and_partition + && targetm.have_named_sections) + FOR_EACH_BB (bb) + { + if (!first_partition) + first_partition = BB_PARTITION (bb); + if (BB_PARTITION (bb) != first_partition) + { + new_note = emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS, + BB_HEAD (bb)); + break; + } + } + } + /* Duplicate the blocks containing computed gotos. This basically unfactors computed gotos that were factored early on in the compilation process to speed up edge based data flow. We used to not unfactoring them again, *************** duplicate_computed_gotos (void) *** 2041,2047 **** /* If the block ends in a computed jump and it is small enough, make it a candidate for duplication. */ ! if (computed_jump_p (BB_END (bb))) { rtx insn; int size = 0; --- 2022,2029 ---- /* If the block ends in a computed jump and it is small enough, make it a candidate for duplication. */ ! if (computed_jump_p (BB_END (bb)) ! && !find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX)) { rtx insn; int size = 0; *************** done: *** 2110,2124 **** function above). This optimization checks the feedback information to determine ! which basic blocks are hot/cold and causes reorder_basic_blocks to ! add NOTE_INSN_UNLIKELY_EXECUTED_CODE to non-hot basic blocks. The ! presence or absence of this note is later used for writing out ! sections in the .o file. Because hot and cold sections can be ! arbitrarily large (within the bounds of memory), far beyond the ! size of a single function, it is necessary to fix up all edges that ! cross section boundaries, to make sure the instructions used can ! actually span the required distance. The fixes are described ! below. Fall-through edges must be changed into jumps; it is not safe or legal to fall through across a section boundary. Whenever a --- 2092,2105 ---- function above). This optimization checks the feedback information to determine ! which basic blocks are hot/cold, updates flags on the basic blocks ! to indicate which section they belong in. This information is ! later used for writing out sections in the .o file. Because hot ! and cold sections can be arbitrarily large (within the bounds of ! memory), far beyond the size of a single function, it is necessary ! to fix up all edges that cross section boundaries, to make sure the ! instructions used can actually span the required distance. The ! fixes are described below. Fall-through edges must be changed into jumps; it is not safe or legal to fall through across a section boundary. Whenever a Index: gcc/cfgcleanup.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v retrieving revision 1.142 diff -c -3 -p -r1.142 cfgcleanup.c *** gcc/cfgcleanup.c 11 Mar 2005 09:04:48 -0000 1.142 --- gcc/cfgcleanup.c 22 Mar 2005 00:03:16 -0000 *************** try_simplify_condjump (basic_block cbran *** 155,163 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block) ! || (cbranch_jump_edge->flags & EDGE_CROSSING))) return false; /* The conditional branch must target the block after the --- 155,162 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block) ! || (cbranch_jump_edge->flags & EDGE_CROSSING)) return false; /* The conditional branch must target the block after the *************** try_forward_edges (int mode, basic_block *** 435,442 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)) return false; for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); ) --- 434,440 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)) return false; for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); ) *************** try_forward_edges (int mode, basic_block *** 471,478 **** bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && first != EXIT_BLOCK_PTR && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX)) return false; --- 469,475 ---- bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (first != EXIT_BLOCK_PTR && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX)) return false; *************** merge_blocks_move_predecessor_nojumps (b *** 684,692 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (BB_PARTITION (a) != BB_PARTITION (b) ! || find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX))) return; barrier = next_nonnote_insn (BB_END (a)); --- 681,687 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (a) != BB_PARTITION (b)) return; barrier = next_nonnote_insn (BB_END (a)); *************** merge_blocks_move_successor_nojumps (bas *** 742,750 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (a) != BB_PARTITION (b))) return; real_b_end = BB_END (b); --- 737,743 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (a) != BB_PARTITION (b)) return; real_b_end = BB_END (b); *************** merge_blocks_move (edge e, basic_block b *** 814,823 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX) ! || find_reg_note (BB_END (c), REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (b) != BB_PARTITION (c))) return NULL; --- 807,813 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (b) != BB_PARTITION (c)) return NULL; *************** try_crossjump_bb (int mode, basic_block *** 1725,1733 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (BB_PARTITION (EDGE_PRED (bb, 0)->src) != BB_PARTITION (EDGE_PRED (bb, 1)->src) ! || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING))) return false; /* It is always cheapest to redirect a block that ends in a branch to --- 1715,1723 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (EDGE_PRED (bb, 0)->src) != ! BB_PARTITION (EDGE_PRED (bb, 1)->src) ! || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING)) return false; /* It is always cheapest to redirect a block that ends in a branch to Index: gcc/cfglayout.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cfglayout.c,v retrieving revision 1.82 diff -c -3 -p -r1.82 cfglayout.c *** gcc/cfglayout.c 12 Mar 2005 00:34:03 -0000 1.82 --- gcc/cfglayout.c 22 Mar 2005 00:03:16 -0000 *************** static void change_scope (rtx, tree, tre *** 51,57 **** void verify_insn_chain (void); static void fixup_fallthru_exit_predecessor (void); static tree insn_scope (rtx); - static void update_unlikely_executed_notes (basic_block); rtx unlink_insn_chain (rtx first, rtx last) --- 51,56 ---- *************** fixup_reorder_chain (void) *** 778,805 **** section boundaries). */ BB_COPY_PARTITION (e_fall->src, single_pred (bb)); if (flag_reorder_blocks_and_partition ! && targetm.have_named_sections) ! { ! if (BB_PARTITION (single_pred (bb)) == BB_COLD_PARTITION) ! { ! rtx new_note; ! rtx note = BB_HEAD (e_fall->src); ! ! while (!INSN_P (note) ! && note != BB_END (e_fall->src)) ! note = NEXT_INSN (note); ! ! new_note = emit_note_before ! (NOTE_INSN_UNLIKELY_EXECUTED_CODE, ! note); ! NOTE_BASIC_BLOCK (new_note) = bb; ! } ! if (JUMP_P (BB_END (bb)) ! && !any_condjump_p (BB_END (bb)) ! && (single_succ_edge (bb)->flags & EDGE_CROSSING)) ! REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST ! (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); ! } } } --- 777,788 ---- section boundaries). */ BB_COPY_PARTITION (e_fall->src, single_pred (bb)); if (flag_reorder_blocks_and_partition ! && targetm.have_named_sections ! && JUMP_P (BB_END (bb)) ! && !any_condjump_p (BB_END (bb)) ! && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING)) ! REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST ! (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); } } *************** fixup_reorder_chain (void) *** 834,841 **** bb->index = index; BASIC_BLOCK (index) = bb; - update_unlikely_executed_notes (bb); - bb->prev_bb = prev_bb; prev_bb->next_bb = bb; } --- 817,822 ---- *************** fixup_reorder_chain (void) *** 857,877 **** } } - /* Update the basic block number information in any - NOTE_INSN_UNLIKELY_EXECUTED_CODE notes within the basic block. */ - - static void - update_unlikely_executed_notes (basic_block bb) - { - rtx cur_insn; - - for (cur_insn = BB_HEAD (bb); cur_insn != BB_END (bb); - cur_insn = NEXT_INSN (cur_insn)) - if (NOTE_P (cur_insn) - && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_UNLIKELY_EXECUTED_CODE) - NOTE_BASIC_BLOCK (cur_insn) = bb; - } - /* Perform sanity checks on the insn chain. 1. Check that next/prev pointers are consistent in both the forward and reverse direction. --- 838,843 ---- *************** duplicate_insn_chain (rtx from, rtx to) *** 1040,1046 **** break; case NOTE_INSN_REPEATED_LINE_NUMBER: ! case NOTE_INSN_UNLIKELY_EXECUTED_CODE: emit_note_copy (insn); break; --- 1006,1012 ---- break; case NOTE_INSN_REPEATED_LINE_NUMBER: ! case NOTE_INSN_SWITCH_TEXT_SECTIONS: emit_note_copy (insn); break; Index: gcc/cfglayout.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/cfglayout.h,v retrieving revision 1.16 diff -c -3 -p -r1.16 cfglayout.h *** gcc/cfglayout.h 15 Oct 2004 14:47:06 -0000 1.16 --- gcc/cfglayout.h 22 Mar 2005 00:03:16 -0000 *************** extern void reemit_insn_block_notes (voi *** 32,38 **** extern bool can_copy_bbs_p (basic_block *, unsigned); extern void copy_bbs (basic_block *, unsigned, basic_block *, edge *, unsigned, edge *, struct loop *); - extern bool scan_ahead_for_unlikely_executed_note (rtx); extern rtx duplicate_insn_chain (rtx, rtx); #endif /* GCC_CFGLAYOUT_H */ --- 32,37 ---- Index: gcc/cfgrtl.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v retrieving revision 1.163 diff -c -3 -p -r1.163 cfgrtl.c *** gcc/cfgrtl.c 11 Mar 2005 09:04:51 -0000 1.163 --- gcc/cfgrtl.c 22 Mar 2005 00:03:16 -0000 *************** static int *** 92,99 **** can_delete_note_p (rtx note) { return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED ! || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK ! || NOTE_LINE_NUMBER (note) == NOTE_INSN_UNLIKELY_EXECUTED_CODE); } /* True if a given label can be deleted. */ --- 92,98 ---- can_delete_note_p (rtx note) { return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED ! || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK); } /* True if a given label can be deleted. */ *************** rtl_can_merge_blocks (basic_block a,basi *** 616,625 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX) ! || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (a) != BB_PARTITION (b))) return false; /* There must be exactly one edge in between the blocks. */ --- 615,621 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (a) != BB_PARTITION (b)) return false; /* There must be exactly one edge in between the blocks. */ *************** try_redirect_by_replacing_jump (edge e, *** 678,686 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (src) != BB_PARTITION (target))) return NULL; /* We can replace or remove a complex jump only when we have exactly --- 674,681 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (src) != BB_PARTITION (target)) return NULL; /* We can replace or remove a complex jump only when we have exactly *************** force_nonfallthru_and_redirect (edge e, *** 1108,1136 **** BB_COPY_PARTITION (jump_block, e->src); if (flag_reorder_blocks_and_partition ! && targetm.have_named_sections) ! { ! if (BB_PARTITION (jump_block) == BB_COLD_PARTITION) ! { ! rtx bb_note, new_note; ! for (bb_note = BB_HEAD (jump_block); ! bb_note && bb_note != NEXT_INSN (BB_END (jump_block)); ! bb_note = NEXT_INSN (bb_note)) ! if (NOTE_P (bb_note) ! && NOTE_LINE_NUMBER (bb_note) == NOTE_INSN_BASIC_BLOCK) ! break; ! new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE, ! bb_note); ! NOTE_BASIC_BLOCK (new_note) = jump_block; ! } ! if (JUMP_P (BB_END (jump_block)) ! && !any_condjump_p (BB_END (jump_block)) ! && (single_succ_edge (jump_block)->flags & EDGE_CROSSING)) ! REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST ! (REG_CROSSING_JUMP, NULL_RTX, ! REG_NOTES (BB_END (jump_block))); ! } ! /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); new_edge->probability = e->probability; --- 1103,1118 ---- BB_COPY_PARTITION (jump_block, e->src); if (flag_reorder_blocks_and_partition ! && targetm.have_named_sections ! && JUMP_P (BB_END (jump_block)) ! && !any_condjump_p (BB_END (jump_block)) ! && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING)) ! REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, ! NULL_RTX, ! REG_NOTES ! (BB_END ! (jump_block))); ! /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); new_edge->probability = e->probability; *************** commit_one_edge_insertion (edge e, int w *** 1576,1585 **** tmp = NEXT_INSN (tmp); if (NOTE_INSN_BASIC_BLOCK_P (tmp)) tmp = NEXT_INSN (tmp); - if (tmp - && NOTE_P (tmp) - && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE) - tmp = NEXT_INSN (tmp); if (tmp == BB_HEAD (bb)) before = tmp; else if (tmp) --- 1560,1565 ---- *************** commit_one_edge_insertion (edge e, int w *** 1629,1635 **** && BB_PARTITION (e->src) == BB_COLD_PARTITION && !(e->flags & EDGE_CROSSING)) { ! rtx bb_note, new_note, cur_insn; bb_note = NULL_RTX; for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb)); --- 1609,1615 ---- && BB_PARTITION (e->src) == BB_COLD_PARTITION && !(e->flags & EDGE_CROSSING)) { ! rtx bb_note, cur_insn; bb_note = NULL_RTX; for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb)); *************** commit_one_edge_insertion (edge e, int w *** 1641,1656 **** break; } - new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE, - bb_note); - NOTE_BASIC_BLOCK (new_note) = bb; if (JUMP_P (BB_END (bb)) && !any_condjump_p (BB_END (bb)) && (single_succ_edge (bb)->flags & EDGE_CROSSING)) REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); - if (after == bb_note) - after = new_note; } } } --- 1621,1631 ---- *************** cfg_layout_can_merge_blocks_p (basic_blo *** 2717,2726 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX) ! || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX) ! || BB_PARTITION (a) != BB_PARTITION (b))) return false; /* There must be exactly one edge in between the blocks. */ --- 2692,2698 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (BB_PARTITION (a) != BB_PARTITION (b)) return false; /* There must be exactly one edge in between the blocks. */ Index: gcc/dbxout.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/dbxout.c,v retrieving revision 1.221 diff -c -3 -p -r1.221 dbxout.c *** gcc/dbxout.c 21 Feb 2005 10:06:20 -0000 1.221 --- gcc/dbxout.c 22 Mar 2005 00:03:16 -0000 *************** static int pending_bincls = 0; *** 275,281 **** static const char *base_input_file; #ifdef DEBUG_SYMS_TEXT ! #define FORCE_TEXT function_section (current_function_decl); #else #define FORCE_TEXT #endif --- 275,281 ---- static const char *base_input_file; #ifdef DEBUG_SYMS_TEXT ! #define FORCE_TEXT current_function_section (current_function_decl); #else #define FORCE_TEXT #endif *************** const struct gcc_debug_hooks dbx_debug_h *** 378,384 **** debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ ! debug_nothing_rtx /* var_location */ }; #endif /* DBX_DEBUGGING_INFO */ --- 378,385 ---- debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ ! debug_nothing_rtx, /* var_location */ ! debug_nothing_void /* switch_text_section */ }; #endif /* DBX_DEBUGGING_INFO */ *************** const struct gcc_debug_hooks xcoff_debug *** 408,414 **** debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ ! debug_nothing_rtx /* var_location */ }; #endif /* XCOFF_DEBUGGING_INFO */ --- 409,416 ---- debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ ! debug_nothing_rtx, /* var_location */ ! debug_nothing_void /* switch_text_section */ }; #endif /* XCOFF_DEBUGGING_INFO */ *************** dbxout_function_end (tree decl) *** 932,940 **** #ifdef DBX_OUTPUT_NFUN DBX_OUTPUT_NFUN (asm_out_file, lscope_label_name, current_function_decl); #else ! dbxout_begin_empty_stabs (N_FUN); ! dbxout_stab_value_label_diff (lscope_label_name, ! XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); #endif --- 934,954 ---- #ifdef DBX_OUTPUT_NFUN DBX_OUTPUT_NFUN (asm_out_file, lscope_label_name, current_function_decl); #else ! if (flag_reorder_blocks_and_partition) ! { ! dbxout_begin_empty_stabs (N_FUN); ! dbxout_stab_value_label_diff (hot_section_end_label, hot_section_label); ! dbxout_begin_empty_stabs (N_FUN); ! dbxout_stab_value_label_diff (cold_section_end_label, ! unlikely_section_label); ! } ! else ! { ! dbxout_begin_empty_stabs (N_FUN); ! dbxout_stab_value_label_diff (lscope_label_name, ! XSTR (XEXP (DECL_RTL (current_function_decl), ! 0), 0)); ! } #endif Index: gcc/debug.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/debug.c,v retrieving revision 1.17 diff -c -3 -p -r1.17 debug.c *** gcc/debug.c 12 Feb 2004 21:42:17 -0000 1.17 --- gcc/debug.c 22 Mar 2005 00:03:16 -0000 *************** const struct gcc_debug_hooks do_nothing_ *** 47,53 **** debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx /* var_location */ }; /* This file contains implementations of each debug hook that do --- 47,54 ---- debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx, /* var_location */ ! debug_nothing_void /* switch_text_section */ }; /* This file contains implementations of each debug hook that do Index: gcc/debug.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/debug.h,v retrieving revision 1.19 diff -c -3 -p -r1.19 debug.h *** gcc/debug.h 12 Feb 2004 21:42:17 -0000 1.19 --- gcc/debug.h 22 Mar 2005 00:03:16 -0000 *************** struct gcc_debug_hooks *** 119,124 **** --- 119,128 ---- /* Called from final_scan_insn for any NOTE_INSN_VAR_LOCATION note. */ void (* var_location) (rtx); + + /* Called from final_scan_insn if there is a switch between hot and cold + text sections. */ + void (* switch_text_section) (void); }; extern const struct gcc_debug_hooks *debug_hooks; Index: gcc/dwarf2out.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v retrieving revision 1.572 diff -c -3 -p -r1.572 dwarf2out.c *** gcc/dwarf2out.c 19 Mar 2005 03:06:51 -0000 1.572 --- gcc/dwarf2out.c 22 Mar 2005 00:03:17 -0000 *************** typedef struct dw_fde_struct GTY(()) *** 253,258 **** --- 253,263 ---- const char *dw_fde_begin; const char *dw_fde_current_label; const char *dw_fde_end; + const char *dw_fde_hot_section_label; + const char *dw_fde_hot_section_end_label; + const char *dw_fde_unlikely_section_label; + const char *dw_fde_unlikely_section_end_label; + bool dw_fde_switched_sections; dw_cfi_ref dw_fde_cfi; unsigned funcdef_number; unsigned all_throwers_are_sibcalls : 1; *************** output_call_frame_info (int for_eh) *** 2273,2289 **** dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref, "FDE initial location"); ! dw2_asm_output_delta (size_of_encoded_value (fde_encoding), ! fde->dw_fde_end, fde->dw_fde_begin, ! "FDE address range"); } else { dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, "FDE initial location"); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, ! fde->dw_fde_end, fde->dw_fde_begin, ! "FDE address range"); } if (augmentation[0]) --- 2278,2334 ---- dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref, "FDE initial location"); ! if (fde->dw_fde_switched_sections) ! { ! rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode, ! fde->dw_fde_unlikely_section_label); ! rtx sym_ref3= gen_rtx_SYMBOL_REF (Pmode, ! fde->dw_fde_hot_section_label); ! SYMBOL_REF_FLAGS (sym_ref2) |= SYMBOL_FLAG_LOCAL; ! SYMBOL_REF_FLAGS (sym_ref3) |= SYMBOL_FLAG_LOCAL; ! dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref3, ! "FDE initial location"); ! dw2_asm_output_delta (size_of_encoded_value (fde_encoding), ! fde->dw_fde_hot_section_end_label, ! fde->dw_fde_hot_section_label, ! "FDE address range"); ! dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref2, ! "FDE initial location"); ! dw2_asm_output_delta (size_of_encoded_value (fde_encoding), ! fde->dw_fde_unlikely_section_end_label, ! fde->dw_fde_unlikely_section_label, ! "FDE address range"); ! } ! else ! dw2_asm_output_delta (size_of_encoded_value (fde_encoding), ! fde->dw_fde_end, fde->dw_fde_begin, ! "FDE address range"); } else { dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, "FDE initial location"); ! if (fde->dw_fde_switched_sections) ! { ! dw2_asm_output_addr (DWARF2_ADDR_SIZE, ! fde->dw_fde_hot_section_label, ! "FDE initial location"); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, ! fde->dw_fde_hot_section_end_label, ! fde->dw_fde_hot_section_label, ! "FDE address range"); ! dw2_asm_output_addr (DWARF2_ADDR_SIZE, ! fde->dw_fde_unlikely_section_label, ! "FDE initial location"); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, ! fde->dw_fde_unlikely_section_end_label, ! fde->dw_fde_unlikely_section_label, ! "FDE address range"); ! } ! else ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, ! fde->dw_fde_end, fde->dw_fde_begin, ! "FDE address range"); } if (augmentation[0]) *************** dwarf2out_begin_prologue (unsigned int l *** 2409,2414 **** --- 2454,2462 ---- fde->decl = current_function_decl; fde->dw_fde_begin = dup_label; fde->dw_fde_current_label = NULL; + fde->dw_fde_hot_section_end_label = NULL; + fde->dw_fde_unlikely_section_label = NULL; + fde->dw_fde_switched_sections = false; fde->dw_fde_end = NULL; fde->dw_fde_cfi = NULL; fde->funcdef_number = current_function_funcdef_no; *************** static void dwarf2out_imported_module_or *** 3413,3418 **** --- 3461,3467 ---- static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx); static void dwarf2out_begin_function (tree); + static void dwarf2out_switch_text_section (void); /* The debug hooks structure. */ *************** const struct gcc_debug_hooks dwarf2_debu *** 3444,3450 **** dwarf2out_abstract_function, /* outlining_inline_function */ debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! dwarf2out_var_location }; #endif --- 3493,3500 ---- dwarf2out_abstract_function, /* outlining_inline_function */ debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! dwarf2out_var_location, ! dwarf2out_switch_text_section }; #endif *************** struct var_loc_node GTY ((chain_next ("% *** 3645,3650 **** --- 3695,3701 ---- { rtx GTY (()) var_loc_note; const char * GTY (()) label; + const char * GTY (()) section_label; struct var_loc_node * GTY (()) next; }; *************** add_loc_descr_to_loc_list (dw_loc_list_r *** 6769,6774 **** --- 6820,6839 ---- *d = new_loc_list (descr, begin, end, section, 0); } + static void + dwarf2out_switch_text_section (void) + { + dw_fde_ref fde; + + fde = &fde_table[fde_table_in_use - 1]; + fde->dw_fde_switched_sections = true; + fde->dw_fde_hot_section_label = xstrdup (hot_section_label); + fde->dw_fde_hot_section_end_label = xstrdup (hot_section_end_label); + fde->dw_fde_unlikely_section_label = xstrdup (unlikely_section_label); + fde->dw_fde_unlikely_section_end_label = xstrdup (cold_section_end_label); + separate_line_info_table_in_use++; + } + /* Output the location list given to us. */ static void *************** output_aranges (void) *** 7195,7202 **** } dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, ! text_section_label, "Length"); for (i = 0; i < arange_table_in_use; i++) { --- 7260,7273 ---- } dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); ! if (last_text_section == in_unlikely_executed_text ! || (last_text_section == in_named ! && last_text_section_name == unlikely_text_section_name)) ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, ! unlikely_section_label, "Length"); ! else ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, ! text_section_label, "Length"); for (i = 0; i < arange_table_in_use; i++) { *************** output_ranges (void) *** 7286,7296 **** base of the text section. */ if (separate_line_info_table_in_use == 0) { ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, ! text_section_label, ! fmt, i * 2 * DWARF2_ADDR_SIZE); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, ! text_section_label, NULL); } /* Otherwise, we add a DW_AT_entry_pc attribute to force the --- 7357,7380 ---- base of the text section. */ if (separate_line_info_table_in_use == 0) { ! if (last_text_section == in_unlikely_executed_text ! || (last_text_section == in_named ! && last_text_section_name == unlikely_text_section_name)) ! { ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, ! unlikely_section_label, ! fmt, i * 2 * DWARF2_ADDR_SIZE); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, ! unlikely_section_label, NULL); ! } ! else ! { ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, ! text_section_label, ! fmt, i * 2 * DWARF2_ADDR_SIZE); ! dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, ! text_section_label, NULL); ! } } /* Otherwise, we add a DW_AT_entry_pc attribute to force the *************** output_line_info (void) *** 7675,7681 **** a series of state machine operations. */ current_file = 1; current_line = 1; ! strcpy (prev_line_label, text_section_label); for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) { dw_line_info_ref line_info = &line_info_table[lt_index]; --- 7759,7770 ---- a series of state machine operations. */ current_file = 1; current_line = 1; ! if (last_text_section == in_unlikely_executed_text ! || (last_text_section == in_named ! && last_text_section_name == unlikely_text_section_name)) ! strcpy (prev_line_label, unlikely_section_label); ! else ! strcpy (prev_line_label, text_section_label); for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) { dw_line_info_ref line_info = &line_info_table[lt_index]; *************** add_location_or_const_value_attribute (d *** 10056,10061 **** --- 10145,10154 ---- tree sectree = DECL_SECTION_NAME (current_function_decl); secname = TREE_STRING_POINTER (sectree); } + else if (last_text_section == in_unlikely_executed_text + || (last_text_section == in_named + && last_text_section_name == unlikely_text_section_name)) + secname = unlikely_section_label; else secname = text_section_label; *************** gen_subprogram_die (tree decl, dw_die_re *** 11362,11376 **** if (!old_die || !get_AT (old_die, DW_AT_inline)) equate_decl_number_to_die (decl, subr_die); ! ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, ! current_function_funcdef_no); ! add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); ! ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, ! current_function_funcdef_no); ! add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); ! ! add_pubname (decl, subr_die); ! add_arange (decl, subr_die); #ifdef MIPS_DEBUGGING_INFO /* Add a reference to the FDE for this routine. */ --- 11455,11487 ---- if (!old_die || !get_AT (old_die, DW_AT_inline)) equate_decl_number_to_die (decl, subr_die); ! if (!flag_reorder_blocks_and_partition) ! { ! ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, ! current_function_funcdef_no); ! add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); ! ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, ! current_function_funcdef_no); ! add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); ! ! add_pubname (decl, subr_die); ! add_arange (decl, subr_die); ! } ! else ! { /* Do nothing for now; maybe need to duplicate die, one for ! hot section and ond for cold section, then use the hot/cold ! section begin/end labels to generate the aranges... */ ! /* ! add_AT_lbl_id (subr_die, DW_AT_low_pc, hot_section_label); ! add_AT_lbl_id (subr_die, DW_AT_high_pc, hot_section_end_label); ! add_AT_lbl_id (subr_die, DW_AT_lo_user, unlikely_section_label); ! add_AT_lbl_id (subr_die, DW_AT_hi_user, cold_section_end_label); ! ! add_pubname (decl, subr_die); ! add_arange (decl, subr_die); ! add_arange (decl, subr_die); ! */ ! } #ifdef MIPS_DEBUGGING_INFO /* Add a reference to the FDE for this routine. */ *************** static void *** 12987,12993 **** dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { ! function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); } --- 13098,13104 ---- dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { ! current_function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); } *************** dwarf2out_begin_block (unsigned int line *** 12997,13003 **** static void dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { ! function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); } --- 13108,13114 ---- static void dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { ! current_function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); } *************** dwarf2out_var_location (rtx loc_note) *** 13138,13143 **** --- 13249,13261 ---- newloc->var_loc_note = loc_note; newloc->next = NULL; + if (last_text_section == in_unlikely_executed_text + || (last_text_section == in_named + && last_text_section_name == unlikely_text_section_name)) + newloc->section_label = unlikely_section_label; + else + newloc->section_label = text_section_label; + last_insn = loc_note; last_label = newloc->label; decl = NOTE_VAR_LOCATION_DECL (loc_note); *************** dwarf2out_source_line (unsigned int line *** 13168,13174 **** if (debug_info_level >= DINFO_LEVEL_NORMAL && line != 0) { ! function_section (current_function_decl); /* If requested, emit something human-readable. */ if (flag_debug_asm) --- 13286,13292 ---- if (debug_info_level >= DINFO_LEVEL_NORMAL && line != 0) { ! current_function_section (current_function_decl); /* If requested, emit something human-readable. */ if (flag_debug_asm) Index: gcc/except.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/except.c,v retrieving revision 1.300 diff -c -3 -p -r1.300 except.c *** gcc/except.c 14 Mar 2005 02:53:58 -0000 1.300 --- gcc/except.c 22 Mar 2005 00:03:17 -0000 *************** output_function_exception_table (void) *** 3434,3440 **** dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i), (i ? NULL : "Exception specification table")); ! function_section (current_function_decl); } #include "gt-except.h" --- 3434,3440 ---- dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i), (i ? NULL : "Exception specification table")); ! current_function_section (current_function_decl); } #include "gt-except.h" Index: gcc/final.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/final.c,v retrieving revision 1.344 diff -c -3 -p -r1.344 final.c *** gcc/final.c 26 Nov 2004 02:21:38 -0000 1.344 --- gcc/final.c 22 Mar 2005 00:03:17 -0000 *************** profile_function (FILE *file ATTRIBUTE_U *** 1425,1431 **** assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); } ! function_section (current_function_decl); #if defined(ASM_OUTPUT_REG_PUSH) if (sval && svrtx != NULL_RTX && REG_P (svrtx)) --- 1425,1431 ---- assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); } ! current_function_section (current_function_decl); #if defined(ASM_OUTPUT_REG_PUSH) if (sval && svrtx != NULL_RTX && REG_P (svrtx)) *************** output_alternate_entry_point (FILE *file *** 1626,1660 **** } } - /* Return boolean indicating if there is a NOTE_INSN_UNLIKELY_EXECUTED_CODE - note in the instruction chain (going forward) between the current - instruction, and the next 'executable' instruction. */ - - bool - scan_ahead_for_unlikely_executed_note (rtx insn) - { - rtx temp; - int bb_note_count = 0; - - for (temp = insn; temp; temp = NEXT_INSN (temp)) - { - if (NOTE_P (temp) - && NOTE_LINE_NUMBER (temp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE) - return true; - if (NOTE_P (temp) - && NOTE_LINE_NUMBER (temp) == NOTE_INSN_BASIC_BLOCK) - { - bb_note_count++; - if (bb_note_count > 1) - return false; - } - if (INSN_P (temp)) - return false; - } - - return false; - } - /* The final scan for one insn, INSN. Args are same as in `final', except that INSN is the insn being scanned. --- 1626,1631 ---- *************** final_scan_insn (rtx insn, FILE *file, i *** 1701,1730 **** case NOTE_INSN_EXPECTED_VALUE: break; ! case NOTE_INSN_UNLIKELY_EXECUTED_CODE: /* The presence of this note indicates that this basic block belongs in the "cold" section of the .o file. If we are not already writing to the cold section we need to change to it. */ ! ! unlikely_text_section (); break; case NOTE_INSN_BASIC_BLOCK: - /* If we are performing the optimization that partitions - basic blocks into hot & cold sections of the .o file, - then at the start of each new basic block, before - beginning to write code for the basic block, we need to - check to see whether the basic block belongs in the hot - or cold section of the .o file, and change the section we - are writing to appropriately. */ - - if (flag_reorder_blocks_and_partition - && !scan_ahead_for_unlikely_executed_note (insn)) - function_section (current_function_decl); - #ifdef TARGET_UNWIND_INFO targetm.asm_out.unwind_emit (asm_out_file, insn); #endif --- 1672,1698 ---- case NOTE_INSN_EXPECTED_VALUE: break; ! case NOTE_INSN_SWITCH_TEXT_SECTIONS: /* The presence of this note indicates that this basic block belongs in the "cold" section of the .o file. If we are not already writing to the cold section we need to change to it. */ ! ! if (last_text_section == in_text) ! { ! (*debug_hooks->switch_text_section) (); ! unlikely_text_section (); ! } ! else ! { ! (*debug_hooks->switch_text_section) (); ! text_section (); ! } break; case NOTE_INSN_BASIC_BLOCK: #ifdef TARGET_UNWIND_INFO targetm.asm_out.unwind_emit (asm_out_file, insn); #endif *************** final_scan_insn (rtx insn, FILE *file, i *** 1908,1932 **** if (LABEL_NAME (insn)) (*debug_hooks->label) (insn); - /* If we are doing the optimization that partitions hot & cold - basic blocks into separate sections of the .o file, we need - to ensure the jump table ends up in the correct section... */ - - if (flag_reorder_blocks_and_partition - && targetm.have_named_sections) - { - rtx tmp_table, tmp_label; - if (LABEL_P (insn) - && tablejump_p (NEXT_INSN (insn), &tmp_label, &tmp_table)) - { - /* Do nothing; Do NOT change the current section. */ - } - else if (scan_ahead_for_unlikely_executed_note (insn)) - unlikely_text_section (); - else if (in_unlikely_text_section ()) - function_section (current_function_decl); - } - if (app_on) { fputs (ASM_APP_OFF, file); --- 1876,1881 ---- *************** final_scan_insn (rtx insn, FILE *file, i *** 1963,1969 **** ASM_OUTPUT_ALIGN (file, log_align); } else ! function_section (current_function_decl); #ifdef ASM_OUTPUT_CASE_LABEL ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), --- 1912,1918 ---- ASM_OUTPUT_ALIGN (file, log_align); } else ! current_function_section (current_function_decl); #ifdef ASM_OUTPUT_CASE_LABEL ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), *************** final_scan_insn (rtx insn, FILE *file, i *** 2078,2084 **** #endif #endif ! function_section (current_function_decl); break; } --- 2027,2033 ---- #endif #endif ! current_function_section (current_function_decl); break; } Index: gcc/ifcvt.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v retrieving revision 1.183 diff -c -3 -p -r1.183 ifcvt.c *** gcc/ifcvt.c 11 Mar 2005 09:05:01 -0000 1.183 --- gcc/ifcvt.c 22 Mar 2005 00:03:17 -0000 *************** find_if_case_1 (basic_block test_bb, edg *** 2865,2876 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && ((BB_END (then_bb) ! && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (else_bb) ! && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, ! NULL_RTX)))) return FALSE; /* THEN has one successor. */ --- 2865,2877 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if ((BB_END (then_bb) ! && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (test_bb) ! && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (else_bb) ! && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, ! NULL_RTX))) return FALSE; /* THEN has one successor. */ *************** find_if_case_2 (basic_block test_bb, edg *** 2970,2981 **** partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if (flag_reorder_blocks_and_partition ! && ((BB_END (then_bb) ! && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (else_bb) ! && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, ! NULL_RTX)))) return FALSE; /* ELSE has one successor. */ --- 2971,2983 ---- partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ ! if ((BB_END (then_bb) ! && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (test_bb) ! && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX)) ! || (BB_END (else_bb) ! && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, ! NULL_RTX))) return FALSE; /* ELSE has one successor. */ Index: gcc/insn-notes.def =================================================================== RCS file: /cvs/gcc/gcc/gcc/insn-notes.def,v retrieving revision 2.4 diff -c -3 -p -r2.4 insn-notes.def *** gcc/insn-notes.def 22 Oct 2004 17:05:05 -0000 2.4 --- gcc/insn-notes.def 22 Mar 2005 00:03:17 -0000 *************** INSN_NOTE (EXPECTED_VALUE) *** 88,96 **** now included in every insn. */ INSN_NOTE (BASIC_BLOCK) ! /* Record that the current basic block is unlikely to be executed and ! should be moved to the UNLIKELY_EXECUTED_TEXT_SECTION. FIXME: Make ! this a bit on the basic block structure. */ ! INSN_NOTE (UNLIKELY_EXECUTED_CODE) #undef INSN_NOTE --- 88,95 ---- now included in every insn. */ INSN_NOTE (BASIC_BLOCK) ! /* Mark the inflection point in the instruction stream where we switch ! between hot and cold text sections. */ ! INSN_NOTE (SWITCH_TEXT_SECTIONS) #undef INSN_NOTE Index: gcc/opts.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/opts.c,v retrieving revision 1.98 diff -c -3 -p -r1.98 opts.c *** gcc/opts.c 18 Mar 2005 08:01:21 -0000 1.98 --- gcc/opts.c 22 Mar 2005 00:03:17 -0000 *************** decode_options (unsigned int argc, const *** 669,692 **** if (flag_exceptions && flag_reorder_blocks_and_partition) { ! warning ("-freorder-blocks-and-partition does not work with exceptions"); flag_reorder_blocks_and_partition = 0; flag_reorder_blocks = 1; } - - /* The optimization to partition hot and cold basic blocks into - separate sections of the .o and executable files does not currently - work correctly with DWARF debugging turned on. Until this is fixed - we will disable the optimization when DWARF debugging is set. */ - - if (flag_reorder_blocks_and_partition && write_symbols == DWARF2_DEBUG) - { - warning - ("-freorder-blocks-and-partition does not work with -g (currently)"); - flag_reorder_blocks_and_partition = 0; - flag_reorder_blocks = 1; - } } /* Handle target- and language-independent options. Return zero to --- 669,679 ---- if (flag_exceptions && flag_reorder_blocks_and_partition) { ! inform ("-freorder-blocks-and-partition does not work with exceptions"); flag_reorder_blocks_and_partition = 0; flag_reorder_blocks = 1; } } /* Handle target- and language-independent options. Return zero to Index: gcc/output.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/output.h,v retrieving revision 1.152 diff -c -3 -p -r1.152 output.h *** gcc/output.h 18 Jan 2005 11:36:16 -0000 1.152 --- gcc/output.h 22 Mar 2005 00:03:17 -0000 *************** extern void named_section (tree, const c *** 209,214 **** --- 209,217 ---- /* Tell assembler to switch to the section for function DECL. */ extern void function_section (tree); + /* Tell assembler to switch to the most recently used text section. */ + extern void current_function_section (tree); + /* Tell assembler to switch to the section for string merging. */ extern void mergeable_string_section (tree, unsigned HOST_WIDE_INT, unsigned int); *************** extern rtx this_is_asm_operands; *** 431,436 **** --- 434,466 ---- extern int size_directive_output; extern tree last_assemble_variable_decl; + enum in_section { no_section, in_text, in_unlikely_executed_text, in_data, + in_named + #ifdef BSS_SECTION_ASM_OP + , in_bss + #endif + #ifdef CTORS_SECTION_ASM_OP + , in_ctors + #endif + #ifdef DTORS_SECTION_ASM_OP + , in_dtors + #endif + #ifdef READONLY_DATA_SECTION_ASM_OP + , in_readonly_data + #endif + #ifdef EXTRA_SECTIONS + , EXTRA_SECTIONS + #endif + }; + + extern char *unlikely_section_label; + extern char *hot_section_label; + extern char *hot_section_end_label; + extern char *cold_section_end_label; + extern char *unlikely_text_section_name; + extern const char *last_text_section_name; + extern enum in_section last_text_section; + /* Decide whether DECL needs to be in a writable section. RELOC is the same as for SELECT_SECTION. */ extern bool decl_readonly_section (tree, int); *************** extern bool default_valid_pointer_mode ( *** 519,524 **** --- 549,558 ---- extern int default_address_cost (rtx); + /* When performing hot/cold basic block partitioning, insert note in + instruction stream indicating boundary between hot and cold sections. */ + extern void insert_section_boundary_note (void); + /* dbxout helper functions */ #if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO Index: gcc/passes.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/passes.c,v retrieving revision 2.75 diff -c -3 -p -r2.75 passes.c *** gcc/passes.c 21 Mar 2005 18:49:23 -0000 2.75 --- gcc/passes.c 22 Mar 2005 00:03:17 -0000 *************** rest_of_handle_final (void) *** 332,337 **** --- 332,339 ---- timevar_push (TV_SYMOUT); (*debug_hooks->function_decl) (current_function_decl); + if (unlikely_text_section_name) + free (unlikely_text_section_name); timevar_pop (TV_SYMOUT); ggc_collect (); Index: gcc/print-rtl.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/print-rtl.c,v retrieving revision 1.119 diff -c -3 -p -r1.119 print-rtl.c *** gcc/print-rtl.c 23 Sep 2004 14:34:19 -0000 1.119 --- gcc/print-rtl.c 22 Mar 2005 00:03:17 -0000 *************** print_rtx (rtx in_rtx) *** 319,325 **** } break; ! case NOTE_INSN_UNLIKELY_EXECUTED_CODE: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); --- 319,325 ---- } break; ! case NOTE_INSN_SWITCH_TEXT_SECTIONS: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); Index: gcc/reg-stack.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v retrieving revision 1.173 diff -c -3 -p -r1.173 reg-stack.c *** gcc/reg-stack.c 13 Mar 2005 14:06:47 -0000 1.173 --- gcc/reg-stack.c 22 Mar 2005 00:03:18 -0000 *************** emit_swap_insn (rtx insn, stack regstack *** 931,938 **** if (LABEL_P (tmp) || CALL_P (tmp) || NOTE_INSN_BASIC_BLOCK_P (tmp) - || (NOTE_P (tmp) - && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE) || (NONJUMP_INSN_P (tmp) && stack_regs_mentioned (tmp))) { --- 931,936 ---- Index: gcc/sdbout.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/sdbout.c,v retrieving revision 1.98 diff -c -3 -p -r1.98 sdbout.c *** gcc/sdbout.c 4 Nov 2004 13:23:18 -0000 1.98 --- gcc/sdbout.c 22 Mar 2005 00:03:18 -0000 *************** const struct gcc_debug_hooks sdb_debug_h *** 335,341 **** debug_nothing_tree, /* outlining_inline_function */ sdbout_label, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx /* var_location */ }; /* Return a unique string to name an anonymous type. */ --- 335,342 ---- debug_nothing_tree, /* outlining_inline_function */ sdbout_label, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx, /* var_location */ ! debug_nothing_void /* switch_text_section */ }; /* Return a unique string to name an anonymous type. */ Index: gcc/varasm.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/varasm.c,v retrieving revision 1.484 diff -c -3 -p -r1.484 varasm.c *** gcc/varasm.c 20 Mar 2005 21:23:24 -0000 1.484 --- gcc/varasm.c 22 Mar 2005 00:03:18 -0000 *************** Software Foundation, 59 Temple Place - S *** 52,57 **** --- 52,58 ---- #include "tree-mudflap.h" #include "cgraph.h" #include "cfglayout.h" + #include "basic-block.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data *************** int size_directive_output; *** 95,119 **** tree last_assemble_variable_decl; ! /* The following global variable indicates if the section label for the ! "cold" section of code has been output yet to the assembler. The ! label is useful when running gdb. This is part of the optimization that ! partitions hot and cold basic blocks into separate sections of the .o ! file. */ ! static bool unlikely_section_label_printed = false; /* The following global variable indicates the label name to be put at ! the start of the first cold section within each function, when ! partitioning basic blocks into hot and cold sections. */ ! static char *unlikely_section_label = NULL; ! /* The following global variable indicates the section name to be used ! for the current cold section, when partitioning hot and cold basic blocks into separate sections. */ ! static char *unlikely_text_section_name = NULL; /* We give all constants their own alias set. Perhaps redundant with MEM_READONLY_P, but pre-dates it. */ --- 96,134 ---- tree last_assemble_variable_decl; ! /* The following global variable indicates the label name to be put at ! the start of the first cold section within each function, when ! partitioning basic blocks into hot and cold sections. Used for ! debug info. */ ! char *unlikely_section_label; /* The following global variable indicates the label name to be put at ! the start of the first hot section within each function, when ! partitioning basic blocks into hot and cold sections. Used for ! debug info. */ ! ! char *hot_section_label; ! ! /* The following global variable indicates the label name to be put at ! the end of the last hot section within each function, when ! partitioning basic blocks into hot and cold sections. Used for ! debug info. */ ! ! char *hot_section_end_label; ! /* The following global variable indicates the label name to be put at ! the end of the last cold section within each function, when ! partitioning basic blocks into hot and cold sections. Used for ! debug info.*/ ! ! char *cold_section_end_label; ! /* The following global variable indicates the seciton name to be used ! for the current cold section, when partitiong hot and cold basic blocks into separate sections. */ ! char *unlikely_text_section_name; /* We give all constants their own alias set. Perhaps redundant with MEM_READONLY_P, but pre-dates it. */ *************** static void globalize_decl (tree); *** 140,145 **** --- 155,161 ---- static void maybe_assemble_visibility (tree); static int in_named_entry_eq (const void *, const void *); static hashval_t in_named_entry_hash (const void *); + static void initialize_cold_section_name (void); #ifdef BSS_SECTION_ASM_OP #ifdef ASM_OUTPUT_BSS static void asm_output_bss (FILE *, tree, const char *, *************** static bool asm_emit_uninitialised (tree *** 156,180 **** unsigned HOST_WIDE_INT); static void mark_weak (tree); - enum in_section { no_section, in_text, in_unlikely_executed_text, in_data, - in_named - #ifdef BSS_SECTION_ASM_OP - , in_bss - #endif - #ifdef CTORS_SECTION_ASM_OP - , in_ctors - #endif - #ifdef DTORS_SECTION_ASM_OP - , in_dtors - #endif - #ifdef READONLY_DATA_SECTION_ASM_OP - , in_readonly_data - #endif - #ifdef EXTRA_SECTIONS - , EXTRA_SECTIONS - #endif - }; static GTY(()) enum in_section in_section = no_section; /* Return a nonzero value if DECL has a section attribute. */ #ifndef IN_NAMED_SECTION --- 172,179 ---- unsigned HOST_WIDE_INT); static void mark_weak (tree); static GTY(()) enum in_section in_section = no_section; + enum in_section last_text_section; /* Return a nonzero value if DECL has a section attribute. */ #ifndef IN_NAMED_SECTION *************** static GTY(()) enum in_section in_sectio *** 185,190 **** --- 184,190 ---- /* Text of section name when in_section == in_named. */ static GTY(()) const char *in_named_name; + const char *last_text_section_name; /* Hash table of flags that have been used for a particular named section. */ *************** static GTY((param_is (struct in_named_en *** 202,225 **** EXTRA_SECTION_FUNCTIONS #endif ! /* Tell assembler to switch to text section. */ ! ! void ! text_section (void) ! { ! if (in_section != in_text) ! { ! in_section = in_text; ! fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); ! } ! } ! ! /* Tell assembler to switch to unlikely-to-be-executed text section. */ ! ! void ! unlikely_text_section (void) { ! const char *name; int len; if (! unlikely_text_section_name) --- 202,211 ---- EXTRA_SECTION_FUNCTIONS #endif ! static void ! initialize_cold_section_name (void) { ! const char* name; int len; if (! unlikely_text_section_name) *************** unlikely_text_section (void) *** 235,252 **** name = TREE_STRING_POINTER (DECL_SECTION_NAME (current_function_decl)); len = strlen (name); ! unlikely_text_section_name = xmalloc ((len + 10) * sizeof (char)); ! strcpy (unlikely_text_section_name, name); ! strcat (unlikely_text_section_name, "_unlikely"); } else ! { ! len = strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME); ! unlikely_text_section_name = xmalloc (len+1 * sizeof (char)); ! strcpy (unlikely_text_section_name, ! UNLIKELY_EXECUTED_TEXT_SECTION_NAME); ! } } if ((in_section != in_unlikely_executed_text) && (in_section != in_named --- 221,255 ---- name = TREE_STRING_POINTER (DECL_SECTION_NAME (current_function_decl)); len = strlen (name); ! unlikely_text_section_name = xmalloc (len + 10); ! sprintf (unlikely_text_section_name, "%s%s", name, "_unlikely"); } else ! unlikely_text_section_name = ! xstrdup (UNLIKELY_EXECUTED_TEXT_SECTION_NAME); } + } + + /* Tell assembler to switch to text section. */ + + void + text_section (void) + { + if (in_section != in_text) + { + in_section = in_text; + last_text_section = in_text; + fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); + } + } + + /* Tell assembler to switch to unlikely-to-be-executed text section. */ + + void + unlikely_text_section (void) + { + if (! unlikely_text_section_name) + initialize_cold_section_name (); if ((in_section != in_unlikely_executed_text) && (in_section != in_named *************** unlikely_text_section (void) *** 254,265 **** { named_section (NULL_TREE, unlikely_text_section_name, 0); in_section = in_unlikely_executed_text; ! ! if (!unlikely_section_label_printed) ! { ! ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label); ! unlikely_section_label_printed = true; ! } } } --- 257,263 ---- { named_section (NULL_TREE, unlikely_text_section_name, 0); in_section = in_unlikely_executed_text; ! last_text_section = in_unlikely_executed_text; } } *************** named_section_real (const char *name, un *** 437,442 **** --- 435,446 ---- in_section = in_named; } } + + if (in_text_section () || in_unlikely_text_section ()) + { + last_text_section = in_section; + last_text_section_name = name; + } } /* Tell assembler to change to section NAME for DECL. *************** asm_output_aligned_bss (FILE *file, tree *** 565,592 **** void function_section (tree decl) { ! if (decl == NULL_TREE) ! text_section (); else ! { ! /* ??? Typical use of this function maybe shouldn't be looking ! for unlikely blocks at all - in the event that an entire ! function is going into the unlikely-execute section, that ! should be reflected in its DECL_SECTION_NAME. */ ! rtx insns = cfun && cfun->emit ? get_insns () : 0; ! bool unlikely = insns && scan_ahead_for_unlikely_executed_note (insns); #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS ! targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl)); #else ! if (unlikely) ! unlikely_text_section (); ! else if (DECL_SECTION_NAME (decl)) ! named_section (decl, 0, 0); ! else ! text_section (); #endif - } } /* Switch to read-only data section associated with function DECL. */ --- 569,630 ---- void function_section (tree decl) { ! bool unlikely = false; ! ! if (decl != NULL_TREE ! && DECL_SECTION_NAME (decl) != NULL_TREE) ! { ! /* 'unlikely' should only be true if the entire function belongs in ! the cold partition; in that case, the DECL_SECTION_NAME was updated ! in assemble_start_function to reflect this. */ ! ! /* The following is necessary, because 'strcmp ! (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), blah)' always ! fails, presumably because TREE_STRING_POINTER is declared to ! be an array of size 1 of char. */ ! ! int i; ! int len = TREE_STRING_LENGTH (DECL_SECTION_NAME (decl)); ! char *s = (char *) xmalloc (len + 1); ! ! for (i = 0; i < len; i ++) ! s[i] = (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)))[i]; ! s[len] = '\0'; ! ! if (unlikely_text_section_name ! && (strcmp (s, unlikely_text_section_name) == 0)) ! unlikely = true; ! } ! ! #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS ! targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl)); ! #else ! if (decl != NULL_TREE ! && DECL_SECTION_NAME (decl) != NULL_TREE) ! named_section (decl, (char *) 0, 0); else ! text_section (); ! #endif ! } + void + current_function_section (tree decl) + { #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS ! bool unlikely = (in_unlikely_text_section () ! || (last_text_section == in_unlikely_executed_text)); ! ! targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl)); #else ! if (last_text_section == in_unlikely_executed_text) ! unlikely_text_section (); ! else if (last_text_section == in_text) ! text_section (); ! else if (last_text_section == in_named) ! named_section (NULL_TREE, last_text_section_name, 0); ! else ! function_section (decl); #endif } /* Switch to read-only data section associated with function DECL. */ *************** void *** 1203,1218 **** assemble_start_function (tree decl, const char *fnname) { int align; - if (unlikely_text_section_name) - free (unlikely_text_section_name); - - unlikely_section_label_printed = false; unlikely_text_section_name = NULL; unlikely_section_label = reconcat (unlikely_section_label, fnname, ".unlikely_section", NULL); ! /* The following code does not need preprocessing in the assembler. */ app_disable (); --- 1241,1258 ---- assemble_start_function (tree decl, const char *fnname) { int align; + bool hot_label_written = false; unlikely_text_section_name = NULL; + hot_section_label = reconcat (hot_section_label, fnname, ".hot_section", NULL); unlikely_section_label = reconcat (unlikely_section_label, fnname, ".unlikely_section", NULL); ! hot_section_end_label = reconcat (hot_section_end_label, ! fnname, ".end", NULL); ! cold_section_end_label = reconcat (cold_section_end_label, ! fnname, ".end.cold", NULL); ! /* The following code does not need preprocessing in the assembler. */ app_disable (); *************** assemble_start_function (tree decl, cons *** 1220,1241 **** if (CONSTANT_POOL_BEFORE_FUNCTION) output_constant_pool (fnname, decl); ! /* Make sure the cold text (code) section is properly aligned. This ! is necessary here in the case where the function has both hot and ! cold sections, because we don't want to re-set the alignment when the ! section switch happens mid-function. We don't need to set the hot ! section alignment here, because code further down in this function ! sets the alignment for whichever section comes first, and if there ! is a hot section it is guaranteed to be first. */ if (flag_reorder_blocks_and_partition) { unlikely_text_section (); assemble_align (FUNCTION_BOUNDARY); } resolve_unique_section (decl, 0, flag_function_sections); function_section (decl); /* Tell assembler to move to target machine's alignment for functions. */ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); --- 1260,1303 ---- if (CONSTANT_POOL_BEFORE_FUNCTION) output_constant_pool (fnname, decl); ! /* Make sure the not and cold text (code) sections are properly ! aligned. This is necessary here in the case where the function ! has both hot and cold sections, because we don't want to re-set ! the alignment when the section switch happens mid-function. */ if (flag_reorder_blocks_and_partition) { unlikely_text_section (); assemble_align (FUNCTION_BOUNDARY); + ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label); + if (BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION) + { + /* The function starts in the cold partition, so update the + DECL_SECTION_NAME to reflect this. */ + DECL_SECTION_NAME (decl) = build_string + (strlen (unlikely_text_section_name), + unlikely_text_section_name); + /* Since the function starts with a cold section, we need to + explicitly align the hot section and write out the hot + section label. */ + text_section (); + assemble_align (FUNCTION_BOUNDARY); + ASM_OUTPUT_LABEL (asm_out_file, hot_section_label); + hot_label_written = true; + } } + else + initialize_cold_section_name (); + last_text_section = no_section; + in_section = no_section; resolve_unique_section (decl, 0, flag_function_sections); + + /* Switch to the correct text section for the start of the function. */ + function_section (decl); + if (!hot_label_written) + ASM_OUTPUT_LABEL (asm_out_file, hot_section_label); /* Tell assembler to move to target machine's alignment for functions. */ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); *************** assemble_start_function (tree decl, cons *** 1288,1299 **** ASM_OUTPUT_LABEL (asm_out_file, fnname); #endif /* ASM_DECLARE_FUNCTION_NAME */ ! if (in_unlikely_text_section () ! && !unlikely_section_label_printed) ! { ! ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label); ! unlikely_section_label_printed = true; ! } } /* Output assembler code associated with defining the size of the --- 1350,1356 ---- ASM_OUTPUT_LABEL (asm_out_file, fnname); #endif /* ASM_DECLARE_FUNCTION_NAME */ ! insert_section_boundary_note (); } /* Output assembler code associated with defining the size of the *************** assemble_start_function (tree decl, cons *** 1302,1307 **** --- 1359,1365 ---- void assemble_end_function (tree decl, const char *fnname) { + enum in_section save_text_section; #ifdef ASM_DECLARE_FUNCTION_SIZE ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl); #endif *************** assemble_end_function (tree decl, const *** 1310,1315 **** --- 1368,1382 ---- output_constant_pool (fnname, decl); function_section (decl); /* need to switch back */ } + /* Output labels for end of hot/cold text sections (to be used by + debug info.) */ + save_text_section = in_section; + unlikely_text_section (); + ASM_OUTPUT_LABEL (asm_out_file, cold_section_end_label); + text_section (); + ASM_OUTPUT_LABEL (asm_out_file, hot_section_end_label); + if (save_text_section == in_unlikely_executed_text) + unlikely_text_section (); } /* Assemble code to leave SIZE bytes of zeros. */ Index: gcc/vmsdbgout.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/vmsdbgout.c,v retrieving revision 1.39 diff -c -3 -p -r1.39 vmsdbgout.c *** gcc/vmsdbgout.c 12 Mar 2005 00:34:04 -0000 1.39 --- gcc/vmsdbgout.c 22 Mar 2005 00:03:18 -0000 *************** const struct gcc_debug_hooks vmsdbg_debu *** 209,215 **** vmsdbgout_abstract_function, debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx /* var_location */ }; /* Definitions of defaults for assembler-dependent names of various --- 209,216 ---- vmsdbgout_abstract_function, debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ ! debug_nothing_rtx, /* var_location */ ! debug_nothing_void /* switch_text_section */ }; /* Definitions of defaults for assembler-dependent names of various Index: gcc/config/darwin.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/darwin.c,v retrieving revision 1.108 diff -c -3 -p -r1.108 darwin.c *** gcc/config/darwin.c 19 Feb 2005 00:08:06 -0000 1.108 --- gcc/config/darwin.c 22 Mar 2005 00:03:18 -0000 *************** machopic_select_section (tree exp, int r *** 1016,1027 **** bool weak_p = DECL_P (exp) && DECL_WEAK (exp); static void (* const base_funs[][2])(void) = { { text_section, text_coal_section }, ! { text_unlikely_section, text_unlikely_coal_section }, { readonly_data_section, const_coal_section }, { const_data_section, const_data_coal_section }, { data_section, data_coal_section } }; if (TREE_CODE (exp) == FUNCTION_DECL) base_function = base_funs[reloc][weak_p]; else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT)) --- 1016,1032 ---- bool weak_p = DECL_P (exp) && DECL_WEAK (exp); static void (* const base_funs[][2])(void) = { { text_section, text_coal_section }, ! { unlikely_text_section, text_unlikely_coal_section }, { readonly_data_section, const_coal_section }, { const_data_section, const_data_coal_section }, { data_section, data_coal_section } }; + if (reloc == 0 + && (last_text_section == in_text_unlikely + || last_text_section == in_text_unlikely_coal)) + reloc = 1; + if (TREE_CODE (exp) == FUNCTION_DECL) base_function = base_funs[reloc][weak_p]; else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT)) Index: gcc/config/darwin.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/darwin.h,v retrieving revision 1.112 diff -c -3 -p -r1.112 darwin.h *** gcc/config/darwin.h 4 Mar 2005 04:43:02 -0000 1.112 --- gcc/config/darwin.h 22 Mar 2005 00:03:18 -0000 *************** FUNCTION (void) \ *** 619,624 **** --- 619,628 ---- if (asm_out_file) \ fputs ("\t" DIRECTIVE "\n", asm_out_file); \ in_section = SECTION; \ + if ((SECTION == in_text_coal) \ + || (SECTION == in_text_unlikely) \ + || (SECTION == in_text_unlikely_coal)) \ + last_text_section = SECTION; \ } \ } \ *************** SECTION_FUNCTION (text_coal_section, *** 658,667 **** in_text_coal, \ ".section __TEXT,__textcoal_nt,coalesced," \ "pure_instructions", 0) \ - SECTION_FUNCTION (text_unlikely_section, \ - in_text_unlikely, \ - ".section __TEXT,__text_unlikely,coalesced," \ - "pure_instructions", 0) \ SECTION_FUNCTION (text_unlikely_coal_section, \ in_text_unlikely_coal, \ ".section __TEXT,__text_unlikely_coal," \ --- 662,667 ---- Index: gcc/config/sparc/sparc.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v retrieving revision 1.355 diff -c -3 -p -r1.355 sparc.c *** gcc/config/sparc/sparc.c 13 Mar 2005 22:11:46 -0000 1.355 --- gcc/config/sparc/sparc.c 22 Mar 2005 00:03:19 -0000 *************** sparc_output_deferred_case_vectors (void *** 8202,8208 **** return; /* Align to cache line in the function's code section. */ ! function_section (current_function_decl); align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (align > 0) --- 8202,8208 ---- return; /* Align to cache line in the function's code section. */ ! current_function_section (current_function_decl); align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (align > 0) Index: gcc/config/stormy16/stormy16.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/stormy16/stormy16.c,v retrieving revision 1.70 diff -c -3 -p -r1.70 stormy16.c *** gcc/config/stormy16/stormy16.c 19 Nov 2004 09:47:22 -0000 1.70 --- gcc/config/stormy16/stormy16.c 22 Mar 2005 00:03:19 -0000 *************** xstormy16_output_addr_vec (FILE *file, r *** 2074,2080 **** { int vlen, idx; ! function_section (current_function_decl); vlen = XVECLEN (table, 0); for (idx = 0; idx < vlen; idx++) --- 2074,2080 ---- { int vlen, idx; ! current_function_section (current_function_decl); vlen = XVECLEN (table, 0); for (idx = 0; idx < vlen; idx++) Index: gcc/config/xtensa/xtensa.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.c,v retrieving revision 1.71 diff -c -3 -p -r1.71 xtensa.c *** gcc/config/xtensa/xtensa.c 21 Mar 2005 18:08:30 -0000 1.71 --- gcc/config/xtensa/xtensa.c 22 Mar 2005 00:03:19 -0000 *************** override_options (void) *** 1560,1565 **** --- 1560,1574 ---- /* There's no need for -fPIC (as opposed to -fpic) on Xtensa. */ if (flag_pic > 1) flag_pic = 1; + + /* Hot/cold partitioning does not work on this architecture, because of + constant pools (the load instruction cannot necessarily reach that far). + Therefore disable it on this architecture. */ + if (flag_reorder_blocks_and_partition) + { + flag_reorder_blocks_and_partition = 0; + flag_reorder_blocks = 1; + } }