Backported 15 patches to 4.6 branch

Jakub Jelinek jakub@redhat.com
Thu Feb 9 17:43:00 GMT 2012


Hi!

I've backported these patches from trunk to 4.6 branch,
bootstrapped/regtested them on x86_64-linux and i686-linux
and committed.  Sorry for the delay.

	Jakub
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2011-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR debug/51517
	* tree-ssa-coalesce.c (coalesce_ssa_name): For !optimize, test
	!DECL_IGNORED_P instead of !DECL_ARTIFICIAL.

	* trans-decl.c (gfc_get_symbol_decl): Don't set DECL_INITAL on span.
	(gfc_trans_deferred_vars): Instead add its runtime initialization
	here.

--- gcc/tree-ssa-coalesce.c	(revision 182361)
+++ gcc/tree-ssa-coalesce.c	(revision 182362)
@@ -1373,7 +1373,7 @@ coalesce_ssa_name (void)
 
 	  if (a
 	      && SSA_NAME_VAR (a)
-	      && !DECL_ARTIFICIAL (SSA_NAME_VAR (a))
+	      && !DECL_IGNORED_P (SSA_NAME_VAR (a))
 	      && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a)))
 	    {
 	      tree *slot = (tree *) htab_find_slot (ssa_name_hash, a, INSERT);
--- gcc/fortran/trans-decl.c	(revision 182361)
+++ gcc/fortran/trans-decl.c	(revision 182362)
@@ -1352,7 +1352,6 @@ gfc_get_symbol_decl (gfc_symbol * sym)
       gfc_finish_var_decl (span, sym);
       TREE_STATIC (span) = TREE_STATIC (decl);
       DECL_ARTIFICIAL (span) = 1;
-      DECL_INITIAL (span) = build_int_cst (gfc_array_index_type, 0);
 
       GFC_DECL_SPAN (decl) = span;
       GFC_TYPE_ARRAY_SPAN (TREE_TYPE (decl)) = span;
@@ -3394,6 +3393,17 @@ gfc_trans_deferred_vars (gfc_symbol * pr
       if (sym->assoc)
 	continue;
 
+      if (sym->attr.subref_array_pointer
+	  && GFC_DECL_SPAN (sym->backend_decl)
+	  && !TREE_STATIC (GFC_DECL_SPAN (sym->backend_decl)))
+	{
+	  gfc_init_block (&tmpblock);
+	  gfc_add_modify (&tmpblock, GFC_DECL_SPAN (sym->backend_decl),
+			  build_int_cst (gfc_array_index_type, 0));
+	  gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock),
+				NULL_TREE);
+	}
+
       if (sym->attr.dimension)
 	{
           /* Assumed-size Cray pointees need to be treated as AS_EXPLICIT.  */
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2011-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR c/51360
	* c-parser.c (c_parser_omp_clause_num_threads,
	c_parser_omp_clause_schedule): Call mark_exp_read.

	* semantics.c (finish_omp_clauses): For OMP_CLAUSE_NUM_THREADS_EXPR
	and OMP_CLAUSE_SCHEDULE_CHUNK_EXPR call mark_rvalue_use.

	* gcc.dg/gomp/pr51360.c: New test.
	* g++.dg/gomp/pr51360.C: New test.
	* g++.dg/gomp/pr51360-2.C: New test.

--- gcc/cp/semantics.c	(revision 182380)
+++ gcc/cp/semantics.c	(revision 182381)
@@ -4087,6 +4087,8 @@ finish_omp_clauses (tree clauses)
 	      error ("num_threads expression must be integral");
 	      remove = true;
 	    }
+	  else
+	    OMP_CLAUSE_NUM_THREADS_EXPR (c) = mark_rvalue_use (t);
 	  break;
 
 	case OMP_CLAUSE_SCHEDULE:
@@ -4101,6 +4103,8 @@ finish_omp_clauses (tree clauses)
 	      error ("schedule chunk size expression must be integral");
 	      remove = true;
 	    }
+	  else
+	    OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = mark_rvalue_use (t);
 	  break;
 
 	case OMP_CLAUSE_NOWAIT:
