diff mbox

Initial shrink-wrapping patch

Message ID 4E8CEC99.2000105@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt Oct. 5, 2011, 11:47 p.m. UTC
On 10/06/11 01:04, Ian Lance Taylor wrote:
> On Wed, Oct 5, 2011 at 10:17 AM, Bernd Schmidt <bernds@codesourcery.com> wrote:
>>
>> I've committed the following after a x86_64-linux bootstrap.
> 
> This patch appears to have broken the Go bootstrap when compiling a C
> file in libgo.  Here is a reduced test case:
> 
> static struct
> {
>   int n;
>   unsigned int m;
>   _Bool f;
> } g;
> 
> _Bool
> f (int s)
> {
>   unsigned int b, m;
> 
>   if (!g.f)
>     return 0;
>   b = 1 << s;
>   while (1)
>     {
>       m = g.m;
>       if (m & b)
>         break;
>       if (__sync_bool_compare_and_swap (&g.m, m, m|b))
>         {
>           if (m == 0)
>             f2 (&g.n);
>           break;
>         }
>     }
>   return 1;
> }
> 
> Compiling this file with -O2 -fsplit-stack causes an ICE:
> 
> foo.c:29:1: internal compiler error: in maybe_record_trace_start, at
> dwarf2cfi.c:2243
> 
> Compiling the file with -O2 -fsplit-stack -fno-shrink-wrap works.

This appears to be because the split prologue contains a jump, which
means the find_many_sub_blocks call reorders the block numbers, and our
indices into bb_flags are off.

I'm testing the following patch, but it won't finish today - feel free
to test and check it in, or to just disable shrink-wrapping with split
prologues.


Bernd

Comments

Ian Lance Taylor Oct. 6, 2011, 3:17 a.m. UTC | #1
Bernd Schmidt <bernds@codesourcery.com> writes:

> This appears to be because the split prologue contains a jump, which
> means the find_many_sub_blocks call reorders the block numbers, and our
> indices into bb_flags are off.
>
> I'm testing the following patch, but it won't finish today - feel free
> to test and check it in, or to just disable shrink-wrapping with split
> prologues.

Thinking about it I think this is the wrong approach.  The -fsplit-stack
code by definition has to wrap the entire function and it can not modify
any callee-saved registers.  We should do shrink wrapping before
-fsplit-stack, not the other way around.

Ian
Bernd Schmidt Oct. 6, 2011, 10:29 a.m. UTC | #2
On 10/06/11 05:17, Ian Lance Taylor wrote:
> Thinking about it I think this is the wrong approach.  The -fsplit-stack
> code by definition has to wrap the entire function and it can not modify
> any callee-saved registers.  We should do shrink wrapping before
> -fsplit-stack, not the other way around.

Sorry, I'm not following what you're saying here. Can you elaborate?


Bernd
Bernd Schmidt Oct. 6, 2011, 1:37 p.m. UTC | #3
On 10/06/11 01:47, Bernd Schmidt wrote:
> This appears to be because the split prologue contains a jump, which
> means the find_many_sub_blocks call reorders the block numbers, and our
> indices into bb_flags are off.

Testing of the patch completed - ok? Regardless of split-stack it seems
like a cleanup and eliminates a potential source of errors.


Bernd
Richard Henderson Oct. 6, 2011, 3:37 p.m. UTC | #4
On 10/06/2011 06:37 AM, Bernd Schmidt wrote:
> On 10/06/11 01:47, Bernd Schmidt wrote:
>> This appears to be because the split prologue contains a jump, which
>> means the find_many_sub_blocks call reorders the block numbers, and our
>> indices into bb_flags are off.
> 
> Testing of the patch completed - ok? Regardless of split-stack it seems
> like a cleanup and eliminates a potential source of errors.

Yes, patch is ok.


r~
Ian Lance Taylor Oct. 6, 2011, 3:57 p.m. UTC | #5
Bernd Schmidt <bernds@codesourcery.com> writes:

