Fix problems with hot/cold partitioning optimization.
authorCaroline Tice <ctice@gcc.gnu.org>
Thu, 31 Mar 2005 14:59:59 +0000 (06:59 -0800)
committerCaroline Tice <ctice@gcc.gnu.org>
Thu, 31 Mar 2005 14:59:59 +0000 (06:59 -0800)
From-SVN: r97322

27 files changed:
gcc/Makefile.in
gcc/bb-reorder.c
gcc/cfgcleanup.c
gcc/cfglayout.c
gcc/cfglayout.h
gcc/cfgrtl.c
gcc/config/darwin.c
gcc/config/darwin.h
gcc/config/sparc/sparc.c
gcc/config/stormy16/stormy16.c
gcc/config/xtensa/xtensa.c
gcc/dbxout.c
gcc/debug.c
gcc/debug.h
gcc/dwarf2out.c
gcc/except.c
gcc/final.c
gcc/ifcvt.c
gcc/insn-notes.def
gcc/opts.c
gcc/output.h
gcc/passes.c
gcc/print-rtl.c
gcc/reg-stack.c
gcc/sdbout.c
gcc/varasm.c
gcc/vmsdbgout.c

index fb8e6cb8e02aa89005bc051175128128432f4afc..5e7e495fa0eae78e6d022aed9827f9fec4b31f43 100644 (file)
@@ -1874,7 +1874,7 @@ rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
 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
+   $(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 \
@@ -2174,7 +2174,7 @@ lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
    $(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)
+   $(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)
@@ -3731,7 +3731,7 @@ STAGEPROFILE_FLAGS_TO_PASS = \
 # Files never linked into the final executable produces warnings about missing
 # profile.
 STAGEFEEDBACK_FLAGS_TO_PASS = \
-       CFLAGS="$(BOOT_CFLAGS) -fprofile-use"
+       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 b7223d7d1aa725c48e0357ef4a67ec5c8e5c1900..b0c99b134e9708e4ff0f5ad734ab7399952ded74 100644 (file)
@@ -81,6 +81,7 @@
 #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
@@ -119,6 +120,9 @@ typedef struct bbro_basic_block_data_def
   /* 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;
 
@@ -169,11 +173,9 @@ static void connect_traces (int, struct trace *);
 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);
@@ -194,26 +196,16 @@ push_to_next_round_p (basic_block bb, int round, int number_of_rounds,
                      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))
+  if (there_exists_another_round
+      && block_not_hot_enough)
     return true;
   else 
     return false;
@@ -237,8 +229,6 @@ find_traces (int *n_traces, struct trace *traces)
      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 ();
@@ -434,11 +424,6 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                     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 ();
@@ -481,6 +466,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
       trace->first = bb;
       trace->round = round;
       trace->length = 0;
+      bbd[bb->index].in_trace = *n_traces;
       (*n_traces)++;
 
       do
@@ -514,8 +500,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                  && e->dest->rbi->visited != *n_traces)
                continue;
 
-             if (BB_PARTITION (e->dest) == BB_COLD_PARTITION
-                 && round < last_round)
+             if (BB_PARTITION (e->dest) != BB_PARTITION (bb))
                continue;
 
              prob = e->probability;
@@ -646,6 +631,8 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                                           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);
                            }
                        }
@@ -658,6 +645,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                            {
                              bb = copy_bb (best_edge->dest, best_edge, bb,
                                            *n_traces);
+                             trace->length++;
                            }
                        }
                    }
@@ -695,7 +683,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                        && !e->dest->rbi->visited
                        && single_pred_p (e->dest)
                        && !(e->flags & EDGE_CROSSING)
-                       && single_succ_p (e->dest) == 1
+                       && single_succ_p (e->dest)
                        && (single_succ_edge (e->dest)->flags
                            & EDGE_CAN_FALLTHRU)
                        && !(single_succ_edge (e->dest)->flags & EDGE_COMPLEX)
@@ -710,6 +698,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                      }
 
                  bb->rbi->next = best_edge->dest;
+                 bbd[best_edge->dest->index].in_trace = (*n_traces) - 1;
                  bb = best_edge->dest;
                }
            }
@@ -788,6 +777,7 @@ copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
       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;
@@ -802,6 +792,8 @@ copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
        }
     }
 
+  bbd[new_bb->index].in_trace = trace;
+
   return new_bb;
 }
 
@@ -899,11 +891,11 @@ static void
 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;
+  bool two_passes;
   int last_trace;
+  int current_pass;
+  int current_partition;
   int freq_threshold;
   gcov_type count_threshold;
 
@@ -915,66 +907,47 @@ connect_traces (int n_traces, struct trace *traces)
 
   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));
+  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; 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++)
+    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 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)
+      if (i >= n_traces)
        {
-         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 (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;
-      if (unconnected_hot_trace_count > 0)
-       unconnected_hot_trace_count--;
 
       /* Find the predecessor traces.  */
       for (t2 = t; t2 > 0;)
@@ -991,6 +964,7 @@ connect_traces (int n_traces, struct trace *traces)
                  && !(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
@@ -1006,9 +980,6 @@ connect_traces (int n_traces, struct trace *traces)
              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",
@@ -1039,6 +1010,7 @@ connect_traces (int n_traces, struct trace *traces)
                  && !(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
@@ -1059,8 +1031,6 @@ connect_traces (int n_traces, struct trace *traces)
              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
@@ -1101,6 +1071,7 @@ connect_traces (int n_traces, struct trace *traces)
                                && !(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
@@ -1153,8 +1124,6 @@ connect_traces (int n_traces, struct trace *traces)
                      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
@@ -1178,7 +1147,6 @@ connect_traces (int n_traces, struct trace *traces)
     }
 
   FREE (connected);
-  FREE (cold_traces);
 }
 
 /* Return true when BB can and should be copied. CODE_MAY_GROW is true
@@ -1242,18 +1210,6 @@ get_uncond_jump_length (void)
   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).  */
@@ -1282,18 +1238,6 @@ find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
        }
     }
 
