* dwarf2out.c (output_fde): When doing hot/cold partitioning, use
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Aug 2009 06:23:42 +0000 (06:23 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Aug 2009 06:23:42 +0000 (06:23 +0000)
fde->dw_fde_begin as begin label instead of hot/cold label.
Use LLSDAC label instead of LLSDA for second section lsda.
(dwarf2out_do_cfi_startproc): Add SECOND argument.  Use LLSDAC
label instead of LLSDA if it is true.
(dwarf2out_begin_prologue, dwarf2out_switch_text_section): Adjust
callers.
* except.c (add_call_site, dw2_size_of_call_site_table): Add
SECTION argument.  Use it as index into crtl->eh.call_site_record
array.
(dw2_output_call_site_table): Likewise.  Add CS_FORMAT argument,
use it to determine how to print table entries instead of using
#ifdef HAVE_AS_LEB128.  For SECTION > 0 use hot resp. cold
label instead of normal begin label as base.
(sjlj_assign_call_site_values): Adjust add_call_site caller.
(convert_to_eh_region_ranges): When doing hot/cold partitioning,
ensure no EH range spans between sections and that landing pads
are always in the corresponding section.
(sjlj_size_of_call_site_table, sjlj_output_call_site_table): Adjust
for crtl->eh.call_site_record being an array rather than scalar.
(output_one_function_exception_table): New function, copied
from output_function_exception_table.  Adjust
dw2_size_of_call_site_table, dw2_output_call_site_table
callers.  For SECOND section use *C suffixed labels.
(output_function_exception_table): Call
output_one_function_exception_table and, when doing hot/cold
partitioning, also another time for the second section.
* opts.c: Include except.h.
(decode_options): Allow -freorder-blocks-and-partition with
exceptions, unless SJLJ or TARGET_UNWIND_INFO.
* Makefile.in (opts.o): Depend on $(EXCEPT_H).
* function.h (struct rtl_eh): Change call_site_record from
scalar into array of 2 elements.

* g++.dg/tree-prof/partition1.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150553 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/dwarf2out.c
gcc/except.c
gcc/function.h
gcc/opts.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-prof/partition1.C [new file with mode: 0644]

index 75129f6..1a76d9a 100644 (file)
@@ -1,3 +1,39 @@
+2009-08-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * dwarf2out.c (output_fde): When doing hot/cold partitioning, use
+       fde->dw_fde_begin as begin label instead of hot/cold label.
+       Use LLSDAC label instead of LLSDA for second section lsda.
+       (dwarf2out_do_cfi_startproc): Add SECOND argument.  Use LLSDAC
+       label instead of LLSDA if it is true.
+       (dwarf2out_begin_prologue, dwarf2out_switch_text_section): Adjust
+       callers.
+       * except.c (add_call_site, dw2_size_of_call_site_table): Add
+       SECTION argument.  Use it as index into crtl->eh.call_site_record
+       array.
+       (dw2_output_call_site_table): Likewise.  Add CS_FORMAT argument,
+       use it to determine how to print table entries instead of using
+       #ifdef HAVE_AS_LEB128.  For SECTION > 0 use hot resp. cold
+       label instead of normal begin label as base.
+       (sjlj_assign_call_site_values): Adjust add_call_site caller.
+       (convert_to_eh_region_ranges): When doing hot/cold partitioning,
+       ensure no EH range spans between sections and that landing pads
+       are always in the corresponding section.
+       (sjlj_size_of_call_site_table, sjlj_output_call_site_table): Adjust
+       for crtl->eh.call_site_record being an array rather than scalar.
+       (output_one_function_exception_table): New function, copied
+       from output_function_exception_table.  Adjust
+       dw2_size_of_call_site_table, dw2_output_call_site_table
+       callers.  For SECOND section use *C suffixed labels.
+       (output_function_exception_table): Call
+       output_one_function_exception_table and, when doing hot/cold
+       partitioning, also another time for the second section.
+       * opts.c: Include except.h.
+       (decode_options): Allow -freorder-blocks-and-partition with
+       exceptions, unless SJLJ or TARGET_UNWIND_INFO.
+       * Makefile.in (opts.o): Depend on $(EXCEPT_H).
+       * function.h (struct rtl_eh): Change call_site_record from
+       scalar into array of 2 elements.
+
 2009-08-07  Martin Jambor  <mjambor@suse.cz>
 
        * ipa-prop.c (count_formal_params_1): New function.
index dd52a03..7951d29 100644 (file)
@@ -2595,7 +2595,7 @@ opts.o : opts.c opts.h options.h $(TOPLEV_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(EXPR_H) $(RTL_H) \
    output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h varray.h \
-   $(PLUGIN_H)
+   $(PLUGIN_H) $(EXCEPT_H)
 opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h intl.h
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
index fe7b72d..af97bb0 100644 (file)
@@ -3429,15 +3429,22 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
       begin = fde->dw_fde_begin;
       end = fde->dw_fde_end;
     }
-  else if (second ^ fde->dw_fde_switched_cold_to_hot)
-    {
-      begin = fde->dw_fde_unlikely_section_label;
-      end = fde->dw_fde_unlikely_section_end_label;
-    }
   else
     {
-      begin = fde->dw_fde_hot_section_label;
-      end = fde->dw_fde_hot_section_end_label;
+      /* For the first section, prefer dw_fde_begin over
+        dw_fde_{hot,cold}_section_label, as the latter
+        might be separated from the real start of the
+        function by alignment padding.  */
+      if (!second)
+       begin = fde->dw_fde_begin;
+      else if (fde->dw_fde_switched_cold_to_hot)
+       begin = fde->dw_fde_hot_section_label;
+      else
+       begin = fde->dw_fde_unlikely_section_label;
+      if (second ^ fde->dw_fde_switched_cold_to_hot)
+       end = fde->dw_fde_unlikely_section_end_label;
+      else
+       end = fde->dw_fde_hot_section_end_label;
     }
 
   if (for_eh)
@@ -3477,7 +3484,8 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
 
          if (fde->uses_eh_lsda)
            {
-             ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", fde->funcdef_number);
+             ASM_GENERATE_INTERNAL_LABEL (l1, second ? "LLSDAC" : "LLSDA",
+                                          fde->funcdef_number);
              dw2_asm_output_encoded_addr_rtx (lsda_encoding,
                                               gen_rtx_SYMBOL_REF (Pmode, l1),
                                               false,
@@ -3781,7 +3789,7 @@ output_call_frame_info (int for_eh)
 /* Emit .cfi_startproc and .cfi_personality/.cfi_lsda if needed.  */
 
 static void
-dwarf2out_do_cfi_startproc (void)
+dwarf2out_do_cfi_startproc (bool second)
 {
   int enc;
   rtx ref;
@@ -3810,7 +3818,7 @@ dwarf2out_do_cfi_startproc (void)
       char lab[20];
 
       enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
-      ASM_GENERATE_INTERNAL_LABEL (lab, "LLSDA",
+      ASM_GENERATE_INTERNAL_LABEL (lab, second ? "LLSDAC" : "LLSDA",
                                   current_function_funcdef_no);
       ref = gen_rtx_SYMBOL_REF (Pmode, lab);
       SYMBOL_REF_FLAGS (ref) = SYMBOL_FLAG_LOCAL;
@@ -3929,7 +3937,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
 #endif
 
   if (dwarf2out_do_cfi_asm ())
-    dwarf2out_do_cfi_startproc ();
+    dwarf2out_do_cfi_startproc (false);
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -4038,7 +4046,7 @@ dwarf2out_switch_text_section (void)
 
   if (dwarf2out_do_cfi_asm ())
     {
-      dwarf2out_do_cfi_startproc ();
+      dwarf2out_do_cfi_startproc (true);
       /* As this is a different FDE, insert all current CFI instructions
         again.  */
       output_cfis (fde->dw_fde_cfi, true, fde, true);
index 06e5529..d72029c 100644 (file)
@@ -169,7 +169,7 @@ static int action_record_eq (const void *, const void *);
 static hashval_t action_record_hash (const void *);
 static int add_action_record (htab_t, int, int);
 static int collect_one_action_chain (htab_t, struct eh_region_d *);
-static int add_call_site (rtx, int);
+static int add_call_site (rtx, int, int);
 
 static void push_uleb128 (varray_type *, unsigned int);
 static void push_sleb128 (varray_type *, int);
@@ -177,7 +177,7 @@ static void push_sleb128 (varray_type *, int);
 static int dw2_size_of_call_site_table (void);
 static int sjlj_size_of_call_site_table (void);
 #endif
-static void dw2_output_call_site_table (void);
+static void dw2_output_call_site_table (int, int);
 static void sjlj_output_call_site_table (void);
 
 \f
@@ -2337,7 +2337,8 @@ sjlj_assign_call_site_values (rtx dispatch_label, struct sjlj_lp_info *lp_info)
          index = -1;
        /* Otherwise, look it up in the table.  */
        else
-         index = add_call_site (GEN_INT (lp_info[i].dispatch_index), action);
+         index = add_call_site (GEN_INT (lp_info[i].dispatch_index),
+                                action, 0);
 
        lp_info[i].call_site_index = index;
       }
@@ -3784,7 +3785,7 @@ collect_one_action_chain (htab_t ar_hash, struct eh_region_d *region)
 }
 
 static int
-add_call_site (rtx landing_pad, int action)
+add_call_site (rtx landing_pad, int action, int section)
 {
   call_site_record record;
   
@@ -3792,9 +3793,11 @@ add_call_site (rtx landing_pad, int action)
   record->landing_pad = landing_pad;
   record->action = action;
 
-  VEC_safe_push (call_site_record, gc, crtl->eh.call_site_record, record);
+  VEC_safe_push (call_site_record, gc,
+                crtl->eh.call_site_record[section], record);
 
-  return call_site_base + VEC_length (call_site_record, crtl->eh.call_site_record) - 1;
+  return call_site_base + VEC_length (call_site_record,
+                                     crtl->eh.call_site_record[section]) - 1;
 }
 
 /* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
@@ -3811,6 +3814,14 @@ convert_to_eh_region_ranges (void)
   rtx last_landing_pad = NULL_RTX;
   rtx first_no_action_insn = NULL_RTX;
   int call_site = 0;
+  int cur_sec = 0;
+  rtx section_switch_note = NULL_RTX;
+  rtx first_no_action_insn_before_switch = NULL_RTX;
+  rtx last_no_action_insn_before_switch = NULL_RTX;
+  rtx *pad_map = NULL;
+  sbitmap pad_loc = NULL;
+  int min_labelno = 0, max_labelno = 0;
+  int saved_call_site_base = call_site_base;
 
   if (USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL)
     return 0;
@@ -3885,9 +3896,27 @@ convert_to_eh_region_ranges (void)
            if (last_action >= -1)
              {
                /* If we delayed the creation of the begin, do it now.  */
+               if (first_no_action_insn_before_switch)
+                 {
+                   call_site = add_call_site (NULL_RTX, 0, 0);
+                   note
+                     = emit_note_before (NOTE_INSN_EH_REGION_BEG,
+                                         first_no_action_insn_before_switch);
+                   NOTE_EH_HANDLER (note) = call_site;
+                   if (first_no_action_insn)
+                     {
+                       note
+                         = emit_note_after (NOTE_INSN_EH_REGION_END,
+                                            last_no_action_insn_before_switch);
+                       NOTE_EH_HANDLER (note) = call_site;
+                     }
+                   else
+                     gcc_assert (last_action_insn
+                                 == last_no_action_insn_before_switch);
+                 }
                if (first_no_action_insn)
                  {
-                   call_site = add_call_site (NULL_RTX, 0);
+                   call_site = add_call_site (NULL_RTX, 0, cur_sec);
                    note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
                                             first_no_action_insn);
                    NOTE_EH_HANDLER (note) = call_site;
@@ -3904,7 +3933,8 @@ convert_to_eh_region_ranges (void)
            if (this_action >= -1)
              {
                call_site = add_call_site (this_landing_pad,
-                                          this_action < 0 ? 0 : this_action);
+                                          this_action < 0 ? 0 : this_action,
+                                          cur_sec);
                note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
                NOTE_EH_HANDLER (note) = call_site;
              }
@@ -3914,6 +3944,37 @@ convert_to_eh_region_ranges (void)
          }
        last_action_insn = iter;
       }
+    else if (NOTE_P (iter)
+            && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+      {
+       gcc_assert (section_switch_note == NULL_RTX);
+       gcc_assert (flag_reorder_blocks_and_partition);
+       section_switch_note = iter;
+       if (first_no_action_insn)
+         {
+           first_no_action_insn_before_switch = first_no_action_insn;
+           last_no_action_insn_before_switch = last_action_insn;
+           first_no_action_insn = NULL_RTX;
+           gcc_assert (last_action == -1);
+           last_action = -3;
+         }
+       /* Force closing of current EH region before section switch and
+          opening a new one afterwards.  */
+       else if (last_action != -3)
+         last_landing_pad = pc_rtx;
+       call_site_base += VEC_length (call_site_record,
+                                     crtl->eh.call_site_record[cur_sec]);
+       cur_sec++;
+       gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL);
+       crtl->eh.call_site_record[cur_sec]
+         = VEC_alloc (call_site_record, gc, 10);
+       max_labelno = max_label_num ();
+       min_labelno = get_first_label_num ();
+       pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1);
+       pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1);
+      }
+    else if (LABEL_P (iter) && pad_map)
+      SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno);
 
   if (last_action >= -1 && ! first_no_action_insn)
     {
@@ -3921,6 +3982,105 @@ convert_to_eh_region_ranges (void)
       NOTE_EH_HANDLER (note) = call_site;
     }
 