--- gcc/c-parser.c	(revision 182380)
+++ gcc/c-parser.c	(revision 182381)
@@ -9011,6 +9011,7 @@ c_parser_omp_clause_num_threads (c_parse
     {
       location_t expr_loc = c_parser_peek_token (parser)->location;
       tree c, t = c_parser_expression (parser).value;
+      mark_exp_read (t);
       t = c_fully_fold (t, false, NULL);
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -9218,6 +9219,7 @@ c_parser_omp_clause_schedule (c_parser *
 
       here = c_parser_peek_token (parser)->location;
       t = c_parser_expr_no_commas (parser, NULL).value;
+      mark_exp_read (t);
       t = c_fully_fold (t, false, NULL);
 
       if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
--- gcc/testsuite/g++.dg/gomp/pr51360.C	(revision 0)
+++ gcc/testsuite/g++.dg/gomp/pr51360.C	(revision 182381)
@@ -0,0 +1,28 @@
+// PR c/51360
+// { dg-do compile }
+// { dg-options "-Wunused -W -fopenmp" }
+
+template <typename T>
+void
+foo (T a, T b, T c)
+{
+  T m, n, o, i;
+  m = 6;
+  n = 1;
+  o = 5;
+  a = 6;
+  b = 1;
+  c = 5;
+  #pragma omp parallel for num_threads (m) if (n) schedule (static, o)
+  for (i = 0; i < 10; i++)
+    ;
+  #pragma omp parallel for num_threads (a) if (b) schedule (static, c)
+  for (i = 0; i < 10; i++)
+    ;
+}
+
+void
+bar ()
+{
+  foo (0, 0, 0);
+}
--- gcc/testsuite/gcc.dg/gomp/pr51360.c	(revision 0)
+++ gcc/testsuite/gcc.dg/gomp/pr51360.c	(revision 182381)
@@ -0,0 +1,21 @@
+/* PR c/51360 */
+/* { dg-do compile } */
+/* { dg-options "-Wunused -W -fopenmp" } */
+
+void
+foo (int a, int b, int c)
+{
+  int m, n, o, i;
+  m = 6;
+  n = 1;
+  o = 5;
+  a = 6;
+  b = 1;
+  c = 5;
+  #pragma omp parallel for num_threads (m) if (n) schedule (static, o)
+  for (i = 0; i < 10; i++)
+    ;
+  #pragma omp parallel for num_threads (a) if (b) schedule (static, c)
+  for (i = 0; i < 10; i++)
+    ;
+}
--- gcc/testsuite/g++.dg/gomp/pr51360-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/gomp/pr51360-2.C	(revision 182381)
@@ -0,0 +1,21 @@
+/* PR c/51360 */
+/* { dg-do compile } */
+/* { dg-options "-Wunused -W -fopenmp" } */
+
+void
+foo (int a, int b, int c)
+{
+  int m, n, o, i;
+  m = 6;
+  n = 1;
+  o = 5;
+  a = 6;
+  b = 1;
+  c = 5;
+  #pragma omp parallel for num_threads (m) if (n) schedule (static, o)
+  for (i = 0; i < 10; i++)
+    ;
+  #pragma omp parallel for num_threads (a) if (b) schedule (static, c)
+  for (i = 0; i < 10; i++)
+    ;
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-26  Jakub Jelinek  <jakub@redhat.com>

	* make-relative-prefix.c (make_relative_prefix_1): Avoid warning
	about using preprocessor directives inside of macro arguments.

	2012-01-02  Jakub Jelinek  <jakub@redhat.com>

	* make-relative-prefix.c (make_relative_prefix_1): Avoid
	stack overflow if PATH contains just a single entry and
	HOST_EXECUTABLE_SUFFIX needs to be used.

	PR driver/48306
	* make-relative-prefix.c: Include sys/stat.h.
	(make_relative_prefix_1): If access succeeds, check also stat
	if nstore is a regular file.

--- libiberty/make-relative-prefix.c	(revision 182819)
+++ libiberty/make-relative-prefix.c	(revision 183561)
@@ -58,6 +58,9 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
 
 #include <string.h>
 
@@ -245,10 +248,15 @@
 	{
 	  char *startp, *endp, *nstore;
 	  size_t prefixlen = strlen (temp) + 1;
+	  size_t len;
 	  if (prefixlen < 2)
 	    prefixlen = 2;
 
-	  nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
+	  len = prefixlen + strlen (progname) + 1;
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+	  len += strlen (HOST_EXECUTABLE_SUFFIX);
+#endif
+	  nstore = (char *) alloca (len);
 
 	  startp = endp = temp;
 	  while (1)
@@ -263,7 +271,7 @@
 		    }
 		  else
 		    {
-		      strncpy (nstore, startp, endp - startp);
+		      memcpy (nstore, startp, endp - startp);
 		      if (! IS_DIR_SEPARATOR (endp[-1]))
 			{
 			  nstore[endp - startp] = DIR_SEPARATOR;
@@ -279,8 +287,14 @@
 #endif
 		      )
 		    {
-		      progname = nstore;
-		      break;
+#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
+		      struct stat st;
+		      if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
+#endif
+			{
+			  progname = nstore;
+			  break;
+			}
 		    }
 
 		  if (*endp == 0)
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-03  Jakub Jelinek  <jakub@redhat.com>

	PR c++/51669
	* semantics.c (finish_omp_clauses): Call fold_build_cleanup_point_expr
	on OMP_CLAUSE_{IF,NUM_THREADS,SCHEDULE_CHUNK}_EXPR.

	* g++.dg/gomp/pr51669.C: New test.

--- gcc/cp/semantics.c	(revision 182827)
+++ gcc/cp/semantics.c	(revision 182828)
@@ -3804,6 +3804,8 @@ finish_omp_clauses (tree clauses)
 	  t = maybe_convert_cond (t);
 	  if (t == error_mark_node)
 	    remove = true;
+	  else if (!processing_template_decl)
+	    t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
 	  OMP_CLAUSE_IF_EXPR (c) = t;
 	  break;
 
@@ -3818,7 +3820,12 @@ finish_omp_clauses (tree clauses)
 	      remove = true;
 	    }
 	  else
-	    OMP_CLAUSE_NUM_THREADS_EXPR (c) = mark_rvalue_use (t);
+	    {
+	      t = mark_rvalue_use (t);
+	      if (!processing_template_decl)
+		t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+	      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+	    }
 	  break;
 
 	case OMP_CLAUSE_SCHEDULE:
@@ -3834,7 +3841,12 @@ finish_omp_clauses (tree clauses)
 	      remove = true;
 	    }
 	  else
-	    OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = mark_rvalue_use (t);
+	    {
+	      t = mark_rvalue_use (t);
+	      if (!processing_template_decl)
+		t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+	      OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+	    }
 	  break;
 
 	case OMP_CLAUSE_NOWAIT:
--- gcc/testsuite/g++.dg/gomp/pr51669.C	(revision 0)
+++ gcc/testsuite/g++.dg/gomp/pr51669.C	(revision 182828)
@@ -0,0 +1,32 @@
+// PR c++/51669
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+template <typename T> const T & min (const T &, const T &);
+
+void
+f1 ()
+{
+#pragma omp parallel num_threads (min (4, 5))
+  ;
+}
+
+struct A { A (); ~A (); };
+int foo (const A &);
+
+void
+f2 ()
+{
+  int i;
+#pragma omp parallel if (foo (A ())) num_threads (foo (A ()))
+  ;
+#pragma omp task if (foo (A ()))
+  ;
+#pragma omp for schedule (static, foo (A ()))
+  for (i = 0; i < 10; i++)
+    ;
+#pragma omp parallel for schedule (static, foo (A ())) \
+  if (foo (A ())) num_threads (foo (A ()))
+  for (i = 0; i < 10; i++)
+    ;
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-04  Jakub Jelinek  <jakub@redhat.com>

	PR debug/51695
	* dwarf2out.c (output_loc_list): For now drop >= 64KB expressions
	in .debug_loc on the floor.

	* gcc.dg/pr51695.c: New test.

--- gcc/dwarf2out.c	(revision 182885)
+++ gcc/dwarf2out.c	(revision 182886)
@@ -11164,6 +11164,13 @@ output_loc_list (dw_loc_list_ref list_he
       /* Don't output an entry that starts and ends at the same address.  */
       if (strcmp (curr->begin, curr->end) == 0)
 	continue;
+      size = size_of_locs (curr->expr);
+      /* If the expression is too large, drop it on the floor.  We could
+	 perhaps put it into DW_TAG_dwarf_procedure and refer to that
+	 in the expression, but >= 64KB expressions for a single value
+	 in a single range are unlikely very useful.  */
+      if (size > 0xffff)
+	continue;
       if (!have_multiple_function_sections)
 	{
 	  dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
@@ -11182,7 +11189,6 @@ output_loc_list (dw_loc_list_ref list_he
 			       "Location list end address (%s)",
 			       list_head->ll_symbol);
 	}
-      size = size_of_locs (curr->expr);
 
       /* Output the block length for this list of location operations.  */
       gcc_assert (size <= 0xffff);
--- gcc/testsuite/gcc.dg/pr51695.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr51695.c	(revision 182886)
@@ -0,0 +1,52 @@
+/* PR debug/51695 */
+/* { dg-do compile { target { int32plus } } } */
+/* { dg-options "-O2 -g" } */
+
+typedef struct
+{
+  struct { unsigned int t1, t2, t3, t4, t5, t6; } t;
+  int p;
+  struct { double X, Y, Z; } r;
+} T;
+typedef struct { T *h; } S;
+
+static unsigned int v = 0x12345678;
+
+int
+foo (void)
+{
+  v = (v & 0x80000000) ? ((v << 1) ^ 0xa398655d) : (v << 1);
+  return 0;
+}
+
+double
+bar (void)
+{
+  unsigned int o;
+  v = (v & 0x80000000) ? ((v << 1) ^ 0xa398655d) : (v << 1);
+  o = v & 0xffff;
+  return (double) o / 32768.0;
+}
+
+int
+baz (void)
+{
+  foo ();
+  return 0;
+}
+
+void
+test (S *x)
+{
+  T *t = x->h;
+  t->t.t1 = foo ();
+  t->t.t2 = foo ();
+  t->t.t3 = foo ();
+  t->t.t4 = foo ();
+  t->t.t5 = foo ();
+  t->t.t6 = foo ();
+  t->p = baz ();
+  t->r.X = bar ();
+  t->r.Y = bar ();
+  t->r.Z = bar ();
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-05  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/44777
	* profile.c (branch_prob): Split bbs that have exit edge
	and need a fake entry edge too.

	* gcc.dg/tree-prof/pr44777.c: New test.

--- gcc/profile.c	(revision 182919)
+++ gcc/profile.c	(revision 182920)
@@ -1040,6 +1040,41 @@ branch_prob (void)
 	    fprintf (dump_file, "Adding fake entry edge to bb %i\n",
 		     bb->index);
 	  make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
+	  /* Avoid bbs that have both fake entry edge and also some
+	     exit edge.  One of those edges wouldn't be added to the
+	     spanning tree, but we can't instrument any of them.  */
+	  if (have_exit_edge || need_exit_edge)
+	    {
+	      gimple_stmt_iterator gsi;
+	      gimple first;
+	      tree fndecl;
+
+	      gsi = gsi_after_labels (bb);
+	      gcc_checking_assert (!gsi_end_p (gsi));
+	      first = gsi_stmt (gsi);
+	      if (is_gimple_debug (first))
+		{
+		  gsi_next_nondebug (&gsi);
+		  gcc_checking_assert (!gsi_end_p (gsi));
+		  first = gsi_stmt (gsi);
+		}
+	      /* Don't split the bbs containing __builtin_setjmp_receiver
+		 or __builtin_setjmp_dispatcher calls.  These are very
+		 special and don't expect anything to be inserted before
+		 them.  */
+	      if (!is_gimple_call (first)
+		  || (fndecl = gimple_call_fndecl (first)) == NULL
+		  || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL
+		  || (DECL_FUNCTION_CODE (fndecl) != BUILT_IN_SETJMP_RECEIVER
+		      && (DECL_FUNCTION_CODE (fndecl)
+			  != BUILT_IN_SETJMP_DISPATCHER)))
+		{
+		  if (dump_file)
+		    fprintf (dump_file, "Splitting bb %i after labels\n",
+			     bb->index);
+		  split_block_after_labels (bb);
+		}
+	    }
 	}
     }
 
--- gcc/testsuite/gcc.dg/tree-prof/pr44777.c	(revision 0)
+++ gcc/testsuite/gcc.dg/tree-prof/pr44777.c	(revision 182920)
@@ -0,0 +1,43 @@
+/* PR middle-end/44777 */
+/* { dg-options "-O0" } */
+/* A variant of gcc.c-torture/execute/comp-goto-2.c.  */
+
+extern void abort (void);
+extern void exit (int);
+
+#ifdef STACK_SIZE
+#define DEPTH ((STACK_SIZE) / 512 + 1)
+#else
+#define DEPTH 1000
+#endif
+
+#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES)
+int
+x (int a)
+{
+  __label__ xlab;
+  void y (int a)
+    {
+      void *x = &&llab;
+      if (a==-1)
+	goto *x;
+      if (a==0)
+	goto xlab;
+    llab:
+      y (a-1);
+    }
+  y (a);
+ xlab:;
+  return a;
+}
+#endif
+
+int
+main ()
+{
+#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES)
+  if (x (DEPTH) != DEPTH)
+    abort ();
+#endif
+  exit (0);
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-05  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/51768
	* stmt.c (check_unique_operand_names): Don't ICE during error
	reporting if i is from labels chain.

	* c-c++-common/pr51768.c: New test.

--- gcc/stmt.c	(revision 182920)
+++ gcc/stmt.c	(revision 182921)
@@ -1253,11 +1253,11 @@ check_operand_nalternatives (tree output
 static bool
 check_unique_operand_names (tree outputs, tree inputs, tree labels)
 {
-  tree i, j;
+  tree i, j, i_name = NULL_TREE;
 
   for (i = outputs; i ; i = TREE_CHAIN (i))
     {
-      tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
+      i_name = TREE_PURPOSE (TREE_PURPOSE (i));
       if (! i_name)
 	continue;
 
@@ -1268,7 +1268,7 @@ check_unique_operand_names (tree outputs
 
   for (i = inputs; i ; i = TREE_CHAIN (i))
     {
-      tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
+      i_name = TREE_PURPOSE (TREE_PURPOSE (i));
       if (! i_name)
 	continue;
 
@@ -1282,7 +1282,7 @@ check_unique_operand_names (tree outputs
 
   for (i = labels; i ; i = TREE_CHAIN (i))
     {
-      tree i_name = TREE_PURPOSE (i);
+      i_name = TREE_PURPOSE (i);
       if (! i_name)
 	continue;
 
@@ -1297,8 +1297,7 @@ check_unique_operand_names (tree outputs
   return true;
 
  failure:
-  error ("duplicate asm operand name %qs",
-	 TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
+  error ("duplicate asm operand name %qs", TREE_STRING_POINTER (i_name));
   return false;
 }
 
--- gcc/testsuite/c-c++-common/pr51768.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pr51768.c	(revision 182921)
@@ -0,0 +1,25 @@
+/* PR middle-end/51768 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo (void)
+{
+  asm goto ("" : : : : lab, lab, lab2, lab);	/* { dg-error "duplicate asm operand name" } */
+lab:;
+lab2:;
+}
+
+void
+bar (void)
+{
+  asm goto ("" : : [lab] "i" (0) : : lab);	/* { dg-error "duplicate asm operand name" } */
+lab:;
+}
+
+void
+baz (void)
+{
+  int x;
+  asm ("" : [lab] "=r" (x) : [lab] "r" (x));	/* { dg-error "duplicate asm operand name" } */
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-05  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/51767
	* cfgrtl.c (force_nonfallthru_and_redirect): Force addition
	of jump_block and add an extra edge for degenerated asm gotos.

	* gcc.c-torture/compile/pr51767.c: New test.

--- gcc/cfgrtl.c	(revision 182921)
+++ gcc/cfgrtl.c	(revision 182922)
@@ -1129,6 +1129,7 @@ force_nonfallthru_and_redirect (edge e, 
   rtx note;
   edge new_edge;
   int abnormal_edge_flags = 0;
+  bool asm_goto_edge = false;
   int loc;
 
   /* In the case the last instruction is conditional jump to the next
@@ -1208,8 +1209,28 @@ force_nonfallthru_and_redirect (edge e, 
 	}
     }
 
-  if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags)
+  /* If e->src ends with asm goto, see if any of the ASM_OPERANDS_LABELs
+     don't point to target label.  */
+  if (JUMP_P (BB_END (e->src))
+      && target != EXIT_BLOCK_PTR
+      && e->dest == target
+      && (e->flags & EDGE_FALLTHRU)
+      && (note = extract_asm_operands (PATTERN (BB_END (e->src)))))
     {
+      int i, n = ASM_OPERANDS_LABEL_LENGTH (note);
+
+      for (i = 0; i < n; ++i)
+	if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (target))
+	  {
+	    asm_goto_edge = true;
+	    break;
+	  }
+    }
+
+  if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge)
+    {
+      gcov_type count = e->count;
+      int probability = e->probability;
       /* Create the new structures.  */
 
       /* If the old block ended with a tablejump, skip its table
@@ -1220,7 +1241,7 @@ force_nonfallthru_and_redirect (edge e, 
       note = NEXT_INSN (note);
 
       jump_block = create_basic_block (note, NULL, e->src);
-      jump_block->count = e->count;
+      jump_block->count = count;
       jump_block->frequency = EDGE_FREQUENCY (e);
       jump_block->loop_depth = target->loop_depth;
 
@@ -1236,13 +1257,27 @@ force_nonfallthru_and_redirect (edge e, 
 
       /* Wire edge in.  */
       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
-      new_edge->probability = e->probability;
-      new_edge->count = e->count;
+      new_edge->probability = probability;
+      new_edge->count = count;
 
       /* Redirect old edge.  */
       redirect_edge_pred (e, jump_block);
       e->probability = REG_BR_PROB_BASE;
 
+      /* If asm goto has any label refs to target's label,
+	 add also edge from asm goto bb to target.  */
+      if (asm_goto_edge)
+	{
+	  new_edge->probability /= 2;
+	  new_edge->count /= 2;
+	  jump_block->count /= 2;
+	  jump_block->frequency /= 2;
+	  new_edge = make_edge (new_edge->src, target,
+				e->flags & ~EDGE_FALLTHRU);
+	  new_edge->probability = probability - probability / 2;
+	  new_edge->count = count - count / 2;
+	}
+
       new_bb = jump_block;
     }
   else
--- gcc/testsuite/gcc.c-torture/compile/pr51767.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr51767.c	(revision 182922)
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/51767 */
+
+extern void fn1 (void), fn2 (void);
+
+static inline __attribute__((always_inline)) int
+foo (int *x, long y)
+{
+  asm goto ("" : : "r" (x), "r" (y) : "memory" : lab);
+  return 0;
+lab:
+  return 1;
+}
+
+void
+bar (int *x)
+{
+  if (foo (x, 23))
+    fn1 ();
+  else
+    fn2 ();
+
+  foo (x, 2);
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-19  Jakub Jelinek  <jakub@redhat.com>

	PR libmudflap/40778
	* tree-mudflap.c (mf_artificial): New function.
	(execute_mudflap_function_ops, execute_mudflap_function_decls,
	mx_register_decls, mudflap_enqueue_decl): Use it.

	* testsuite/libmudflap.c/fail68-frag.c: New test.

--- gcc/tree-mudflap.c	(revision 183306)
+++ gcc/tree-mudflap.c	(revision 183307)
@@ -69,6 +69,13 @@ static tree mx_xfn_xform_decls (gimple_s
 static gimple_seq mx_register_decls (tree, gimple_seq, location_t);
 static unsigned int execute_mudflap_function_decls (void);
 
+/* Return true if DECL is artificial stub that shouldn't be instrumented by
+   mf.  We should instrument clones of non-artificial functions.  */
+static inline bool
+mf_artificial (const_tree decl)
+{
+  return DECL_ARTIFICIAL (DECL_ORIGIN (decl));
+}
 
 /* ------------------------------------------------------------------------ */
 /* Some generally helpful functions for mudflap instrumentation.  */
@@ -412,8 +419,8 @@ execute_mudflap_function_ops (void)
 
   /* Don't instrument functions such as the synthetic constructor
      built during mudflap_finish_file.  */
-  if (mf_marked_p (current_function_decl) ||
-      DECL_ARTIFICIAL (current_function_decl))
+  if (mf_marked_p (current_function_decl)
+      || mf_artificial (current_function_decl))
     return 0;
 
   push_gimplify_context (&gctx);
@@ -994,8 +1001,8 @@ execute_mudflap_function_decls (void)
 
   /* Don't instrument functions such as the synthetic constructor
      built during mudflap_finish_file.  */
-  if (mf_marked_p (current_function_decl) ||
-      DECL_ARTIFICIAL (current_function_decl))
+  if (mf_marked_p (current_function_decl)
+      || mf_artificial (current_function_decl))
     return 0;
 
   push_gimplify_context (&gctx);
@@ -1078,7 +1085,7 @@ mx_register_decls (tree decl, gimple_seq
           /* Add the __mf_register call at the current appending point.  */
           if (gsi_end_p (initially_stmts))
 	    {
-	      if (!DECL_ARTIFICIAL (decl))
+	      if (!mf_artificial (decl))
 		warning (OPT_Wmudflap,
 			 "mudflap cannot track %qE in stub function",
 			 DECL_NAME (decl));
@@ -1249,7 +1256,7 @@ mudflap_enqueue_decl (tree obj)
      during mudflap_finish_file ().  That would confuse the user,
      since the text would refer to variables that don't show up in the
      user's source code.  */
-  if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
+  if (DECL_P (obj) && DECL_EXTERNAL (obj) && mf_artificial (obj))
     return;
 
   VEC_safe_push (tree, gc, deferred_static_decls, obj);
--- libmudflap/testsuite/libmudflap.c/fail68-frag.c	(revision 0)
+++ libmudflap/testsuite/libmudflap.c/fail68-frag.c	(revision 183307)
@@ -0,0 +1,27 @@
+/* PR libmudflap/40778 */
+
+char p[32];
+static int j;
+
+__attribute__((noinline))
+static void foo (int i)
+{
+  if (j++ == 0)
+    p[i + 4] = 12;
+  else
+    p[i - 4] = 13;
+}
+
+int
+main ()
+{
+  foo (30);
+  foo (30);
+  foo (30);
+  return 0;
+}
+
+/* { dg-output "mudflap violation 1.*" } */
+/* { dg-output "Nearby object 1.*" } */
+/* { dg-output "mudflap object.*name.*p" } */
+/* { dg-do run { xfail *-*-* } } */
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-01-28  Jakub Jelinek  <jakub@redhat.com>

	PR target/52006
	* config/arm/arm.md (pic_add_dot_plus_eight peephole2): Use
	arm_general_register_operand predicate for operand 2 instead of
	register_operand.

	* gcc.target/arm/pr52006.c: New test.

--- gcc/config/arm/arm.md	(revision 183660)
+++ gcc/config/arm/arm.md	(revision 183661)
@@ -5719,7 +5719,8 @@ (define_peephole2
 		    (const_int 8)
 		    (match_operand 1 "" "")]
 		   UNSPEC_PIC_BASE))
-   (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
+   (set (match_operand:SI 2 "arm_general_register_operand" "")
+	(mem:SI (match_dup 0)))]
   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
   [(set (match_dup 2)
 	(mem:SI (unspec:SI [(match_dup 3)
--- gcc/testsuite/gcc.target/arm/pr52006.c	(revision 0)
+++ gcc/testsuite/gcc.target/arm/pr52006.c	(revision 183661)
@@ -0,0 +1,19 @@
+/* PR target/52006 */
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mfloat-abi=hard -O2 -fPIC" } */
+
+unsigned long a;
+static int b;
+
+void
+foo (void)
+{
+  asm volatile ("" : "=r" (b));
+}
+
+void
+bar (float f)
+{
+  if (f < b / 100.0)
+    a = 1;
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-02-02  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/48071
	* diagnostic.c (diagnostic_finish): Remove trailing newlines.

--- gcc/diagnostic.c	(revision 183846)
+++ gcc/diagnostic.c	(revision 183847)
@@ -133,12 +133,12 @@ diagnostic_finish (diagnostic_context *c
       /* -Werror was given.  */
       if (context->warning_as_error_requested)
 	pp_verbatim (context->printer,
-		     _("%s: all warnings being treated as errors\n"),
+		     _("%s: all warnings being treated as errors"),
 		     progname);
       /* At least one -Werror= was given.  */
       else
 	pp_verbatim (context->printer,
-		     _("%s: some warnings being treated as errors\n"),
+		     _("%s: some warnings being treated as errors"),
 		     progname);
       pp_flush (context->printer);
     }
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-02-06  Jakub Jelinek  <jakub@redhat.com>

	PR target/52129
	* calls.c (mem_overlaps_already_clobbered_arg_p): If val is
	CONST_INT_P, subtract resp. add crtl->args.pretend_args_size to it.

	* gcc.c-torture/execute/pr52129.c: New test.

--- gcc/calls.c	(revision 183932)
+++ gcc/calls.c	(revision 183933)
@@ -1808,6 +1808,11 @@ mem_overlaps_already_clobbered_arg_p (rt
     return true;
   else
     i = INTVAL (val);
+#ifdef STACK_GROWS_DOWNWARD
+  i -= crtl->args.pretend_args_size;
+#else
+  i += crtl->args.pretend_args_size;
+#endif
 
 #ifdef ARGS_GROW_DOWNWARD
   i = -i - size;
--- gcc/testsuite/gcc.c-torture/execute/pr52129.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr52129.c	(revision 183933)
@@ -0,0 +1,28 @@
+/* PR target/52129 */
+
+extern void abort (void);
+struct S { void *p; unsigned int q; };
+struct T { char a[64]; char b[64]; } t;
+
+__attribute__((noinline, noclone)) int
+foo (void *x, struct S s, void *y, void *z)
+{
+  if (x != &t.a[2] || s.p != &t.b[5] || s.q != 27 || y != &t.a[17] || z != &t.b[17])
+    abort ();
+  return 29;
+}
+
+__attribute__((noinline, noclone)) int
+bar (void *x, void *y, void *z, struct S s, int t, struct T *u)
+{
+  return foo (x, s, &u->a[t], &u->b[t]);
+}
+
+int
+main ()
+{
+  struct S s = { &t.b[5], 27 };
+  if (bar (&t.a[2], (void *) 0, (void *) 0, s, 17, &t) != 29)
+    abort ();
+  return 0;
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-02-07  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/52074
	* expr.c (expand_expr_addr_expr_1): For CONSTANT_CLASS_P or CONST_DECL
	if modifier < EXPAND_SUM call force_operand on the result.

	* gcc.c-torture/compile/pr52074.c: New test.

--- gcc/expr.c	(revision 183955)
+++ gcc/expr.c	(revision 183956)
@@ -7414,7 +7414,12 @@ expand_expr_addr_expr_1 (tree exp, rtx t
      generating ADDR_EXPR of something that isn't an LVALUE.  The only
      exception here is STRING_CST.  */
   if (CONSTANT_CLASS_P (exp))
-    return XEXP (expand_expr_constant (exp, 0, modifier), 0);
+    {
+      result = XEXP (expand_expr_constant (exp, 0, modifier), 0);
+      if (modifier < EXPAND_SUM)
+	result = force_operand (result, target);
+      return result;
+    }
 
   /* Everything must be something allowed by is_gimple_addressable.  */
   switch (TREE_CODE (exp))
@@ -7433,7 +7438,11 @@ expand_expr_addr_expr_1 (tree exp, rtx t
 
     case CONST_DECL:
       /* Expand the initializer like constants above.  */
-      return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
+      result = XEXP (expand_expr_constant (DECL_INITIAL (exp),
+					   0, modifier), 0);
+      if (modifier < EXPAND_SUM)
+	result = force_operand (result, target);
+      return result;
 
     case REALPART_EXPR:
       /* The real part of the complex number is always first, therefore
--- gcc/testsuite/gcc.c-torture/compile/pr52074.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr52074.c	(revision 183956)
@@ -0,0 +1,10 @@
+/* PR middle-end/52074 */
+
+struct S { const char *d, *e; } __attribute__((packed));
+
+void
+foo (const char **p, struct S *q)
+{
+  *p = "abcdef";
+  q->d = "ghijk";
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-02-07  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/52060
	* combine.c (try_combine): Add i0src_copy and i0src_copy2 variables,
	copy i1src to i1src_copy whenever added_sets_2 && i1_feeds_i2_n already
	before i1dest -> i1src substitution in newpat, copy i0src to i0src_copy
	and/or i0src_copy2 when needed.

	* gcc.dg/torture/pr52060.c: New test.

--- gcc/combine.c	(revision 183971)
+++ gcc/combine.c	(revision 183972)
@@ -2558,8 +2558,8 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
   rtx i3dest_killed = 0;
   /* SET_DEST and SET_SRC of I2, I1 and I0.  */
   rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0;
-  /* Copy of SET_SRC of I1, if needed.  */
-  rtx i1src_copy = 0;
+  /* Copy of SET_SRC of I1 and I0, if needed.  */
+  rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0;
   /* Set if I2DEST was reused as a scratch register.  */
   bool i2scratch = false;
   /* The PATTERNs of I0, I1, and I2, or a copy of them in certain cases.  */
@@ -3171,6 +3171,11 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
       n_occurrences = 0;
       subst_low_luid = DF_INSN_LUID (i1);
 
+      /* If the following substitution will modify I1SRC, make a copy of it
+	 for the case where it is substituted for I1DEST in I2PAT later.  */
+      if (added_sets_2 && i1_feeds_i2_n)
+	i1src_copy = copy_rtx (i1src);
+
       /* If I0 feeds into I1 and I0DEST is in I0SRC, we need to make a unique
 	 copy of I1SRC each time we substitute it, in order to avoid creating
 	 self-referential RTL when we will be substituting I0SRC for I0DEST
@@ -3198,10 +3203,14 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
 	  return 0;
 	}
 
-      /* If the following substitution will modify I1SRC, make a copy of it
-	 for the case where it is substituted for I1DEST in I2PAT later.  */
-      if (i0_feeds_i1_n && added_sets_2 && i1_feeds_i2_n)
-	i1src_copy = copy_rtx (i1src);
+      /* If the following substitution will modify I0SRC, make a copy of it
+	 for the case where it is substituted for I0DEST in I1PAT later.  */
+      if (added_sets_1 && i0_feeds_i1_n)
+	i0src_copy = copy_rtx (i0src);
+      /* And a copy for I0DEST in I2PAT substitution.  */
+      if (added_sets_2 && ((i0_feeds_i1_n && i1_feeds_i2_n)
+			   || (i0_feeds_i2_n)))
+	i0src_copy2 = copy_rtx (i0src);
 
       n_occurrences = 0;
       subst_low_luid = DF_INSN_LUID (i0);
@@ -3267,7 +3276,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
 	{
 	  rtx t = i1pat;
 	  if (i0_feeds_i1_n)
-	    t = subst (t, i0dest, i0src, 0, 0);
+	    t = subst (t, i0dest, i0src_copy ? i0src_copy : i0src, 0, 0);
 
 	  XVECEXP (newpat, 0, --total_sets) = t;
 	}
@@ -3278,7 +3287,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
 	    t = subst (t, i1dest, i1src_copy ? i1src_copy : i1src, 0,
 		       i0_feeds_i1_n && i0dest_in_i0src);
 	  if ((i0_feeds_i1_n && i1_feeds_i2_n) || i0_feeds_i2_n)
-	    t = subst (t, i0dest, i0src, 0, 0);
+	    t = subst (t, i0dest, i0src_copy2 ? i0src_copy2 : i0src, 0, 0);
 
 	  XVECEXP (newpat, 0, --total_sets) = t;
 	}
--- gcc/testsuite/gcc.dg/torture/pr52060.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr52060.c	(revision 183972)
@@ -0,0 +1,57 @@
+/* PR rtl-optimization/52060 */
+/* { dg-do run { target int32plus } } */
+
+extern void abort (void);
+union U { float f; unsigned int i; };
+
+static inline __attribute__((always_inline)) unsigned int
+foo (float x)
+{
+  union U u;
+  unsigned int a, b, c;
+  int d;
+  int e;
+  u.f = x;
+  d = ((unsigned) u.i >> 23) & 0xFF;
+  c = d < 126 ? 0 : ~0;
+  e = 127 + 30 - d;
+  a = (u.i << 8) | 0x80000000U;
+  b = a & ((1 << e) - 1);
+  a = a >> e;
+  c &= (b | (a & 2)) ? ~0 : ~1;
+  a = ((a + 1U) >> 1) & c;
+  return a;
+}
+
+__attribute__((noinline)) unsigned int
+bar (float x)
+{
+  unsigned int a, b, c;
+  static const unsigned int d[128] =
+  {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7
+  };
+  a = foo (1048575.0f * x);
+  c = d[a >> 13];
+  b = (c << 13) | ((a >> (7 - c)) & 0x1fff);
+  return b;
+}
+
+int
+main ()
+{
+  union U u;
+  u.f = 1048575.0f;
+  if (sizeof (u.i) == sizeof (u.f)
+      && u.i == 0x497ffff0U
+      && bar (1.0f) != 65535)
+    abort ();
+  return 0;
+}
-------------- next part --------------
2012-02-09  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2012-02-08  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/52139
	* cfgrtl.c (cfg_layout_merge_blocks): If BB_END
	is a BARRIER after emit_insn_after_noloc, move BB_END
	to the last non-BARRIER insn before it.

	* gcc.dg/pr52139.c: New test.

--- gcc/cfgrtl.c	(revision 184004)
+++ gcc/cfgrtl.c	(revision 184005)
@@ -2871,6 +2871,11 @@ cfg_layout_merge_blocks (basic_block a, 
       rtx first = BB_END (a), last;
 
       last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a), a);
+      /* The above might add a BARRIER as BB_END, but as barriers
+	 aren't valid parts of a bb, remove_insn doesn't update
+	 BB_END if it is a barrier.  So adjust BB_END here.  */
+      while (BB_END (a) != first && BARRIER_P (BB_END (a)))
+	BB_END (a) = PREV_INSN (BB_END (a));
       delete_insn_chain (NEXT_INSN (first), last, false);
       b->il.rtl->header = NULL;
     }
--- gcc/testsuite/gcc.dg/pr52139.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr52139.c	(revision 184005)
@@ -0,0 +1,49 @@
+/* PR rtl-optimization/52139 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-dominator-opts -fno-tree-fre" } */
+/* { dg-options "-O -fno-tree-dominator-opts -fno-tree-fre -fpic" { target fpic } } */
+
+void *p;
+
+void
+foo (int a)
+{
+  switch (a)
+    {
+    case 0:
+    a0:
+    case 1:
+    a1:
+      p = &&a1;
+    case 2:
+    a2:
+      p = &&a2;
+    case 3:
+    a3:
+      p = &&a3;
+    case 4:
+    a4:
+      p = &&a4;
+    case 5:
+    a5:
+      p = &&a5;
+    case 6:
+    a6:
+      p = &&a6;
+    case 7:
+    a7:
+      p = &&a7;
+    case 8:
+    a8:
+      p = &&a8;
+    case 9:
+    a9:
+      p = &&a9;
+    case 10:
+    a10:
+      p = &&a10;
+    default:
+      p = &&a0;
+    }
+  goto *p;
+}


More information about the Gcc-patches mailing list