-  /* 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;
@@ -1322,39 +1266,6 @@ find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
   *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.  */
@@ -1782,6 +1693,10 @@ fix_crossing_unconditional_branches (void)
   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
@@ -1864,19 +1779,19 @@ add_reg_crossing_jump_notes (void)
                                                                  (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.
-   
+/* 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" 
@@ -1942,6 +1857,44 @@ fix_edges_for_rarely_executed_code (edge *crossing_edges,
     }
 }
 
+/* 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().  */
 
@@ -1976,6 +1929,7 @@ reorder_basic_blocks (unsigned int flags)
   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;
@@ -1991,15 +1945,42 @@ reorder_basic_blocks (unsigned int flags)
   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 ();
+  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,
@@ -2041,7 +2022,8 @@ duplicate_computed_gotos (void)
 
       /* 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)))
+      if (computed_jump_p (BB_END (bb))
+         && !find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
        {
          rtx insn;
          int size = 0;
@@ -2110,15 +2092,14 @@ done:
    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.
+   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 49cbb44a9f2152359ee5cd84c07ccf5fb1c36e99..70bd28d173c8892c57b3333dd1d91106391e92b2 100644 (file)
@@ -155,9 +155,8 @@ try_simplify_condjump (basic_block cbranch_block)
      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)))
+  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
@@ -435,8 +434,7 @@ try_forward_edges (int mode, basic_block b)
      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))
+  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)); )
@@ -471,8 +469,7 @@ try_forward_edges (int mode, basic_block b)
         bb-reorder.c:partition_hot_cold_basic_blocks for complete
         details.  */
 
-      if (flag_reorder_blocks_and_partition
-         && first != EXIT_BLOCK_PTR
+      if (first != EXIT_BLOCK_PTR
          && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
        return false;
 
@@ -684,9 +681,7 @@ merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b)
      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)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return;
 
   barrier = next_nonnote_insn (BB_END (a));
@@ -742,9 +737,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
      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)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return;
 
   real_b_end = BB_END (b);