+  call_site_base = saved_call_site_base;
+
+  if (pad_map)
+    {
+      /* When doing hot/cold partitioning, ensure landing pads are
+        always in the same section as the EH region, .gcc_except_table
+        can't express it otherwise.  */
+      for (cur_sec = 0; cur_sec < 2; cur_sec++)
+       {
+         int i, idx;
+         int n = VEC_length (call_site_record,
+                             crtl->eh.call_site_record[cur_sec]);
+         basic_block prev_bb = NULL, padbb;
+
+         for (i = 0; i < n; ++i)
+           {
+             struct call_site_record_d *cs =
+               VEC_index (call_site_record,
+                          crtl->eh.call_site_record[cur_sec], i);
+             rtx jump, note;
+
+             if (cs->landing_pad == NULL_RTX)
+               continue;
+             idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno;
+             /* If the landing pad is in the correct section, nothing
+                is needed.  */
+             if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0))
+               continue;
+             /* Otherwise, if we haven't seen this pad yet, we need to
+                add a new label and jump to the correct section.  */
+             if (pad_map[idx] == NULL_RTX)
+               {
+                 pad_map[idx] = gen_label_rtx ();
+                 if (prev_bb == NULL)
+                   for (iter = section_switch_note;
+                        iter; iter = PREV_INSN (iter))
+                     if (NOTE_INSN_BASIC_BLOCK_P (iter))
+                       {
+                         prev_bb = NOTE_BASIC_BLOCK (iter);
+                         break;
+                       }
+                 if (cur_sec == 0)
+                   {
+                     note = emit_label_before (pad_map[idx],
+                                               section_switch_note);
+                     jump = emit_jump_insn_before (gen_jump (cs->landing_pad),
+                                                   section_switch_note);
+                   }
+                 else
+                   {
+                     jump = emit_jump_insn_after (gen_jump (cs->landing_pad),
+                                                  section_switch_note);
+                     note = emit_label_after (pad_map[idx],
+                                              section_switch_note);
+                   }
+                 JUMP_LABEL (jump) = cs->landing_pad;
+                 add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
+                 iter = NEXT_INSN (cs->landing_pad);
+                 if (iter && NOTE_INSN_BASIC_BLOCK_P (iter))
+                   padbb = NOTE_BASIC_BLOCK (iter);
+                 else
+                   padbb = NULL;
+                 if (padbb && prev_bb
+                     && BB_PARTITION (padbb) != BB_UNPARTITIONED)
+                   {
+                     basic_block bb;
+                     int part
+                       = BB_PARTITION (padbb) == BB_COLD_PARTITION
+                         ? BB_HOT_PARTITION : BB_COLD_PARTITION;
+                     edge_iterator ei;
+                     edge e;
+
+                     bb = create_basic_block (note, jump, prev_bb);
+                     make_single_succ_edge (bb, padbb, EDGE_CROSSING);
+                     BB_SET_PARTITION (bb, part);
+                     for (ei = ei_start (padbb->preds);
+                          (e = ei_safe_edge (ei)); )
+                       {
+                         if ((e->flags & (EDGE_EH|EDGE_CROSSING))
+                             == (EDGE_EH|EDGE_CROSSING))
+                           {
+                             redirect_edge_succ (e, bb);
+                             e->flags &= ~EDGE_CROSSING;
+                           }
+                         else
+                           ei_next (&ei);
+                       }
+                     if (cur_sec == 0)
+                       prev_bb = bb;
+                   }
+               }
+             cs->landing_pad = pad_map[idx];
+           }
+       }
+
+      sbitmap_free (pad_loc);
+      XDELETEVEC (pad_map);
+    }
+
   htab_delete (ar_hash);
   return 0;
 }
