Backports to 7.3

Message ID 20171222085545.GI2353@tucnak
State New
Headers show
Series
  • Backports to 7.3
Related show

Commit Message

Jakub Jelinek Dec. 22, 2017, 8:55 a.m.
Hi!

5 further backports to 7 branch, bootstrapped/regtested on x86_64-linux and
i686-linux, committed to branch.

	Jakub
2017-12-22  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-19  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/82801
	PR ipa/83346
	* ipa-inline.c (flatten_remove_node_hook): New function.
	(ipa_inline): Keep only nodes with flatten attribute at the end of
	the array in the order from ipa_reverse_postorder, only walk that
	portion of array for flattening, if there is more than one such
	node, temporarily register a removal hook and ignore removed nodes.

	* g++.dg/ipa/pr82801.C: New test.
2017-12-22  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/83521
	* tree-ssa-phiopt.c (factor_out_conditional_conversion): Use
	gimple_build_assign without code on result of
	fold_build1 (VIEW_CONVERT_EXPR, ...), as it might not create
	a VIEW_CONVERT_EXPR.

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

--- gcc/tree-ssa-phiopt.c	(revision 255951)
+++ gcc/tree-ssa-phiopt.c	(revision 255952)
@@ -548,8 +548,12 @@ factor_out_conditional_conversion (edge
 
   /* Create the conversion stmt and insert it.  */
   if (convert_code == VIEW_CONVERT_EXPR)
-    temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
-  new_stmt = gimple_build_assign (result, convert_code, temp);
+    {
+      temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
+      new_stmt = gimple_build_assign (result, temp);
+    }
+  else
+    new_stmt = gimple_build_assign (result, convert_code, temp);
   gsi = gsi_after_labels (gimple_bb (phi));
   gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
 
--- gcc/testsuite/gcc.dg/pr83521.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/pr83521.c	(revision 255952)
@@ -0,0 +1,10 @@
+/* PR tree-optimization/83521 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-forwprop" } */
+
+int
+foo (unsigned int x, int y)
+{
+  int *z = (int *)&x;
+  return (y == 0) ? y : *z;
+}
2017-12-22  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/83523
	* tree-ssa-math-opts.c (is_widening_mult_p): Return false if
	for INTEGER_TYPE TYPE_OVERFLOW_TRAPS.
	(convert_mult_to_fma): Likewise.

	* g++.dg/tree-ssa/pr83523.C: New test.

--- gcc/tree-ssa-math-opts.c	(revision 255952)
+++ gcc/tree-ssa-math-opts.c	(revision 255953)
@@ -3074,8 +3074,12 @@ is_widening_mult_p (gimple *stmt,
 {
   tree type = TREE_TYPE (gimple_assign_lhs (stmt));
 
-  if (TREE_CODE (type) != INTEGER_TYPE
-      && TREE_CODE (type) != FIXED_POINT_TYPE)
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    {
+      if (TYPE_OVERFLOW_TRAPS (type))
+	return false;
+    }
+  else if (TREE_CODE (type) != FIXED_POINT_TYPE)
     return false;
 
   if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
@@ -3443,7 +3447,8 @@ convert_mult_to_fma (gimple *mul_stmt, t
   /* We don't want to do bitfield reduction ops.  */
   if (INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type)
-	  != GET_MODE_PRECISION (TYPE_MODE (type))))
+	  != GET_MODE_PRECISION (TYPE_MODE (type))
+	  || TYPE_OVERFLOW_TRAPS (type)))
     return false;
 
   /* If the target doesn't support it, don't generate it.  We assume that
--- gcc/testsuite/g++.dg/tree-ssa/pr83523.C	(nonexistent)
+++ gcc/testsuite/g++.dg/tree-ssa/pr83523.C	(revision 255953)
@@ -0,0 +1,25 @@
+// PR tree-optimization/83523
+// { dg-do compile }
+// { dg-options "-O2 -fexceptions -fnon-call-exceptions -ftrapv" }
+
+#ifdef __SIZEOF_INT128__
+typedef __int128 T;
+typedef long long int U;
+#else
+typedef long long int T;
+typedef int U;
+#endif
+
+struct S { S (); ~S (); };
+void bar ();
+
+T
+foo (U x, U y)
+{
+  T z = x;
+  S s;
+  bar ();
+  z *= y;
+  bar ();
+  return z;
+}
2017-12-22  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/80747
	PR rtl-optimization/83512
	* cfgrtl.c (force_nonfallthru_and_redirect): When splitting
	succ edge from ENTRY, copy partition from e->dest to the newly
	created bb.
	* bb-reorder.c (reorder_basic_blocks_simple): If last_tail is
	ENTRY, use BB_PARTITION of its successor block as current_partition.
	Don't copy partition when splitting succ edge from ENTRY.

	* gcc.dg/pr80747.c: New test.
	* gcc.dg/pr83512.c: New test.

--- gcc/bb-reorder.c	(revision 255953)
+++ gcc/bb-reorder.c	(revision 255954)
@@ -2405,7 +2405,10 @@ reorder_basic_blocks_simple (void)
 
   basic_block last_tail = (basic_block) ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux;
 
-  int current_partition = BB_PARTITION (last_tail);
+  int current_partition
+    = BB_PARTITION (last_tail == ENTRY_BLOCK_PTR_FOR_FN (cfun)
+		    ? EDGE_SUCC (ENTRY_BLOCK_PTR_FOR_FN (cfun), 0)->dest
+		    : last_tail);
   bool need_another_pass = true;
 
   for (int pass = 0; pass < 2 && need_another_pass; pass++)
@@ -2446,7 +2449,6 @@ reorder_basic_blocks_simple (void)
     {
       force_nonfallthru (e);
       e->src->aux = ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux;
-      BB_COPY_PARTITION (e->src, e->dest);
     }
 }
 
--- gcc/cfgrtl.c	(revision 255953)
+++ gcc/cfgrtl.c	(revision 255954)
@@ -1542,6 +1542,9 @@ force_nonfallthru_and_redirect (edge e,
 	  basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL,
 					       ENTRY_BLOCK_PTR_FOR_FN (cfun));
 
+	  /* Make sure new block ends up in correct hot/cold section.  */
+	  BB_COPY_PARTITION (bb, e->dest);
+
 	  /* Change the existing edge's source to be the new block, and add
 	     a new edge from the entry block to the new block.  */
 	  e->src = bb;