@@ -814,10 +807,7 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
      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)))
+  if (BB_PARTITION (b) != BB_PARTITION (c))
     return NULL;
       
     
@@ -1725,9 +1715,9 @@ try_crossjump_bb (int mode, basic_block bb)
      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)))
+  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 655c9a1b397dd9b4d8121e1b93bfb2b7b6cb7240..6b6006291d75c84bbe2fbad62d49d78c1e3bf72a 100644 (file)
@@ -51,7 +51,6 @@ static void change_scope (rtx, tree, tree);
 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);
 \f
 rtx
 unlink_insn_chain (rtx first, rtx last)
@@ -784,28 +783,12 @@ fixup_reorder_chain (void)
             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)));
-           }
+             && 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)));
        }
     }
 
@@ -840,8 +823,6 @@ fixup_reorder_chain (void)
       bb->index = index;
       BASIC_BLOCK (index) = bb;
 
-      update_unlikely_executed_notes (bb);
-
       bb->prev_bb = prev_bb;
       prev_bb->next_bb = bb;
     }
@@ -863,21 +844,6 @@ fixup_reorder_chain (void)
     }
 }
 \f
-/* 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;
-}
-\f
 /* Perform sanity checks on the insn chain.
    1. Check that next/prev pointers are consistent in both the forward and
       reverse direction.
@@ -1046,7 +1012,7 @@ duplicate_insn_chain (rtx from, rtx to)
              break;
 
            case NOTE_INSN_REPEATED_LINE_NUMBER:
-           case NOTE_INSN_UNLIKELY_EXECUTED_CODE:
+           case NOTE_INSN_SWITCH_TEXT_SECTIONS:
              emit_note_copy (insn);
              break;
 
index 69c9d562e2c456ef567eb2edf51b4cd935471320..14105099054e9d75a22ab58b83c5763956ceef94 100644 (file)
@@ -32,7 +32,6 @@ extern void reemit_insn_block_notes (void);
 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 */
index 92399068dcab727f5c26c6967363abe1642f454a..d11db10b0e66fc8943bd97d7bd75b342a9b74840 100644 (file)
@@ -92,8 +92,7 @@ static int
 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);
+         || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
 }
 
 /* True if a given label can be deleted.  */
@@ -616,10 +615,7 @@ rtl_can_merge_blocks (basic_block a,basic_block b)
      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)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return false;
 
   /* There must be exactly one edge in between the blocks.  */
@@ -678,9 +674,8 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
      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)))
+  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
@@ -1108,29 +1103,16 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
 
       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)));
-       }
-
+         && 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;
@@ -1576,10 +1558,6 @@ commit_one_edge_insertion (edge e, int watch_calls)
            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)
@@ -1629,7 +1607,7 @@ commit_one_edge_insertion (edge e, int watch_calls)
              && BB_PARTITION (e->src) == BB_COLD_PARTITION
              && !(e->flags & EDGE_CROSSING))
            {
-             rtx bb_note, new_note, cur_insn;
+             rtx bb_note, cur_insn;
 
              bb_note = NULL_RTX;
              for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
@@ -1641,16 +1619,11 @@ commit_one_edge_insertion (edge e, int watch_calls)
                    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;
            }
        }
     }
@@ -2717,10 +2690,7 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
      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)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return false;
 
   /* There must be exactly one edge in between the blocks.  */
index 6a547384aaeb62e07ea4bee1773dff8f03765c20..e6f41a22994ed63d350b148753687e82d6632874 100644 (file)
@@ -1016,12 +1016,17 @@ machopic_select_section (tree exp, int reloc,
   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 },
+    { 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 b26715e26effcf1902a7fcb40822500ca3af7b7f..25d1bcade86203148d6165f0c98b17c67685a52e 100644 (file)
@@ -621,6 +621,10 @@ FUNCTION (void)                                                            \
       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;                                    \
     }                                                                  \
 }                                                                      \
 