@@ -3981,16 +4141,16 @@ push_sleb128 (varray_type *data_area, int value)
 \f
 #ifndef HAVE_AS_LEB128
 static int
-dw2_size_of_call_site_table (void)
+dw2_size_of_call_site_table (int section)
 {
-  int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+  int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
   int size = n * (4 + 4 + 4);
   int i;
 
   for (i = 0; i < n; ++i)
     {
       struct call_site_record_d *cs =
-       VEC_index (call_site_record, crtl->eh.call_site_record, i);
+       VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
       size += size_of_uleb128 (cs->action);
     }
 
@@ -4000,14 +4160,14 @@ dw2_size_of_call_site_table (void)
 static int
 sjlj_size_of_call_site_table (void)
 {
-  int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+  int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
   int size = 0;
   int i;
 
   for (i = 0; i < n; ++i)
     {
       struct call_site_record_d *cs =
-       VEC_index (call_site_record, crtl->eh.call_site_record, i);
+       VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
       size += size_of_uleb128 (INTVAL (cs->landing_pad));
       size += size_of_uleb128 (cs->action);
     }
@@ -4017,15 +4177,23 @@ sjlj_size_of_call_site_table (void)
 #endif
 
 static void
-dw2_output_call_site_table (void)
+dw2_output_call_site_table (int cs_format, int section)
 {
-  int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+  int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
   int i;
+  const char *begin;
+
+  if (section == 0)
+    begin = current_function_func_begin_label;
+  else if (first_function_block_is_cold)
+    begin = crtl->subsections.hot_section_label;
+  else
+    begin = crtl->subsections.cold_section_label;
 
   for (i = 0; i < n; ++i)
     {
       struct call_site_record_d *cs =
-       VEC_index (call_site_record, crtl->eh.call_site_record, i);
+       VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
       char reg_start_lab[32];
       char reg_end_lab[32];
       char landing_pad_lab[32];
@@ -4041,30 +4209,29 @@ dw2_output_call_site_table (void)
         generic arithmetic.  */
       /* ??? Perhaps use attr_length to choose data1 or data2 instead of
         data4 if the function is small enough.  */
-#ifdef HAVE_AS_LEB128
-      dw2_asm_output_delta_uleb128 (reg_start_lab,
-                                   current_function_func_begin_label,
-                                   "region %d start", i);
-      dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
-                                   "length");
-      if (cs->landing_pad)
-       dw2_asm_output_delta_uleb128 (landing_pad_lab,
-                                     current_function_func_begin_label,
-                                     "landing pad");
-      else
-       dw2_asm_output_data_uleb128 (0, "landing pad");
-#else
-      dw2_asm_output_delta (4, reg_start_lab,
-                           current_function_func_begin_label,
-                           "region %d start", i);
-      dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
-      if (cs->landing_pad)
-       dw2_asm_output_delta (4, landing_pad_lab,
-                             current_function_func_begin_label,
-                             "landing pad");
+      if (cs_format == DW_EH_PE_uleb128)
+       {
+         dw2_asm_output_delta_uleb128 (reg_start_lab, begin,
+                                       "region %d start", i);
+         dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
+                                       "length");
+         if (cs->landing_pad)
+           dw2_asm_output_delta_uleb128 (landing_pad_lab, begin,
+                                         "landing pad");
+         else
+           dw2_asm_output_data_uleb128 (0, "landing pad");
+       }
       else
-       dw2_asm_output_data (4, 0, "landing pad");
-#endif
+       {
+         dw2_asm_output_delta (4, reg_start_lab, begin,
+                               "region %d start", i);
+         dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
+         if (cs->landing_pad)
+           dw2_asm_output_delta (4, landing_pad_lab, begin,
+                                 "landing pad");
+         else
+           dw2_asm_output_data (4, 0, "landing pad");
+       }
       dw2_asm_output_data_uleb128 (cs->action, "action");
     }
 
@@ -4074,13 +4241,13 @@ dw2_output_call_site_table (void)
 static void
 sjlj_output_call_site_table (void)
 {
-  int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+  int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
   int i;
 
   for (i = 0; i < n; ++i)
     {
       struct call_site_record_d *cs =
-       VEC_index (call_site_record, crtl->eh.call_site_record, i);
+       VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
 
       dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
                                   "region %d landing pad", i);
@@ -4192,8 +4359,9 @@ output_ttype (tree type, int tt_format, int tt_format_size)
     dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
 }
 
-void
-output_function_exception_table (const char * ARG_UNUSED (fnname))
+static void
+output_one_function_exception_table (const char * ARG_UNUSED (fnname),
+                                    int section)
 {
   int tt_format, cs_format, lp_format, i, n;
 #ifdef HAVE_AS_LEB128
@@ -4206,13 +4374,6 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
   int have_tt_data;
   int tt_format_size = 0;
 
-  /* Not all functions need anything.  */
-  if (! crtl->uses_eh_lsda)
-    return;
-
-  if (eh_personality_libfunc)
-    assemble_external_libcall (eh_personality_libfunc);
-
 #ifdef TARGET_UNWIND_INFO
   /* TODO: Move this into target file.  */
   fputs ("\t.personality\t", asm_out_file);
@@ -4237,7 +4398,8 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
     {
       tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
 #ifdef HAVE_AS_LEB128
-      ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT",
+      ASM_GENERATE_INTERNAL_LABEL (ttype_label,
+                                  section ? "LLSDATTC" : "LLSDATT",
                                   current_function_funcdef_no);
 #endif
       tt_format_size = size_of_encoded_value (tt_format);
@@ -4245,8 +4407,8 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
       assemble_align (tt_format_size * BITS_PER_UNIT);
     }
 
-  targetm.asm_out.internal_label (asm_out_file, "LLSDA",
-                            current_function_funcdef_no);
+  targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA",
+                                 current_function_funcdef_no);
 
   /* The LSDA header.  */
 
@@ -4269,7 +4431,7 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
   if (USING_SJLJ_EXCEPTIONS)
     call_site_len = sjlj_size_of_call_site_table ();
   else
-    call_site_len = dw2_size_of_call_site_table ();
+    call_site_len = dw2_size_of_call_site_table (section);
 #endif
 
   /* A pc-relative 4-byte displacement to the @TType data.  */
@@ -4277,7 +4439,8 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
     {
 #ifdef HAVE_AS_LEB128
       char ttype_after_disp_label[32];
-      ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, "LLSDATTD",
+      ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
+                                  section ? "LLSDATTDC" : "LLSDATTD",
                                   current_function_funcdef_no);
       dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
                                    "@TType base offset");
