diff mbox

[committed] 4 backports from trunk to 4.6 branch

Message ID 20111208134530.GL1957@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 8, 2011, 1:45 p.m. UTC
Hi!

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to 4.6
branch:

	Jakub
2011-12-08  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-11-30  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/48721
	* sched-deps.c (sched_analyze_insn): For SIBLING_CALL_P set
	reg_pending_barrier to TRUE_BARRIER.

	* gcc.target/i386/pr48721.c: New test.
2011-12-08  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-12-05  Jakub Jelinek  <jakub@redhat.com>
		    Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/51323
	PR middle-end/50074
	* calls.c (internal_arg_pointer_exp_state): New variable.
	(internal_arg_pointer_based_exp_1,
	internal_arg_pointer_exp_scan): New functions.
	(internal_arg_pointer_based_exp): New function.
	(mem_overlaps_already_clobbered_arg_p): Use it.
	(expand_call): Free internal_arg_pointer_exp_state.cache vector
	and clear internal_arg_pointer_exp_state.scan_start.

	2011-11-26  Joern Rennecke  <joern.rennecke@embecosm.com>

	PR middle-end/50074
	* calls.c (mem_overlaps_already_clobbered_arg_p):
	Return false if no outgoing arguments have been stored so far.

	2011-12-05  Jakub Jelinek  <jakub@redhat.com>
		    Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/51323
	PR middle-end/50074
	* gcc.c-torture/execute/pr51323.c: New test.

--- gcc/calls.c	(revision 181999)
+++ gcc/calls.c	(revision 182000)
@@ -1548,6 +1548,129 @@ rtx_for_function_call (tree fndecl, tree
   return funexp;
 }
 