@@ -660,10 +664,6 @@ SECTION_FUNCTION (text_coal_section,                               \
                  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,"       \
index 6823915097a5e7dda7e4b07e06f6f222b1d608ea..340a3776958feea021a54c5ef23c1ab515c6b4d8 100644 (file)
@@ -8201,7 +8201,7 @@ sparc_output_deferred_case_vectors (void)
     return;
 
   /* Align to cache line in the function's code section.  */
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
 
   align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
   if (align > 0)
index ec40cd916b25fe3ded0d2c75058decf99de20451..a15051f92029e49aff726919a9fba92b6c1d615c 100644 (file)
@@ -2074,7 +2074,7 @@ xstormy16_output_addr_vec (FILE *file, rtx label ATTRIBUTE_UNUSED, rtx table)
 { 
   int vlen, idx;
   
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
 
   vlen = XVECLEN (table, 0);
   for (idx = 0; idx < vlen; idx++)
index cdba18c8388eae9a0d08aecf757f48979e09704d..b6084c9c5d2e599759f1cc8f935a5791320d91fd 100644 (file)
@@ -1560,6 +1560,15 @@ override_options (void)
   /* 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;
+    }
 }
 
 
index 92538b8ce1079ac8be5d8d1186fb13fa15a2be12..ea830a62e9cde2cfca8757f6436d7f723c039e85 100644 (file)
@@ -275,7 +275,7 @@ static int pending_bincls = 0;
 static const char *base_input_file;
 
 #ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
+#define FORCE_TEXT current_function_section (current_function_decl);
 #else
 #define FORCE_TEXT
 #endif
@@ -379,6 +379,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   debug_nothing_rtx,                    /* label */
   dbxout_handle_pch,                    /* handle_pch */
   debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
   0                                      /* start_end_main_source_file */
 };
 #endif /* DBX_DEBUGGING_INFO  */
@@ -410,6 +411,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_rtx,                    /* label */
   dbxout_handle_pch,                    /* handle_pch */
   debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
   0                                      /* start_end_main_source_file */
 };
 #endif /* XCOFF_DEBUGGING_INFO  */
@@ -934,9 +936,21 @@ dbxout_function_end (tree decl)
 #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));
+  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 ab26bc1cae57c21662ccd4e88b48c4e423cfa44a..e34b7b9f61b19826bbe2883bfe9de5cb58ffdb76 100644 (file)
@@ -48,6 +48,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_rtx,                    /* label */
   debug_nothing_int,                    /* handle_pch */
   debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
   0                                      /* start_end_main_source_file */
 };
 
index ca0ad77adba774b0569c71aab642c6715237c541..5b4074b1294e97a3afd3257d29a0cbf6c11884c1 100644 (file)
@@ -120,6 +120,10 @@ struct gcc_debug_hooks
   /* 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);
+
   /* This is 1 if the debug writer wants to see start and end commands for the
      main source files, and 0 otherwise.  */
   int start_end_main_source_file;
index 70ad88749aaf8c0ada63e11624d3659ed9b9dddb..43ab1b5d215680962f8cb87e7e0b212095e9771a 100644 (file)
@@ -253,6 +253,11 @@ typedef struct dw_fde_struct GTY(())
   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;
@@ -2273,17 +2278,57 @@ output_call_frame_info (int for_eh)
          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");
+         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");
-         dw2_asm_output_delta (DWARF2_ADDR_SIZE,
-                               fde->dw_fde_end, fde->dw_fde_begin,
-                               "FDE address range");
+         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])
@@ -2409,6 +2454,11 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
   fde->decl = current_function_decl;
   fde->dw_fde_begin = dup_label;
   fde->dw_fde_current_label = NULL;