@@ -4323,9 +4486,11 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
                       eh_data_format_name (cs_format));
 
 #ifdef HAVE_AS_LEB128
-  ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
+  ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
+                              section ? "LLSDACSBC" : "LLSDACSB",
                               current_function_funcdef_no);
-  ASM_GENERATE_INTERNAL_LABEL (cs_end_label, "LLSDACSE",
+  ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
+                              section ? "LLSDACSEC" : "LLSDACSE",
                               current_function_funcdef_no);
   dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
                                "Call-site table length");
@@ -4333,14 +4498,14 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
   if (USING_SJLJ_EXCEPTIONS)
     sjlj_output_call_site_table ();
   else
-    dw2_output_call_site_table ();
+    dw2_output_call_site_table (cs_format, section);
   ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
 #else
-  dw2_asm_output_data_uleb128 (call_site_len,"Call-site table length");
+  dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
   if (USING_SJLJ_EXCEPTIONS)
     sjlj_output_call_site_table ();
   else
-    dw2_output_call_site_table ();
+    dw2_output_call_site_table (cs_format, section);
 #endif
 
   /* ??? Decode and interpret the data for flag_debug_asm.  */
@@ -4377,6 +4542,21 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
        dw2_asm_output_data (1, VARRAY_UCHAR (crtl->eh.ehspec_data, i),
                             (i ? NULL : "Exception specification table"));
     }