--- gcc/testsuite/gcc.dg/pr83512.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/pr83512.c	(revision 255954)
@@ -0,0 +1,16 @@
+/* PR rtl-optimization/83512 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -freorder-blocks-algorithm=simple" } */
+
+int a;
+
+void
+foo (int *x)
+{
+  for (;;)
+    {
+      for (*x = 0; *x < 1; *x++)
+	;
+      ++a;
+    }
+}
--- gcc/testsuite/gcc.dg/pr80747.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/pr80747.c	(revision 255954)
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/80747 */
+/* { dg-do compile } */
+/* { dg-options "-fprofile-use -freorder-blocks-and-partition -O1 -foptimize-sibling-calls" } */
+
+int
+foo (int a)
+{
+  int r;
+  if (a & 1)
+    r = foo (a - 1);
+  else if (a)
+    r = foo (a - 2);
+  else
+    return 0;
+  if (r)
+    r = r;
+  return r;
+}
2017-12-22  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2017-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR c/83448
	* gimple-ssa-sprintf.c (maybe_warn): Don't call set_caret_index
	if navail is >= dir.len.

	* gcc.c-torture/compile/pr83448.c: New test.
	* gcc.dg/tree-ssa/builtin-snprintf-warn-4.c: New test.

--- gcc/gimple-ssa-sprintf.c	(revision 255959)
+++ gcc/gimple-ssa-sprintf.c	(revision 255960)
@@ -2466,7 +2466,8 @@ maybe_warn (substring_loc &dirloc, locat
 	  /* For plain character directives (i.e., the format string itself)
 	     but not others, point the caret at the first character that's
 	     past the end of the destination.  */
-	  dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
+	  if (navail < dir.len)
+	    dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
 	}
 
       if (*dir.beg == '\0')