+  fde->dw_fde_hot_section_label = NULL;
+  fde->dw_fde_hot_section_end_label = NULL;
+  fde->dw_fde_unlikely_section_label = NULL;
+  fde->dw_fde_unlikely_section_end_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;
@@ -3418,6 +3468,7 @@ static void dwarf2out_imported_module_or_decl (tree, tree);
 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.  */
 
@@ -3450,6 +3501,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   debug_nothing_rtx,           /* label */
   debug_nothing_int,           /* handle_pch */
   dwarf2out_var_location,
+  dwarf2out_switch_text_section,
   1                             /* start_end_main_source_file */
 };
 #endif
@@ -3651,6 +3703,7 @@ struct var_loc_node GTY ((chain_next ("%h.next")))
 {
   rtx GTY (()) var_loc_note;
   const char * GTY (()) label;
+  const char * GTY (()) section_label;
   struct var_loc_node * GTY (()) next;
 };
 
@@ -6742,6 +6795,20 @@ add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr,
   *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
@@ -7168,8 +7235,14 @@ output_aranges (void)
     }
 
   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");
+  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++)
     {
@@ -7259,11 +7332,24 @@ output_ranges (void)
             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);
+             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
@@ -7648,7 +7734,12 @@ output_line_info (void)
      a series of state machine operations.  */
   current_file = 1;
   current_line = 1;
-  strcpy (prev_line_label, text_section_label);
+  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];
@@ -10028,6 +10119,10 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
          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;
 
@@ -11334,15 +11429,33 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       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);
+      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.  */
@@ -12956,7 +13069,7 @@ static void
 dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
                       unsigned int blocknum)
 {
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
 }
 
@@ -12966,7 +13079,7 @@ dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
 static void
 dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
 {
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
 }
 
@@ -13107,6 +13220,13 @@ dwarf2out_var_location (rtx loc_note)
   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);
@@ -13137,7 +13257,7 @@ dwarf2out_source_line (unsigned int line, const char *filename)
   if (debug_info_level >= DINFO_LEVEL_NORMAL
       && line != 0)
     {
-      function_section (current_function_decl);
+      current_function_section (current_function_decl);
 
       /* If requested, emit something human-readable.  */
       if (flag_debug_asm)
index d774bf3fa259b242160baccdcd71cc34fd2fce2a..05834247d88c06850a2cce31573279805eb8d174 100644 (file)
@@ -3434,7 +3434,7 @@ output_function_exception_table (void)
     dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i),
                         (i ? NULL : "Exception specification table"));
 
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
 }
 
 #include "gt-except.h"
index 7f5c664fd20f6808d85c181b1e979ca5675d2a5c..76337244e4ac6238396ca7e276493f7f73ace942 100644 (file)
@@ -1426,7 +1426,7 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
       assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
     }
 
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
 
 #if defined(ASM_OUTPUT_REG_PUSH)
   if (sval && svrtx != NULL_RTX && REG_P (svrtx))
@@ -1619,35 +1619,6 @@ output_alternate_entry_point (FILE *file, rtx insn)
     }
 }
 
-/* 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.
@@ -1691,30 +1662,27 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
        case NOTE_INSN_EXPECTED_VALUE:
          break;
 
-       case NOTE_INSN_UNLIKELY_EXECUTED_CODE:
+       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.  */
-         
-         unlikely_text_section ();
+
+         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:
          
-         /* 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
@@ -1896,25 +1864,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
       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);
@@ -1952,7 +1901,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
                  ASM_OUTPUT_ALIGN (file, log_align);
                }
              else
-               function_section (current_function_decl);
+               current_function_section (current_function_decl);
 
 #ifdef ASM_OUTPUT_CASE_LABEL
              ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
@@ -2011,7 +1960,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
            if (! JUMP_TABLES_IN_TEXT_SECTION)
              targetm.asm_out.function_rodata_section (current_function_decl);
            else
-             function_section (current_function_decl);
+             current_function_section (current_function_decl);
 
            if (app_on)
              {
@@ -2069,7 +2018,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
 #endif
 #endif
 
-           function_section (current_function_decl);
+           current_function_section (current_function_decl);
 
            break;
          }
index b0df6dae3ac46f131c149b53fbf85213c0c575da..7a934ee6acfaa51f535b96dfc6826de846b79cef 100644 (file)
@@ -2865,12 +2865,13 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
      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))))
+  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.  */
@@ -2970,12 +2971,13 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
      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))))
