Patchwork Backports from trunk to 4.5 branch

login
register
mail settings
Submitter Jakub Jelinek
Date Nov. 11, 2010, 8:44 p.m.
Message ID <20101111204418.GI29412@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/70879/
State New
Headers show

Comments

Jakub Jelinek - Nov. 11, 2010, 8:44 p.m.
Hi!

I've backported a bunch of recent patches of mine to 4.5 and committed
them after bootstrapping/regtesting them on x86_64-linux and i686-linux
(with yes,rtl checking).

	Jakub
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-05  Jakub Jelinek  <jakub@redhat.com>

	PR c++/46160
	* cp-gimplify.c (cp_gimplify_expr): Drop volatile INDIRECT_REFs
	on the RHS to avoid infinite recursion with gimplify_expr.

	* g++.dg/opt/empty2.C: New test.
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-05  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46099
	* tree-parloops.c (take_address_of): Add GSI argument.  Return NULL
	if it is NULL and uid wasn't found in the hash table.  Just fold the
	result if it is NULL otherwise.  Insert other potentially needed
	stmts right before current stmt instead of on the entry edge.
	(struct elv_data): Add gsi and reset fields.
	(eliminate_local_variables_1): Adjust caller.  If take_address_of
	failed for debug stmt, set dta->reset and return.
	(eliminate_local_variables_stmt): Change STMT argument for GSI,
	pass GSI through to the callback, handle resetting of debug stmts.
	(eliminate_local_variables): Adjust caller.  Process debug stmts
	in second phase.

	* gcc.dg/autopar/pr46099.c: New test.