+/* Internal state for internal_arg_pointer_based_exp and its helpers.  */
+static struct
+{
+  /* Last insn that has been scanned by internal_arg_pointer_based_exp_scan,
+     or NULL_RTX if none has been scanned yet.  */
+  rtx scan_start;
+  /* Vector indexed by REGNO - FIRST_PSEUDO_REGISTER, recording if a pseudo is
+     based on crtl->args.internal_arg_pointer.  The element is NULL_RTX if the
+     pseudo isn't based on it, a CONST_INT offset if the pseudo is based on it
+     with fixed offset, or PC if this is with variable or unknown offset.  */
+  VEC(rtx, heap) *cache;
+} internal_arg_pointer_exp_state;
+
+static rtx internal_arg_pointer_based_exp (rtx, bool);
+
+/* Helper function for internal_arg_pointer_based_exp.  Scan insns in
+   the tail call sequence, starting with first insn that hasn't been
+   scanned yet, and note for each pseudo on the LHS whether it is based
+   on crtl->args.internal_arg_pointer or not, and what offset from that
+   that pointer it has.  */
+
+static void
+internal_arg_pointer_based_exp_scan (void)
+{
+  rtx insn, scan_start = internal_arg_pointer_exp_state.scan_start;
+
+  if (scan_start == NULL_RTX)
+    insn = get_insns ();
+  else
+    insn = NEXT_INSN (scan_start);
+
+  while (insn)
+    {
+      rtx set = single_set (insn);
+      if (set && REG_P (SET_DEST (set)) && !HARD_REGISTER_P (SET_DEST (set)))
+	{
+	  rtx val = NULL_RTX;
+	  unsigned int idx = REGNO (SET_DEST (set)) - FIRST_PSEUDO_REGISTER;
+	  /* Punt on pseudos set multiple times.  */
+	  if (idx < VEC_length (rtx, internal_arg_pointer_exp_state.cache)
+	      && (VEC_index (rtx, internal_arg_pointer_exp_state.cache, idx)
+		  != NULL_RTX))
+	    val = pc_rtx;
+	  else
+	    val = internal_arg_pointer_based_exp (SET_SRC (set), false);
+	  if (val != NULL_RTX)
+	    {
+	      VEC_safe_grow_cleared (rtx, heap,
+				     internal_arg_pointer_exp_state.cache,
+				     idx + 1);
+	      VEC_replace (rtx, internal_arg_pointer_exp_state.cache,
+			   idx, val);
+	    }
+	}
+      if (NEXT_INSN (insn) == NULL_RTX)
+	scan_start = insn;
+      insn = NEXT_INSN (insn);
+    }
+
+  internal_arg_pointer_exp_state.scan_start = scan_start;
+}
+
+/* Helper function for internal_arg_pointer_based_exp, called through
+   for_each_rtx.  Return 1 if *LOC is a register based on
+   crtl->args.internal_arg_pointer.  Return -1 if *LOC is not based on it
+   and the subexpressions need not be examined.  Otherwise return 0.  */
+
+static int
+internal_arg_pointer_based_exp_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+  if (REG_P (*loc) && internal_arg_pointer_based_exp (*loc, false) != NULL_RTX)
+    return 1;
+  if (MEM_P (*loc))
+    return -1;
+  return 0;
+}
+
+/* Compute whether RTL is based on crtl->args.internal_arg_pointer.  Return
+   NULL_RTX if RTL isn't based on it, a CONST_INT offset if RTL is based on
+   it with fixed offset, or PC if this is with variable or unknown offset.
+   TOPLEVEL is true if the function is invoked at the topmost level.  */
+
+static rtx
+internal_arg_pointer_based_exp (rtx rtl, bool toplevel)
+{
+  if (CONSTANT_P (rtl))
+    return NULL_RTX;
+
+  if (rtl == crtl->args.internal_arg_pointer)
+    return const0_rtx;
+
+  if (REG_P (rtl) && HARD_REGISTER_P (rtl))
+    return NULL_RTX;
+
+  if (GET_CODE (rtl) == PLUS && CONST_INT_P (XEXP (rtl, 1)))
+    {
+      rtx val = internal_arg_pointer_based_exp (XEXP (rtl, 0), toplevel);
+      if (val == NULL_RTX || val == pc_rtx)
+	return val;
+      return plus_constant (val, INTVAL (XEXP (rtl, 1)));
+    }
+
+  /* When called at the topmost level, scan pseudo assignments in between the
+     last scanned instruction in the tail call sequence and the latest insn
+     in that sequence.  */
+  if (toplevel)
+    internal_arg_pointer_based_exp_scan ();
+
+  if (REG_P (rtl))
+    {
+      unsigned int idx = REGNO (rtl) - FIRST_PSEUDO_REGISTER;
+      if (idx < VEC_length (rtx, internal_arg_pointer_exp_state.cache))
+	return VEC_index (rtx, internal_arg_pointer_exp_state.cache, idx);
+
+      return NULL_RTX;
+    }
+
+  if (for_each_rtx (&rtl, internal_arg_pointer_based_exp_1, NULL))
+    return pc_rtx;
+
+  return NULL_RTX;
+}
+
 /* Return true if and only if SIZE storage units (usually bytes)
    starting from address ADDR overlap with already clobbered argument
    area.  This function is used to determine if we should give up a
@@ -1557,20 +1680,17 @@ static bool
 mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
 {
   HOST_WIDE_INT i;
+  rtx val;
 
-  if (addr == crtl->args.internal_arg_pointer)
-    i = 0;
-  else if (GET_CODE (addr) == PLUS
-	   && XEXP (addr, 0) == crtl->args.internal_arg_pointer
-	   && CONST_INT_P (XEXP (addr, 1)))
-    i = INTVAL (XEXP (addr, 1));
-  /* Return true for arg pointer based indexed addressing.  */
-  else if (GET_CODE (addr) == PLUS
-	   && (XEXP (addr, 0) == crtl->args.internal_arg_pointer
-	       || XEXP (addr, 1) == crtl->args.internal_arg_pointer))
+  if (sbitmap_empty_p (stored_args_map))
+    return false;
+  val = internal_arg_pointer_based_exp (addr, true);
+  if (val == NULL_RTX)
+    return false;
+  else if (val == pc_rtx)
     return true;
   else
-    return false;
+    i = INTVAL (val);
 
 #ifdef ARGS_GROW_DOWNWARD
   i = -i - size;
@@ -3175,6 +3295,8 @@ expand_call (tree exp, rtx target, int i
 	    }
 
 	  sbitmap_free (stored_args_map);
+	  internal_arg_pointer_exp_state.scan_start = NULL_RTX;
+	  VEC_free (rtx, heap, internal_arg_pointer_exp_state.cache);
 	}
       else
 	{
--- gcc/testsuite/gcc.c-torture/execute/pr51323.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr51323.c	(revision 182000)
@@ -0,0 +1,35 @@
+/* PR middle-end/51323 */
+
+extern void abort (void);
+struct S { int a, b, c; };
+int v;
+
+__attribute__((noinline, noclone)) void
+foo (int x, int y, int z)
+{
+  if (x != v || y != 0 || z != 9)
+    abort ();
+}
+
+static inline int
+baz (const struct S *p)
+{
+  return p->b;
+}
+
+__attribute__((noinline, noclone)) void
+bar (int x, struct S y)
+{
+  foo (baz (&y), 0, x);
+}
+
+int
+main ()
+{
+  struct S s;
+  v = 3; s.a = v - 1; s.b = v; s.c = v + 1;
+  bar (9, s);
+  v = 17; s.a = v - 1; s.b = v; s.c = v + 1;
+  bar (9, s);
+  return 0;
+}
2011-12-08  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-12-05  Jakub Jelinek  <jakub@redhat.com>

	PR c/51339
	* c-decl.c (c_finish_incomplete_decl, finish_decl): Call
	relayout_decl instead of layout_decl.

	* gcc.dg/gomp/pr51339.c: New test.

--- gcc/c-decl.c	(revision 182025)
+++ gcc/c-decl.c	(revision 182026)
@@ -719,7 +719,7 @@ c_finish_incomplete_decl (tree decl)
 
 	  complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
 
-	  layout_decl (decl, 0);
+	  relayout_decl (decl);
 	}
     }
 }