> On 10/06/11 05:17, Ian Lance Taylor wrote:
>> Thinking about it I think this is the wrong approach.  The -fsplit-stack
>> code by definition has to wrap the entire function and it can not modify
>> any callee-saved registers.  We should do shrink wrapping before
>> -fsplit-stack, not the other way around.
>
> Sorry, I'm not following what you're saying here. Can you elaborate?

Basically -fsplit-stack wraps the entire function in code that (on
x86_64) looks like

	cmpq	%fs:112, %rsp
	jae	.L2
	movl	$24, %r10d
	movl	$0, %r11d
	call	__morestack
	ret
.L2:

There is absolutely no reason to try to shrink wrap that code.  It will
never help.  That code always has to be first.  It especially has to be
first because the gold linker recognizes the prologue specially when a
split-stack function calls a non-split-stack function, in order to
request a larger stack.

Therefore, it seems to me that we should apply shrink wrapping to the
function as it exists *before* the split-stack prologue is created.  The
flag_split_stack bit should be moved after the flag_shrink_wrap bit.

Ian
diff mbox

Patch

Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 179577)
+++ gcc/function.c	(working copy)
@@ -5455,7 +5455,7 @@  thread_prologue_and_epilogue_insns (void
   basic_block last_bb;
   bool last_bb_active;
 #ifdef HAVE_simple_return
-  bool unconverted_simple_returns = false;
+  VEC (basic_block, heap) *unconverted_simple_returns = NULL;
   basic_block simple_return_block_hot = NULL;
   basic_block simple_return_block_cold = NULL;
   bool nonempty_prologue;
@@ -5876,7 +5876,8 @@  thread_prologue_and_epilogue_insns (void
 		{
 #ifdef HAVE_simple_return
 		  if (simple_p)
-		    unconverted_simple_returns = true;
+		    VEC_safe_push (basic_block, heap,
+				   unconverted_simple_returns, bb);
 #endif
 		  continue;
 		}
@@ -5894,7 +5895,8 @@  thread_prologue_and_epilogue_insns (void
 	    {
 #ifdef HAVE_simple_return
 	      if (simple_p)
-		unconverted_simple_returns = true;
+		VEC_safe_push (basic_block, heap,
+			       unconverted_simple_returns, bb);
 #endif
 	      continue;
 	    }
@@ -6042,10 +6044,11 @@  epilogue_done:
      convert to conditional simple_returns, but couldn't for some
      reason, create a block to hold a simple_return insn and redirect
      those remaining edges.  */
-  if (unconverted_simple_returns)
+  if (!VEC_empty (basic_block, unconverted_simple_returns))
     {
-      edge_iterator ei2;
       basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
+      basic_block src_bb;
+      int i;
 
       gcc_assert (entry_edge != orig_entry_edge);
 
@@ -6062,19 +6065,12 @@  epilogue_done:
 	    simple_return_block_cold = e->dest;
 	}
 
-    restart_scan:
-      for (ei2 = ei_start (last_bb->preds); (e = ei_safe_edge (ei2)); )
+      FOR_EACH_VEC_ELT (basic_block, unconverted_simple_returns, i, src_bb)
 	{
-	  basic_block bb = e->src;
+	  edge e = find_edge (src_bb, last_bb);
 	  basic_block *pdest_bb;
 
-	  if (bb == ENTRY_BLOCK_PTR
-	      || bitmap_bit_p (&bb_flags, bb->index))
-	    {
-	      ei_next (&ei2);
-	      continue;
-	    }
-	  if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
+	  if (BB_PARTITION (src_bb) == BB_HOT_PARTITION)
 	    pdest_bb = &simple_return_block_hot;
 	  else
 	    pdest_bb = &simple_return_block_cold;
@@ -6094,8 +6090,8 @@  epilogue_done:
 	      make_edge (bb, EXIT_BLOCK_PTR, 0);
 	    }
 	  redirect_edge_and_branch_force (e, *pdest_bb);
-	  goto restart_scan;
 	}
+      VEC_free (basic_block, heap, unconverted_simple_returns);
     }
 #endif