This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Allow exceptions together with -freorder-blocks-and-partition


Hi!

This is a follow-up to my recent changes to support unwinding with
-freorder-blocks-and-partition, which allows also exceptions to be used
when doing hot/cold partitioning.  I haven't touched TARGET_UNWIND_INFO
targets (ia64/arm, there it would be more effort) and sjlj (probably
shouldn't be that hard if anyone is interested).
What the patch does is basically just make sure no EH range crosses between
the hot/cold sections and prepares two call site tables instead of one,
emits two .gcc_except_table section records, one for hot, one for cold
section.  ATM the patch adds unconditional jumps from one section to another
one for landing pads if a landing pad in one section (typically cold) is
used by other section's EH range.  In theory without modifying personality
functions we could get away without those on i386 by using DW_EH_PE_sdata4
call site table format instead of the usual DW_EH_PE_uleb128 one
in hot/cold partitioned functions and use DW_EH_PE_pcrel encoded
__GLOBAL_OFFSET_TABLE__ LPStart and landing pads relative to that
(@GOTOFF).  But I have no idea how to optimize similarly e.g. on x86-64,
because e.g. using DW_EH_PE_pcrel encoding of landing pads couldn't be
used for begin/size too and also encoding a 0 is impossible in that
encoding.  For -fno-pic code small enough to fix into low 4GB we could
still use LPStart 0 and absolute DW_EH_PE_udata4 landing pad values.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2009-07-30  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.

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

--- gcc/dwarf2out.c.jj	2009-07-27 14:20:51.000000000 +0200
+++ gcc/dwarf2out.c	2009-07-30 14:48:09.000000000 +0200
@@ -3413,15 +3413,22 @@ output_fde (dw_fde_ref fde, bool for_eh,
       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)
@@ -3461,7 +3468,8 @@ output_fde (dw_fde_ref fde, bool for_eh,
 
 	  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,
@@ -3765,7 +3773,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;
@@ -3794,7 +3802,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;
@@ -3913,7 +3921,7 @@ dwarf2out_begin_prologue (unsigned int l
 #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
@@ -4022,7 +4030,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);
--- gcc/except.c.jj	2009-07-20 20:42:09.000000000 +0200
+++ gcc/except.c	2009-07-30 14:43:14.000000000 +0200
@@ -169,7 +169,7 @@ static int action_record_eq (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 *,
 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);
 
 
@@ -2337,7 +2337,8 @@ sjlj_assign_call_site_values (rtx dispat
 	  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
 }
 
 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 acti
   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, in
 
 #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, 
     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 c
   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 c
     {
       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 c
       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 c
   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 c
     {
 #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 c
 		       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 c
   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 c
 	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 ());
 }
--- gcc/opts.c.jj	2009-07-20 20:42:09.000000000 +0200
+++ gcc/opts.c	2009-07-30 14:50:14.000000000 +0200
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  
 #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
      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
      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
 
   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");
--- gcc/Makefile.in.jj	2009-07-27 08:47:01.000000000 +0200
+++ gcc/Makefile.in	2009-07-30 14:50:37.000000000 +0200
@@ -2506,7 +2506,7 @@ opts.o : opts.c opts.h options.h $(TOPLE
    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) \
--- gcc/function.h.jj	2009-06-30 13:10:30.000000000 +0200
+++ gcc/function.h	2009-07-29 17:24:21.000000000 +0200
@@ -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)
--- gcc/testsuite/g++.dg/tree-prof/partition1.C.jj	2009-07-30 12:35:43.000000000 +0200
+++ gcc/testsuite/g++.dg/tree-prof/partition1.C	2009-07-30 12:36:06.000000000 +0200
@@ -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 ();
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]