+  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 3894dda31289df8788aec7b7ae56402395f59321..58f264da6d88b5bba6a238a01bb7d04865734acc 100644 (file)
@@ -88,9 +88,8 @@ INSN_NOTE (EXPECTED_VALUE)
    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)
+/* 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 3befb1d4d4376fb074c960a9d10fa72146898b95..bd971c8e3f9cf42b6985e2d6b4c491e754bc71a3 100644 (file)
@@ -669,24 +669,11 @@ decode_options (unsigned int argc, const char **argv)
 
   if (flag_exceptions && flag_reorder_blocks_and_partition)
     {
-      warning 
+      inform 
            ("-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
index dbc2d4745ddfae5fe61f5c50a41f310d927edb4a..4d9eabb49f75b5a7a3b7a3eddf4e654274640dfc 100644 (file)
@@ -209,6 +209,9 @@ extern void named_section (tree, const char *, int);
 /* 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);
@@ -431,6 +434,34 @@ extern rtx this_is_asm_operands;
 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;
+extern bool first_function_block_is_cold;
+
 /* 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);
@@ -519,6 +550,10 @@ extern bool default_valid_pointer_mode (enum machine_mode);
 
 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 988f4f2c7632f059f0def4dc64afedd883e07c56..2ded2b3ff7108f0d19f062ecbe0bed060747af36 100644 (file)
@@ -332,6 +332,8 @@ rest_of_handle_final (void)
 
   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 32ef01c88442b8cffa2ab81a0b264e260be52f41..4f8c9a9bf3c65e2ccc72a44543baf9dc82dea253 100644 (file)
@@ -319,7 +319,7 @@ print_rtx (rtx in_rtx)
                }
                break;
 
-             case NOTE_INSN_UNLIKELY_EXECUTED_CODE:
+             case NOTE_INSN_SWITCH_TEXT_SECTIONS:
                {
 #ifndef GENERATOR_FILE
                  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
index 6f58341ba2775f327c274738382274ae21ebdd11..f126d98461b44d4be54534efe602d246a207cfe5 100644 (file)
@@ -931,8 +931,6 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
          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)))
            {
index fb098474d19de870107cfd635e2ba50b1cb831e4..d5964323aef3e5d0ee8150bfa3130f30278f7d04 100644 (file)
@@ -336,6 +336,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
   sdbout_label,                                 /* label */
   debug_nothing_int,                    /* handle_pch */
   debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
   0                                      /* start_end_main_source_file */
 };
 
index 9210c413b252410221bb0bf743a89771945e381e..d2aeac6aabf4741c258311e9bab032669df953b3 100644 (file)
@@ -52,6 +52,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #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
@@ -95,25 +96,44 @@ int size_directive_output;
 
 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.  */
+/* The following global variable indicates if the first basic block
+   in a function belongs to the cold partition or not.  */
 
-static bool unlikely_section_label_printed = false;
+bool first_function_block_is_cold;
 
 /* 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.  */
+   partitioning basic blocks into hot and cold sections.  Used for
+   debug info.  */
 
-static char *unlikely_section_label = NULL;
+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 section name to be used
-   for the current cold section, when partitioning hot and cold basic
+/* 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.  */
 
-static char *unlikely_text_section_name = NULL;
+char *unlikely_text_section_name;
 
 /* We give all constants their own alias set.  Perhaps redundant with
    MEM_READONLY_P, but pre-dates it.  */
@@ -140,6 +160,7 @@ static void globalize_decl (tree);
 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 *,