@@ -2594,7 +2595,8 @@ maybe_warn (substring_loc &dirloc, locat
       /* For plain character directives (i.e., the format string itself)
 	 but not others, point the caret at the first character that's
 	 past the end of the destination.  */
-      dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
+      if (navail < dir.len)
+	dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
     }
 
   if (*dir.beg == '\0')
--- gcc/testsuite/gcc.c-torture/compile/pr83448.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr83448.c	(revision 255960)
@@ -0,0 +1,15 @@
+/* PR c/83448 */
+
+char *a;
+int b;
+
+void
+foo (void)
+{
+  for (;;)
+    {
+      if (b < 0)
+	foo ();
+      __builtin_snprintf (a, b, "%*s", b, "");
+    }
+}
--- gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-4.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-4.c	(revision 255960)
@@ -0,0 +1,46 @@
+/* PR c/83448 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wformat-truncation -fdiagnostics-show-caret" } */
+
+extern int snprintf (char *, __SIZE_TYPE__, const char *, ...);
+
+void
+foo (char *a, char *b, char *c, int d, int e)
+{
+  snprintf (a, 7, "abc\\\123 efg");
+  /* { dg-warning "directive output truncated writing 9 bytes into a region of size 7" "" { target *-*-* } .-1 }
+     { dg-message ".snprintf. output 10 bytes into a destination of size 7" "note" { target *-*-* } .-2 }
+     { dg-begin-multiline-output "" }
+   snprintf (a, 7, "abc\\\123 efg");
+                    ~~~~~~~~~~~^~
+     { dg-end-multiline-output "" }
+     { dg-begin-multiline-output "note" }
+   snprintf (a, 7, "abc\\\123 efg");
+   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     { dg-end-multiline-output "" } */
+  d &= 63;
+  d += 10;
+  snprintf (b, 7, "a%dbcdefg", d);
+  /* { dg-warning "'bcdefg' directive output truncated writing 6 bytes into a region of size 4" "" { target *-*-* } .-1 }
+     { dg-message ".snprintf. output 10 bytes into a destination of size 7" "note" { target *-*-* } .-2 }
+     { dg-begin-multiline-output "" }
+   snprintf (b, 7, "a%dbcdefg", d);
+                       ~~~~^~
+     { dg-end-multiline-output "" }
+     { dg-begin-multiline-output "note" }
+   snprintf (b, 7, "a%dbcdefg", d);
+   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     { dg-end-multiline-output "" } */
+  e &= 127;
+  snprintf (c, 7, "a%dbcdefgh", e);
+  /* { dg-warning "'bcdefgh' directive output truncated writing 7 bytes into a region of size between 3 and 5" "" { target *-*-* } .-1 }
+     { dg-message ".snprintf. output between 10 and 12 bytes into a destination of size 7" "note" { target *-*-* } .-2 }
+     { dg-begin-multiline-output "" }
+   snprintf (c, 7, "a%dbcdefgh", e);
+                       ~~~~~^~
+     { dg-end-multiline-output "" }
+     { dg-begin-multiline-output "note" }
+   snprintf (c, 7, "a%dbcdefgh", e);
+   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     { dg-end-multiline-output "" } */
+}

Patch

--- gcc/ipa-inline.c	(revision 255804)
+++ gcc/ipa-inline.c	(revision 255805)
@@ -2338,6 +2338,19 @@  dump_inline_stats (void)
 	       (int) reason[i][1], reason_freq[i].to_double (), reason[i][0]);
 }
 