--- gcc/tree-parloops.c	(revision 166354)
+++ gcc/tree-parloops.c	(revision 166355)
@@ -315,10 +315,12 @@ loop_has_blocks_with_irreducible_flag (s
 /* Assigns the address of OBJ in TYPE to an ssa name, and returns this name.
    The assignment statement is placed on edge ENTRY.  DECL_ADDRESS maps decls
    to their addresses that can be reused.  The address of OBJ is known to
-   be invariant in the whole function.  */
+   be invariant in the whole function.  Other needed statements are placed
+   right before GSI.  */
 
 static tree
-take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
+take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
+		 gimple_stmt_iterator *gsi)
 {
   int uid;
   void **dslot;
@@ -340,6 +342,8 @@ take_address_of (tree obj, tree type, ed
   dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT);
   if (!*dslot)
     {
+      if (gsi == NULL)
+	return NULL;
       addr = build_addr (*var_p, current_function_decl);
       bvar = create_tmp_var (TREE_TYPE (addr), get_name (*var_p));
       add_referenced_var (bvar);
@@ -356,13 +360,22 @@ take_address_of (tree obj, tree type, ed
   else
     name = ((struct int_tree_map *) *dslot)->to;
 
+  if (gsi == NULL)
+    {
+      if (var_p != &obj)
+	{
+	  *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
+	  name = build_fold_addr_expr_with_type (obj, type);
+	}
+      return fold_convert (type, name);
+    }
   if (var_p != &obj)
     {
       *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
       name = force_gimple_operand (build_addr (obj, current_function_decl),
 				   &stmts, true, NULL_TREE);
       if (!gimple_seq_empty_p (stmts))
-	gsi_insert_seq_on_edge_immediate (entry, stmts);
+	gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     }
 
   if (TREE_TYPE (name) != type)
@@ -370,7 +383,7 @@ take_address_of (tree obj, tree type, ed
       name = force_gimple_operand (fold_convert (type, name), &stmts, true,
 				   NULL_TREE);
       if (!gimple_seq_empty_p (stmts))
-	gsi_insert_seq_on_edge_immediate (entry, stmts);
+	gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     }
 
   return name;
@@ -432,7 +445,9 @@ struct elv_data
   struct walk_stmt_info info;
   edge entry;
   htab_t decl_address;
+  gimple_stmt_iterator *gsi;
   bool changed;
+  bool reset;
 };
 
 /* Eliminates references to local variables in *TP out of the single
@@ -456,7 +471,14 @@ eliminate_local_variables_1 (tree *tp, i
 
       type = TREE_TYPE (t);
       addr_type = build_pointer_type (type);
-      addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
+      addr = take_address_of (t, addr_type, dta->entry, dta->decl_address,
+			      dta->gsi);
+      if (dta->gsi == NULL && addr == NULL_TREE)
+	{
+	  dta->reset = true;
+	  return NULL_TREE;
+	}
+
       *tp = build1 (INDIRECT_REF, TREE_TYPE (*tp), addr);
 
       dta->changed = true;
@@ -486,7 +508,13 @@ eliminate_local_variables_1 (tree *tp, i
 	return NULL_TREE;
 
       addr_type = TREE_TYPE (t);
-      addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address);
+      addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address,
+			      dta->gsi);
+      if (dta->gsi == NULL && addr == NULL_TREE)
+	{
+	  dta->reset = true;
+	  return NULL_TREE;
+	}
       *tp = addr;
 
       dta->changed = true;
@@ -499,27 +527,40 @@ eliminate_local_variables_1 (tree *tp, i
   return NULL_TREE;
 }
 
-/* Moves the references to local variables in STMT out of the single
+/* Moves the references to local variables in STMT at *GSI out of the single
    entry single exit region starting at ENTRY.  DECL_ADDRESS contains
    addresses of the references that had their address taken
    already.  */
 
 static void
-eliminate_local_variables_stmt (edge entry, gimple stmt,
+eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
 				htab_t decl_address)
 {
   struct elv_data dta;
+  gimple stmt = gsi_stmt (*gsi);
 
   memset (&dta.info, '\0', sizeof (dta.info));
   dta.entry = entry;
   dta.decl_address = decl_address;
   dta.changed = false;
+  dta.reset = false;
 
   if (gimple_debug_bind_p (stmt))
-    walk_tree (gimple_debug_bind_get_value_ptr (stmt),
-	       eliminate_local_variables_1, &dta.info, NULL);
+    {
+      dta.gsi = NULL;
+      walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+		 eliminate_local_variables_1, &dta.info, NULL);
+      if (dta.reset)
+	{
+	  gimple_debug_bind_reset_value (stmt);
+	  dta.changed = true;
+	}
+    }
   else
-    walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+    {
+      dta.gsi = gsi;
+      walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+    }
 
   if (dta.changed)
     update_stmt (stmt);
@@ -543,6 +584,7 @@ eliminate_local_variables (edge entry, e
   VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
   unsigned i;
   gimple_stmt_iterator gsi;
+  bool has_debug_stmt = false;
   htab_t decl_address = htab_create (10, int_tree_map_hash, int_tree_map_eq,
 				     free);
   basic_block entry_bb = entry->src;
@@ -553,8 +595,17 @@ eliminate_local_variables (edge entry, e
   for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
     if (bb != entry_bb && bb != exit_bb)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-	eliminate_local_variables_stmt (entry, gsi_stmt (gsi),
-					decl_address);
+	if (gimple_debug_bind_p (gsi_stmt (gsi)))
+	  has_debug_stmt = true;
+	else
+	  eliminate_local_variables_stmt (entry, &gsi, decl_address);
+
+  if (has_debug_stmt)
+    for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+      if (bb != entry_bb && bb != exit_bb)
+	for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	  if (gimple_debug_bind_p (gsi_stmt (gsi)))
+	    eliminate_local_variables_stmt (entry, &gsi, decl_address);
 
   htab_delete (decl_address);
   VEC_free (basic_block, heap, body);
--- gcc/testsuite/gcc.dg/autopar/pr46099.c	(revision 0)
+++ gcc/testsuite/gcc.dg/autopar/pr46099.c	(revision 166355)
@@ -0,0 +1,47 @@
+/* PR tree-optimization/46099 */
+/* { dg-do compile } */
+/* { dg-options "-ftree-parallelize-loops=2 -fcompare-debug -O" } */
+
+static inline void
+bar (int *i)
+{
+  int j = *i;
+}
+
+void baz (int *, int *, int *);
+
+void
+f1 (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    bar (&i);
+}
+
+void
+f2 (int n)
+{
+  int i;
+  int a[10000], b[10000], c[10000];
+  baz (a, b, c);
+  for (i = 0; i < n; i++)
+    {
+      void *p = c;
+      a[i] = b[i] + c[i];
+    }
+  baz (a, b, c);
+}
+
+void
+f3 (int n)
+{
+  int i;
+  int a[10000], b[10000], c[10000];
+  baz (a, b, c);
+  for (i = 0; i < n; i++)
+    {
+      a[i] = b[i] + c[i];
+      void *p = c;
+    }
+  baz (a, b, c);
+}
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-03  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46165
	* tree-ssa-pre.c (eliminate): Return TODO_cleanup_cfg if changing
	a normal call into noreturn call.

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

--- gcc/tree-ssa-pre.c	(revision 166235)
+++ gcc/tree-ssa-pre.c	(revision 166236)
@@ -4311,6 +4311,8 @@ eliminate (void)
 	      && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
 	    {
 	      tree fn = VN_INFO (gimple_call_fn (stmt))->valnum;
+	      bool was_noreturn = gimple_call_noreturn_p (stmt);
+ 
 	      if (TREE_CODE (fn) == ADDR_EXPR
 		  && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
 		{
@@ -4324,6 +4326,12 @@ eliminate (void)
 
 		  gimple_call_set_fn (stmt, fn);
 		  update_stmt (stmt);
+
+		  /* When changing a call into a noreturn call, cfg cleanup
+		     is needed to fix up the noreturn call.  */
+		  if (!was_noreturn && gimple_call_noreturn_p (stmt))
+		    todo |= TODO_cleanup_cfg;
+
 		  if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
 		    {
 		      bitmap_set_bit (need_eh_cleanup,
--- gcc/testsuite/gcc.dg/pr46165.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr46165.c	(revision 166236)
@@ -0,0 +1,11 @@
+/* PR tree-optimization/46165 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-dce" } */
+
+extern void foo (void) __attribute__((noreturn));
+void
+g (void)
+{
+  void (*f) (void) = foo;
+  f ();
+}
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-03  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46107
	* cfgloopmanip.c (loop_version): Set irred_flag back into entry->flags
	if cfg_hook_duplicate_loop_to_header_edge failed.

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

--- gcc/cfgloopmanip.c	(revision 166233)
+++ gcc/cfgloopmanip.c	(revision 166234)
@@ -1538,7 +1538,10 @@ loop_version (struct loop *loop,
   /* Duplicate loop.  */
   if (!cfg_hook_duplicate_loop_to_header_edge (loop, entry, 1,
 					       NULL, NULL, NULL, 0))
-    return NULL;
+    {
+      entry->flags |= irred_flag;
+      return NULL;
+    }
 
   /* After duplication entry edge now points to new loop head block.
      Note down new head as second_head.  */
--- gcc/testsuite/gcc.c-torture/compile/pr46107.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr46107.c	(revision 166234)
@@ -0,0 +1,16 @@
+/* PR tree-optimization/46107 */
+
+int foo (void) __attribute__ ((noreturn));
+
+void
+bar (int x, int *y, int z)
+{
+  static void *j[] = { &&l1, &&l2 };
+l1:
+  if (*y)
+    goto *j[z];
+  foo ();
+l2:
+  *y ^= (x & 1) ? -1 : 0;
+  goto *j[x];
+}
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-09  Jakub Jelinek  <jakub@redhat.com>

	PR c++/45894
	* tree.c (lvalue_p_1): Don't crash if ref has NULL type.

	* g++.dg/warn/Wsequence-point-2.C: New test.

--- gcc/cp/tree.c	(revision 166480)
+++ gcc/cp/tree.c	(revision 166481)
@@ -72,7 +72,8 @@ lvalue_p_1 (const_tree ref)
 	  == REFERENCE_TYPE)
     return lvalue_p_1 (TREE_OPERAND (ref, 0));
 
-  if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
+  if (TREE_TYPE (ref)
+      && TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
     {
       /* unnamed rvalue references are rvalues */
       if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref))
--- gcc/testsuite/g++.dg/warn/Wsequence-point-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wsequence-point-2.C	(revision 166481)
@@ -0,0 +1,28 @@
+// PR c++/45894
+// { dg-do compile }
+// { dg-options "-std=c++0x -Wsequence-point" }
+
+struct F
+{
+  template <typename = int>
+  void bar ();
+};
+template <typename = int>
+struct V
+{
+  V (const V &) { F::bar <>; }
+};
+struct C
+{
+  V <> v;
+};
+struct B
+{
+  C f ();
+};
+struct A
+{
+  C c;
+  B b;
+  A () : c (b.f ()) { }
+};
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-05  Jakub Jelinek  <jakub@redhat.com>

	PR c/44772
	* c-decl.c (warn_cxx_compat_finish_struct): Don't call
	pointer_set_contains if DECL_NAME is NULL.

	* gcc.dg/Wcxx-compat-21.c: New test.

--- gcc/c-decl.c	(revision 166383)
+++ gcc/c-decl.c	(revision 166384)
@@ -6709,7 +6709,8 @@ warn_cxx_compat_finish_struct (tree fiel
 
       for (x = fieldlist; x != NULL_TREE; x = TREE_CHAIN (x))
 	{
-	  if (pointer_set_contains (tset, DECL_NAME (x)))
+	  if (DECL_NAME (x) != NULL_TREE
+	      && pointer_set_contains (tset, DECL_NAME (x)))
 	    {
 	      warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
 			  ("using %qD as both field and typedef name is "
--- gcc/testsuite/gcc.dg/Wcxx-compat-21.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wcxx-compat-21.c	(revision 166384)
@@ -0,0 +1,25 @@
+/* PR c/44772 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+typedef enum { E1, E2 } E;
+
+typedef struct
+{
+  E e;
+  union
+  {
+    int i;
+    char *c;
+  };			/* { dg-bogus "as both field and typedef name" } */
+} S;
+
+S s;
+
+typedef int T;
+
+struct U
+{
+  T t;
+  union { int i; };	/* { dg-bogus "as both field and typedef name" } */
+};
2010-11-11  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-11-05  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/43690
	* gimplify.c (gimplify_asm_expr): If a "m" input is a
	{pre,post}{in,de}crement, fail.

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

--- gcc/gimplify.c	(revision 166353)
+++ gcc/gimplify.c	(revision 166354)
@@ -5066,6 +5066,13 @@ gimplify_asm_expr (tree *expr_p, gimple_
       /* If the operand is a memory input, it should be an lvalue.  */
       if (!allows_reg && allows_mem)
 	{
+	  tree inputv = TREE_VALUE (link);
+	  STRIP_NOPS (inputv);
+	  if (TREE_CODE (inputv) == PREDECREMENT_EXPR
+	      || TREE_CODE (inputv) == PREINCREMENT_EXPR
+	      || TREE_CODE (inputv) == POSTDECREMENT_EXPR
+	      || TREE_CODE (inputv) == POSTINCREMENT_EXPR)
+	    TREE_VALUE (link) = error_mark_node;
 	  tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
 				is_gimple_lvalue, fb_lvalue | fb_mayfail);
 	  mark_addressable (TREE_VALUE (link));
--- gcc/testsuite/c-c++-common/pr43690.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pr43690.c	(revision 166354)
@@ -0,0 +1,13 @@
+/* PR middle-end/43690 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (char *x)
+{
+  asm ("" : : "m" (x++));	/* { dg-error "is not directly addressable" } */
+  asm ("" : : "m" (++x));	/* { dg-error "is not directly addressable" } */
+  asm ("" : : "m" (x--));	/* { dg-error "is not directly addressable" } */
+  asm ("" : : "m" (--x));	/* { dg-error "is not directly addressable" } */
+  asm ("" : : "m" (x + 1));	/* { dg-error "is not directly addressable" } */
+}

Patch

--- gcc/cp/cp-gimplify.c	(revision 166371)
+++ gcc/cp/cp-gimplify.c	(revision 166372)
@@ -590,6 +590,16 @@  cp_gimplify_expr (tree *expr_p, gimple_s
 	    if (!TREE_SIDE_EFFECTS (op1)
 		|| (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
 	      *expr_p = op0;
+	    else if (TREE_CODE (op1) == INDIRECT_REF
+		     && TREE_THIS_VOLATILE (op1))
+	      {
+		/* Similarly for volatile INDIRECT_REFs on the RHS.  */
+		if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
+		  *expr_p = op0;
+		else
+		  *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
+				    TREE_OPERAND (op1, 0), op0);
+	      }
 	    else
 	      *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
 				op0, op1);
--- gcc/testsuite/g++.dg/opt/empty2.C	(revision 0)
+++ gcc/testsuite/g++.dg/opt/empty2.C	(revision 166372)
@@ -0,0 +1,18 @@ 
+// PR c++/46160
+// { dg-do compile }
+
+struct S
+{
+  enum E { A };
+} s;
+volatile S t;
+
+void f (S::E);
+
+void
+g ()
+{
+  volatile S *p = &s;
+  f (p->A);
+  f (t.A);
+}