@@ -4311,7 +4311,7 @@ finish_decl (tree decl, location_t init_
       if (DECL_INITIAL (decl))
 	TREE_TYPE (DECL_INITIAL (decl)) = type;
 
-      layout_decl (decl, 0);
+      relayout_decl (decl);
     }
 
   if (TREE_CODE (decl) == VAR_DECL)
--- gcc/testsuite/gcc.dg/gomp/pr51339.c	(revision 0)
+++ gcc/testsuite/gcc.dg/gomp/pr51339.c	(revision 182026)
@@ -0,0 +1,15 @@
+/* PR c/51339 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+char g[] = "g";
+
+void
+foo (void)
+{
+#pragma omp parallel sections firstprivate (g) lastprivate (g)
+  {
+  #pragma omp section
+    g[0] = 'h';
+  }
+}
2011-12-08  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-12-05  Jakub Jelinek  <jakub@redhat.com>

	PR debug/51410
	* c-decl.c (pop_scope): Don't add DECL_EXTERNAL decls
	for debug info if scope is file_scope.

	* gcc.dg/debug/dwarf2/pr51410.c: New test.

--- gcc/c-decl.c	(revision 182026)
+++ gcc/c-decl.c	(revision 182027)
@@ -1196,7 +1196,7 @@ pop_scope (void)
 	      DECL_CHAIN (p) = BLOCK_VARS (block);
 	      BLOCK_VARS (block) = p;
 	    }
-	  else if (VAR_OR_FUNCTION_DECL_P (p))
+	  else if (VAR_OR_FUNCTION_DECL_P (p) && scope != file_scope)
 	    {
 	      /* For block local externs add a special
 		 DECL_EXTERNAL decl for debug info generation.  */
--- gcc/testsuite/gcc.dg/debug/dwarf2/pr51410.c	(revision 0)
+++ gcc/testsuite/gcc.dg/debug/dwarf2/pr51410.c	(revision 182027)
@@ -0,0 +1,13 @@
+/* PR debug/51410 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -gdwarf-2 -dA -fno-merge-debug-strings" } */
+
+int x;
+
+int
+foo (void)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "\\(DIE\[^\\r\\n\]*DW_TAG_variable\\)" 1 } } */

Comments

Mikael Pettersson Dec. 11, 2011, 1:48 p.m. UTC | #1
Jakub Jelinek writes:
 > Hi!
 > 
 > Bootstrapped/regtested on x86_64-linux and i686-linux, committed to 4.6
 > branch:
...
 > 2011-12-08  Jakub Jelinek  <jakub@redhat.com>
 > 
 > 	Backport from mainline
 > 	2011-12-05  Jakub Jelinek  <jakub@redhat.com>
 > 		    Eric Botcazou  <ebotcazou@adacore.com>
 > 
 > 	PR middle-end/51323
 > 	PR middle-end/50074
 > 	* calls.c (internal_arg_pointer_exp_state): New variable.
 > 	(internal_arg_pointer_based_exp_1,
 > 	internal_arg_pointer_exp_scan): New functions.
 > 	(internal_arg_pointer_based_exp): New function.
 > 	(mem_overlaps_already_clobbered_arg_p): Use it.
 > 	(expand_call): Free internal_arg_pointer_exp_state.cache vector
 > 	and clear internal_arg_pointer_exp_state.scan_start.
 > 
 > 	2011-11-26  Joern Rennecke  <joern.rennecke@embecosm.com>
 > 
 > 	PR middle-end/50074
 > 	* calls.c (mem_overlaps_already_clobbered_arg_p):
 > 	Return false if no outgoing arguments have been stored so far.
 > 
 > 	2011-12-05  Jakub Jelinek  <jakub@redhat.com>
 > 		    Eric Botcazou  <ebotcazou@adacore.com>
 > 
 > 	PR middle-end/51323
 > 	PR middle-end/50074
 > 	* gcc.c-torture/execute/pr51323.c: New test.