+/* Called when node is removed.  */
+
+static void
+flatten_remove_node_hook (struct cgraph_node *node, void *data)
+{
+  if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) == NULL)
+    return;
+
+  hash_set<struct cgraph_node *> *removed
+    = (hash_set<struct cgraph_node *> *) data;
+  removed->add (node);
+}
+
 /* Decide on the inlining.  We do so in the topological order to avoid
    expenses on updating data structures.  */
 
@@ -2347,7 +2360,7 @@  ipa_inline (void)
   struct cgraph_node *node;
   int nnodes;
   struct cgraph_node **order;
-  int i;
+  int i, j;
   int cold;
   bool remove_functions = false;
 
@@ -2380,26 +2393,56 @@  ipa_inline (void)
   if (dump_file)
     fprintf (dump_file, "\nFlattening functions:\n");
 
+  /* First shrink order array, so that it only contains nodes with
+     flatten attribute.  */
+  for (i = nnodes - 1, j = i; i >= 0; i--)
+    {
+      node = order[i];
+      if (lookup_attribute ("flatten",
+			    DECL_ATTRIBUTES (node->decl)) != NULL)
+	order[j--] = order[i];
+    }
+
+  /* After the above loop, order[j + 1] ... order[nnodes - 1] contain
+     nodes with flatten attribute.  If there is more than one such
+     node, we need to register a node removal hook, as flatten_function
+     could remove other nodes with flatten attribute.  See PR82801.  */
+  struct cgraph_node_hook_list *node_removal_hook_holder = NULL;
+  hash_set<struct cgraph_node *> *flatten_removed_nodes = NULL;
+  if (j < nnodes - 2)
+    {
+      flatten_removed_nodes = new hash_set<struct cgraph_node *>;
+      node_removal_hook_holder
+	= symtab->add_cgraph_removal_hook (&flatten_remove_node_hook,
+					   flatten_removed_nodes);
+    }
+
   /* In the first pass handle functions to be flattened.  Do this with
      a priority so none of our later choices will make this impossible.  */
-  for (i = nnodes - 1; i >= 0; i--)
+  for (i = nnodes - 1; i > j; i--)
     {
       node = order[i];
+      if (flatten_removed_nodes
+	  && flatten_removed_nodes->contains (node))
+	continue;
 
       /* Handle nodes to be flattened.
 	 Ideally when processing callees we stop inlining at the
 	 entry of cycles, possibly cloning that entry point and
 	 try to flatten itself turning it into a self-recursive
 	 function.  */
-      if (lookup_attribute ("flatten",
-			    DECL_ATTRIBUTES (node->decl)) != NULL)
-	{
-	  if (dump_file)
-	    fprintf (dump_file,
-		     "Flattening %s\n", node->name ());
-	  flatten_function (node, false);
-	}
+      if (dump_file)
+	fprintf (dump_file, "Flattening %s\n", node->name ());
+      flatten_function (node, false);
     }
+
+  if (j < nnodes - 2)
+    {
+      symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
+      delete flatten_removed_nodes;
+    }
+  free (order);
+
   if (dump_file)
     dump_overall_stats ();
 
@@ -2411,7 +2454,6 @@  ipa_inline (void)
      inline functions and virtual functions so we really know what is called
      once.  */
   symtab->remove_unreachable_nodes (dump_file);
-  free (order);
 
   /* Inline functions with a property that after inlining into all callers the
      code size will shrink because the out-of-line copy is eliminated. 
--- gcc/testsuite/g++.dg/ipa/pr82801.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ipa/pr82801.C	(revision 255805)
@@ -0,0 +1,20 @@ 
+// PR ipa/82801
+// { dg-do compile }
+// { dg-options "-O2 -Wno-attributes" }
+
+template<int>
+struct A { A () {} };
+struct B { double foo () const; };
+
+__attribute__((always_inline, flatten))
+double B::foo () const
+{
+  A<1> v;
+  return 0.0;
+}
+
+int
+main ()
+{
+  return 0;
+}