+}
+
+void
+output_function_exception_table (const char * ARG_UNUSED (fnname))
+{
+  /* Not all functions need anything.  */
+  if (! crtl->uses_eh_lsda)
+    return;
+
+  if (eh_personality_libfunc)
+    assemble_external_libcall (eh_personality_libfunc);
+
+  output_one_function_exception_table (fnname, 0);
+  if (crtl->eh.call_site_record[1] != NULL)
+    output_one_function_exception_table (fnname, 1);
 
   switch_to_section (current_function_section ());
 }
index 8f69429..ac3a174 100644 (file)
@@ -156,7 +156,7 @@ struct GTY(()) rtl_eh {
   varray_type ehspec_data;
   varray_type action_record_data;
 
-  VEC(call_site_record,gc) *call_site_record;
+  VEC(call_site_record,gc) *call_site_record[2];
 };
 
 #define pending_stack_adjust (crtl->expr.x_pending_stack_adjust)
index 33635dd..59c24b6 100644 (file)
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "debug.h"
 #include "plugin.h"
+#include "except.h"
 
 /* Value of the -G xx switch, and whether it was passed or not.  */
 unsigned HOST_WIDE_INT g_switch_value;
@@ -1036,10 +1037,15 @@ decode_options (unsigned int argc, const char **argv)
      generating unwind info.  If flag_exceptions is turned on we need to
      turn off the partitioning optimization.  */
 