This patch, r182112 on 4.6 branch, caused a test suite regression on arm-linux-gnueabi:

+FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -O2  (internal compiler error)
+UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -O2
+FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -Os  (internal compiler error)
+UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -Os

because the compiler now ICEs:

20050713-1.c: In function 'bar3':
20050713-1.c:38:3: internal compiler error: in calculate_allocation, at vec.c:183

The same ICE also happens with today's trunk.

/Mikael
Jakub Jelinek Dec. 11, 2011, 9:37 p.m. UTC | #2
On Sun, Dec 11, 2011 at 02:48:52PM +0100, Mikael Pettersson wrote:
> This patch, r182112 on 4.6 branch, caused a test suite regression on arm-linux-gnueabi:
> 
> +FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -O2  (internal compiler error)
> +UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -O2
> +FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -Os  (internal compiler error)
> +UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -Os
> 
> because the compiler now ICEs:
> 
> 20050713-1.c: In function 'bar3':
> 20050713-1.c:38:3: internal compiler error: in calculate_allocation, at vec.c:183
> 
> The same ICE also happens with today's trunk.

Please file it into bugzilla (and the other bug too), I'll have a look.

	Jakub
Mikael Pettersson Dec. 12, 2011, 8:24 a.m. UTC | #3
Jakub Jelinek writes:
 > On Sun, Dec 11, 2011 at 02:48:52PM +0100, Mikael Pettersson wrote:
 > > This patch, r182112 on 4.6 branch, caused a test suite regression on arm-linux-gnueabi:
 > > 
 > > +FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -O2  (internal compiler error)
 > > +UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -O2
 > > +FAIL: gcc.c-torture/execute/20050713-1.c compilation,  -Os  (internal compiler error)
 > > +UNRESOLVED: gcc.c-torture/execute/20050713-1.c execution,  -Os
 > > 
 > > because the compiler now ICEs:
 > > 
 > > 20050713-1.c: In function 'bar3':
 > > 20050713-1.c:38:3: internal compiler error: in calculate_allocation, at vec.c:183
 > > 
 > > The same ICE also happens with today's trunk.
 > 
 > Please file it into bugzilla (and the other bug too), I'll have a look.
 > 
 > 	Jakub

Done, they are PR51510 and PR51511.
diff mbox

Patch

--- gcc/sched-deps.c	(revision 181855)
+++ gcc/sched-deps.c	(revision 181856)
@@ -2873,7 +2873,11 @@  sched_analyze_insn (struct deps_desc *de
 	  else
 	    sched_analyze_2 (deps, XEXP (link, 0), insn);
 	}
-      if (find_reg_note (insn, REG_SETJMP, NULL))
+      /* Don't schedule anything after a tail call, tail call needs
+	 to use at least all call-saved registers.  */
+      if (SIBLING_CALL_P (insn))
+	reg_pending_barrier = TRUE_BARRIER;
+      else if (find_reg_note (insn, REG_SETJMP, NULL))
 	reg_pending_barrier = MOVE_BARRIER;
     }
 
--- gcc/testsuite/gcc.target/i386/pr48721.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr48721.c	(revision 181856)
@@ -0,0 +1,51 @@ 
+/* PR rtl-optimization/48721 */
+/* { dg-do compile } */
+/* { dg-options "-O -foptimize-sibling-calls -fsched2-use-superblocks -fschedule-insns2 -mtune=core2" } */
+
+extern unsigned char a[];
+extern int b[], d[], e[], f[], g[], *h[], m[], *n[], o[];
+extern char c[];
+
+struct S
+{
+  unsigned char s1;
+  int s2, s3, s4, s5, s6, s7, s8;
+};
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  return 0;
+}
+
+int
+bar (int x, struct S *y)
+{
+  int z;
+  switch (x)
+    {
+    case 1:
+    case 2:
+      {
+	int t2, t4, t5, t6, t7, t8;
+	z = o[y->s8 * 6];
+	t8 = *n[m[x] * 5];
+	t4 = *h[y->s7];
+	t7 = z;
+	z = g[f[x] + y->s6];
+	t6 = e[y->s5];
+	t5 = d[c[x] + y->s3 * 17];
+	if (z)
+	  t2 = b[z];
+	if (a[z] != y->s1)
+	  return foo (x);
+	y->s8 = t8;
+	y->s4 = t4;
+	y->s7 = t7;
+	y->s6 = t6;
+	y->s5 = t5;
+	y->s2 = t2;
+      }
+    }
+  return 0;
+}