@@ -156,25 +177,8 @@ static bool asm_emit_uninitialised (tree, const char*,
                                    unsigned HOST_WIDE_INT);
 static void mark_weak (tree);
 \f
-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;
+enum in_section last_text_section;
 
 /* Return a nonzero value if DECL has a section attribute.  */
 #ifndef IN_NAMED_SECTION
@@ -185,6 +189,7 @@ static GTY(()) enum in_section in_section = no_section;
 
 /* 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.  */
 
@@ -202,24 +207,10 @@ static GTY((param_is (struct in_named_entry))) htab_t in_named_htab;
 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)
+static void
+initialize_cold_section_name (void)
 {
-  const char *name;
+  const charname;
   int len;
 
   if (! unlikely_text_section_name)
@@ -235,18 +226,35 @@ unlikely_text_section (void)
          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");
+         unlikely_text_section_name = xmalloc (len + 10);
+         sprintf (unlikely_text_section_name, "%s%s", 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);
-       }
+       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 
@@ -254,12 +262,7 @@ unlikely_text_section (void)
     {
       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;
-       }
+      last_text_section = in_unlikely_executed_text;
     }
 }
 
@@ -437,6 +440,12 @@ named_section_real (const char *name, unsigned int flags, tree decl)
          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.
@@ -565,28 +574,40 @@ asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
 void
 function_section (tree decl)
 {
-  if (decl == NULL_TREE)
-    text_section ();
+  bool unlikely = false;
+    
+  if (first_function_block_is_cold)
+    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
-    {
-      /* ??? 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);
+    text_section ();
+#endif
+}
 
+void
+current_function_section (tree decl)
+{
 #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
-      targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
+  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 (unlikely)
-       unlikely_text_section ();
-      else if (DECL_SECTION_NAME (decl))
-       named_section (decl, 0, 0);
-      else
-       text_section ();
+  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.  */
@@ -1203,16 +1224,19 @@ void
 assemble_start_function (tree decl, const char *fnname)
 {
   int align;
+  bool hot_label_written = false;
 
-  if (unlikely_text_section_name)
-    free (unlikely_text_section_name);
-
-  unlikely_section_label_printed = false;
   unlikely_text_section_name = NULL;
   
+  first_function_block_is_cold = false;
+  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 ();
@@ -1220,22 +1244,67 @@ assemble_start_function (tree decl, const char *fnname)
   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.  */
+  /* 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)
+       {
+         /* 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;
+         first_function_block_is_cold = true;
+       }
     }
+  else if (DECL_SECTION_NAME (decl))
+    {
+      /* Calls to function_section rely on first_function_block_is_cold
+        being accurate.  The first block may be cold even if we aren't
+        doing partitioning, if the entire function was decided by
+        choose_function_section (predict.c) to be cold.  */
+
+      int i;
+      int len;
+      char *s;
 
+      initialize_cold_section_name ();
+
+      /* 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.  */
+
+      len = TREE_STRING_LENGTH (DECL_SECTION_NAME (decl));
+      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))
+       first_function_block_is_cold = true;
+    }
+
+  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);
@@ -1288,12 +1357,7 @@ assemble_start_function (tree decl, const char *fnname)
   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;
-    }
+  insert_section_boundary_note ();
 }
 
 /* Output assembler code associated with defining the size of the
@@ -1302,6 +1366,7 @@ assemble_start_function (tree decl, const char *fnname)
 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
@@ -1310,6 +1375,15 @@ assemble_end_function (tree decl, const char *fnname)
       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 ();
 }
 \f
 /* Assemble code to leave SIZE bytes of zeros.  */
index d0f4abe6e0acf8fd179c737830ec7ab5793ddaaf..d612479f6c611d43f4108363d29d5ef202db4cbb 100644 (file)
@@ -210,6 +210,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
    debug_nothing_rtx,            /* label */
    debug_nothing_int,            /* handle_pch */
    debug_nothing_rtx,            /* var_location */
+   debug_nothing_void,            /* switch_text_section */
    0                              /* start_end_main_source_file */
 };