-  if (flag_exceptions && flag_reorder_blocks_and_partition)
+  if (flag_exceptions && flag_reorder_blocks_and_partition
+      && (USING_SJLJ_EXCEPTIONS
+#ifdef TARGET_UNWIND_INFO
+         || 1
+#endif
+        ))
     {
       inform (input_location, 
-             "-freorder-blocks-and-partition does not work with exceptions");
+             "-freorder-blocks-and-partition does not work with exceptions on this architecture");
       flag_reorder_blocks_and_partition = 0;
       flag_reorder_blocks = 1;
     }
@@ -1048,9 +1054,15 @@ decode_options (unsigned int argc, const char **argv)
      optimization.  */
 
   if (flag_unwind_tables && ! targetm.unwind_tables_default
-      && flag_reorder_blocks_and_partition)
+      && flag_reorder_blocks_and_partition
+      && (USING_SJLJ_EXCEPTIONS
+#ifdef TARGET_UNWIND_INFO
+         || 1
+#endif
+        ))
     {
-      inform (input_location, "-freorder-blocks-and-partition does not support unwind info");
+      inform (input_location,
+             "-freorder-blocks-and-partition does not support unwind info on this architecture");
       flag_reorder_blocks_and_partition = 0;
       flag_reorder_blocks = 1;
     }
@@ -1061,7 +1073,12 @@ decode_options (unsigned int argc, const char **argv)
 
   if (flag_reorder_blocks_and_partition
       && (!targetm.have_named_sections
-         || (flag_unwind_tables && targetm.unwind_tables_default)))
+         || (flag_unwind_tables && targetm.unwind_tables_default
+             && (USING_SJLJ_EXCEPTIONS
+#ifdef TARGET_UNWIND_INFO
+                 || 1
+#endif
+                ))))
     {
       inform (input_location,
              "-freorder-blocks-and-partition does not work on this architecture");
index 0dc1b9d..4d3f9b0 100644 (file)
@@ -1,3 +1,7 @@
+2009-08-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/tree-prof/partition1.C: New test.
+
 2009-08-06  Richard Earnshaw  <rearnsha@arm.com>
 
        * gcc.target/arm/abitest.h: Allow the test function to have a PCS
diff --git a/gcc/testsuite/g++.dg/tree-prof/partition1.C b/gcc/testsuite/g++.dg/tree-prof/partition1.C
new file mode 100644 (file)
index 0000000..d0dcbc4
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+struct A { A () __attribute__((noinline)); ~A () __attribute__((noinline)); };
+A::A () { asm volatile ("" : : : "memory"); }
+A::~A () { asm volatile ("" : : : "memory"); }
+
+int bar () __attribute__((noinline));
+void foo () __attribute__((noinline));
+
+volatile int k, l;
+
+int bar (int i)
+{
+  void *p = __builtin_alloca (i);
+  asm volatile ("" : : "r" (i), "r" (p) : "memory");
+  if (k) throw 6;
+  return ++l;
+}
+
+void foo ()
+{
+  A a;
+  try {
+    A b;
+    int i = bar (5);
+    try { throw 6; } catch (int) {}
+    if (__builtin_expect (i < 4500, 0)) {
+      bar (7);
+      try { bar (8); } catch (long) {}
+      bar (10);
+      if (__builtin_expect (i < 0, 0)) {
+       try { bar (12); } catch (...) {}
+       bar (16);
+       bar (122);
+      } else {
+       try { bar (bar (7)); } catch (int) {}
+      }
+    } else {
+      try { bar (bar (bar (9))); } catch (...) {}
+      bar (5);
+    }
+  } catch (...) {
+  }
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 10000; i++)
+    foo ();
+}