Backports to gcc-8-branch

Message ID 20181011174332.GD11625@tucnak
State New
Headers show
Series
  • Backports to gcc-8-branch
Related show

Commit Message

Jakub Jelinek Oct. 11, 2018, 5:43 p.m.
Hi!

I've bootstrapped/regtested and committed following 4 backports from trunk
to gcc-8-branch.

	Jakub
2018-10-11  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2018-09-12  Jakub Jelinek  <jakub@redhat.com>
		    Andreas Krebbel  <krebbel@linux.ibm.com>

	PR tree-optimization/86844
	* gimple-ssa-store-merging.c
	(imm_store_chain_info::coalesce_immediate): For overlapping stores, if
	there are any overlapping stores in between them, make sure they are
	also coalesced or we give up completely.

	* gcc.c-torture/execute/pr86844.c: New test.
	* gcc.dg/store_merging_22.c: New test.
	* gcc.dg/store_merging_23.c: New test.
2018-10-11  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2018-09-26  Jakub Jelinek  <jakub@redhat.com>

	PR target/87414
	* config/i386/i386.c: Include debug.h and dwarf2out.h.
	(output_indirect_thunk): Emit DW_CFA_def_cfa_offset after the
	call.

--- gcc/config/i386/i386.c	(revision 264650)
+++ gcc/config/i386/i386.c	(revision 264651)
@@ -91,6 +91,8 @@ along with GCC; see the file COPYING3.
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
+#include "debug.h"
+#include "dwarf2out.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -11014,6 +11016,23 @@ output_indirect_thunk (enum indirect_thu
 
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
 
+  /* The above call insn pushed a word to stack.  Adjust CFI info.  */
+  if (flag_asynchronous_unwind_tables && dwarf2out_do_frame ())
+    {
+      if (! dwarf2out_do_cfi_asm ())
+	{
+	  dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> ();
+	  xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
+	  xcfi->dw_cfi_oprnd1.dw_cfi_addr = ggc_strdup (indirectlabel2);
+	  vec_safe_push (cfun->fde->dw_fde_cfi, xcfi);
+	}
+      dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> ();
+      xcfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+      xcfi->dw_cfi_oprnd1.dw_cfi_offset = 2 * UNITS_PER_WORD;
+      vec_safe_push (cfun->fde->dw_fde_cfi, xcfi);
+      dwarf2out_emit_cfi (xcfi);
+    }
+
   if (regno != INVALID_REGNUM)
     {
       /* MOV.  */
2018-10-11  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2018-10-10  Jakub Jelinek  <jakub@redhat.com>

	PR target/87550
	* config/i386/i386-builtin.def (IX86_BUILTIN_RDPMC): Move from args set
	to special_args set.

	* gcc.target/i386/pr87550.c: New test.

--- gcc/config/i386/i386-builtin.def	(revision 265006)
+++ gcc/config/i386/i386-builtin.def	(revision 265007)
@@ -90,6 +90,7 @@ BDESC_END (PCMPISTR, SPECIAL_ARGS)
 BDESC_FIRST (special_args, SPECIAL_ARGS,
        0, CODE_FOR_nothing, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, UNKNOWN, (int) UINT64_FTYPE_VOID)
 BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED)
+BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT)
 BDESC (0, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID)
 
 /* 80387 (for use internally for atomic compound assignment).  */
@@ -427,7 +428,6 @@ BDESC_END (SPECIAL_ARGS, ARGS)
 BDESC_FIRST (args, ARGS,
        0, CODE_FOR_bsr, "__builtin_ia32_bsrsi", IX86_BUILTIN_BSRSI, UNKNOWN, (int) INT_FTYPE_INT)
 BDESC (OPTION_MASK_ISA_64BIT, CODE_FOR_bsr_rex64, "__builtin_ia32_bsrdi", IX86_BUILTIN_BSRDI, UNKNOWN, (int) INT64_FTYPE_INT64)
-BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT)
 BDESC (0, CODE_FOR_rotlqi3, "__builtin_ia32_rolqi", IX86_BUILTIN_ROLQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT)
 BDESC (0, CODE_FOR_rotlhi3, "__builtin_ia32_rolhi", IX86_BUILTIN_ROLHI, UNKNOWN, (int) UINT16_FTYPE_UINT16_INT)
 BDESC (0, CODE_FOR_rotrqi3, "__builtin_ia32_rorqi", IX86_BUILTIN_RORQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT)
--- gcc/testsuite/gcc.target/i386/pr87550.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr87550.c	(revision 265007)
@@ -0,0 +1,21 @@
+/* PR target/87550 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <x86intrin.h>
+
+int
+foo (int x)
+{
+  return __rdtsc () + __rdtsc ();
+}
+
+/* { dg-final { scan-assembler-times "\trdtsc\[\n\r]" 2 } } */
+
+int
+bar (int x)
+{
+  return __rdpmc (0) + __rdpmc (0);
+}
+
+/* { dg-final { scan-assembler-times "\trdpmc\[\n\r]" 2 } } */
2018-10-11  Jakub Jelinek  <jakub@redhat.com>

	PR c++/87582
	* typeck.c (maybe_warn_about_returning_address_of_local): If
	whats_returned is a structured binding identifier and the structured
	binding is a reference, recurse on its initializer.

	* g++.dg/cpp1z/decomp48.C: New test.

--- gcc/cp/typeck.c	(revision 265040)
+++ gcc/cp/typeck.c	(revision 265041)
@@ -9067,6 +9067,22 @@ maybe_warn_about_returning_address_of_lo
       && !(TREE_STATIC (whats_returned)
 	   || TREE_PUBLIC (whats_returned)))
     {
+      if (VAR_P (whats_returned)
+	  && DECL_DECOMPOSITION_P (whats_returned)
+	  && DECL_DECOMP_BASE (whats_returned)
+	  && DECL_HAS_VALUE_EXPR_P (whats_returned))
+	{
+	  /* When returning address of a structured binding, if the structured
+	     binding is not a reference, continue normally, if it is a
+	     reference, recurse on the initializer of the structured
+	     binding.  */
+	  tree base = DECL_DECOMP_BASE (whats_returned);
+	  if (TREE_CODE (TREE_TYPE (base)) == REFERENCE_TYPE)
+	    {
+	      tree init = DECL_INITIAL (base);
+	      return maybe_warn_about_returning_address_of_local (init);
+	    }
+	}
       if (TREE_CODE (valtype) == REFERENCE_TYPE)
 	warning_at (DECL_SOURCE_LOCATION (whats_returned),
 		    OPT_Wreturn_local_addr,
--- gcc/testsuite/g++.dg/cpp1z/decomp48.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp48.C	(revision 265041)
@@ -0,0 +1,134 @@
+// PR c++/87582
+// { dg-do run { target c++11 } }
+// { dg-options "-Wreturn-local-addr" }
+
+struct S { int s, t; };
+S v {1, 2};
+int a[3] = {1, 2, 3};
+
+int &
+f1 ()
+{
+  auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-bogus "reference to local variable '.' returned" }
+}
+
+int &
+f2 ()
+{
+  S v {1, 2};		// { dg-warning "reference to local variable 'v' returned" }
+  auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;
+}
+
+int &
+f3 ()
+{
+  auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-bogus "reference to local variable '.' returned" }
+}
+
+int &
+f4 ()
+{
+  int a[3] = {1, 2, 3};	// { dg-warning "reference to local variable 'a' returned" }
+  auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;
+}
+
+int &
+f5 ()
+{
+  auto [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-warning "reference to local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f6 ()
+{
+  S v {1, 2};
+  auto [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-warning "reference to local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f7 ()
+{
+  auto [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-warning "reference to local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f8 ()
+{
+  int a[3] = {1, 2, 3};
+  auto [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return s;		// { dg-warning "reference to local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f9 ()
+{
+  auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-bogus "address of local variable '.' returned" }
+}
+
+int *
+f10 ()
+{
+  S v {1, 2};		// { dg-warning "address of local variable 'v' returned" }
+  auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;
+}
+
+int *
+f11 ()
+{
+  auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-bogus "address of local variable '.' returned" }
+}
+
+int *
+f12 ()
+{
+  int a[3] = {1, 2, 3};	// { dg-warning "address of local variable 'a' returned" }
+  auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;
+}
+
+int *
+f13 ()
+{
+  auto [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-warning "address of local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f14 ()
+{
+  S v {1, 2};
+  auto [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-warning "address of local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f15 ()
+{
+  auto [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-warning "address of local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f16 ()
+{
+  int a[3] = {1, 2, 3};
+  auto [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return &s;		// { dg-warning "address of local variable 's' returned" "" { target *-*-* } .-1 }
+}
+
+int
+main ()
+{
+  if (&f1 () != &v.s || &f3 () != &a[0] || f9 () != &v.s || f11 () != &a[0])
+    __builtin_abort ();
+}

Patch

--- gcc/gimple-ssa-store-merging.c	(revision 264231)
+++ gcc/gimple-ssa-store-merging.c	(revision 264232)
@@ -2648,15 +2648,80 @@  imm_store_chain_info::coalesce_immediate
 	{
 	  /* Only allow overlapping stores of constants.  */
 	  if (info->rhs_code == INTEGER_CST
-	      && merged_store->stores[0]->rhs_code == INTEGER_CST
-	      && check_no_overlap (m_store_info, i, INTEGER_CST,
-				   MAX (merged_store->last_order, info->order),
-				   MAX (merged_store->start
-					+ merged_store->width,
-					info->bitpos + info->bitsize)))
+	      && merged_store->stores[0]->rhs_code == INTEGER_CST)
 	    {
-	      merged_store->merge_overlapping (info);
-	      continue;
+	      unsigned int last_order
+		= MAX (merged_store->last_order, info->order);
+	      unsigned HOST_WIDE_INT end
+		= MAX (merged_store->start + merged_store->width,
+		       info->bitpos + info->bitsize);
+	      if (check_no_overlap (m_store_info, i, INTEGER_CST,
+				    last_order, end))
+		{
+		  /* check_no_overlap call above made sure there are no
+		     overlapping stores with non-INTEGER_CST rhs_code
+		     in between the first and last of the stores we've
+		     just merged.  If there are any INTEGER_CST rhs_code
+		     stores in between, we need to merge_overlapping them
+		     even if in the sort_by_bitpos order there are other
+		     overlapping stores in between.  Keep those stores as is.
+		     Example:
+			MEM[(int *)p_28] = 0;
+			MEM[(char *)p_28 + 3B] = 1;
+			MEM[(char *)p_28 + 1B] = 2;
+			MEM[(char *)p_28 + 2B] = MEM[(char *)p_28 + 6B];
+		     We can't merge the zero store with the store of two and
+		     not merge anything else, because the store of one is
+		     in the original order in between those two, but in
+		     store_by_bitpos order it comes after the last store that
+		     we can't merge with them.  We can merge the first 3 stores
+		     and keep the last store as is though.  */
+		  unsigned int len = m_store_info.length (), k = i;
+		  for (unsigned int j = i + 1; j < len; ++j)
+		    {
+		      store_immediate_info *info2 = m_store_info[j];
+		      if (info2->bitpos >= end)
+			break;
+		      if (info2->order < last_order)
+			{
+			  if (info2->rhs_code != INTEGER_CST)
+			    {
+			      /* Normally check_no_overlap makes sure this
+				 doesn't happen, but if end grows below, then
+				 we need to process more stores than
+				 check_no_overlap verified.  Example:
+				    MEM[(int *)p_5] = 0;
+				    MEM[(short *)p_5 + 3B] = 1;
+				    MEM[(char *)p_5 + 4B] = _9;
+				    MEM[(char *)p_5 + 2B] = 2;  */
+			      k = 0;
+			      break;
+			    }
+			  k = j;
+			  end = MAX (end, info2->bitpos + info2->bitsize);
+			}
+		    }
+
+		  if (k != 0)
+		    {
+		      merged_store->merge_overlapping (info);
+
+		      for (unsigned int j = i + 1; j <= k; j++)
+			{
+			  store_immediate_info *info2 = m_store_info[j];
+			  gcc_assert (info2->bitpos < end);
+			  if (info2->order < last_order)
+			    {
+			      gcc_assert (info2->rhs_code == INTEGER_CST);
+			      merged_store->merge_overlapping (info2);
+			    }
+			  /* Other stores are kept and not merged in any
+			     way.  */
+			}
+		      ignore = k;
+		      continue;
+		    }
+		}
 	    }
 	}
       /* |---store 1---||---store 2---|
--- gcc/testsuite/gcc.c-torture/execute/pr86844.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr86844.c	(revision 264232)
@@ -0,0 +1,24 @@ 
+/* PR tree-optimization/86844 */
+
+__attribute__((noipa)) void
+foo (int *p)
+{
+  *p = 0;
+  *((char *)p + 3) = 1;
+  *((char *)p + 1) = 2;
+  *((char *)p + 2) = *((char *)p + 6);
+}
+
+int
+main ()
+{
+  int a[2] = { -1, 0 };
+  if (sizeof (int) != 4)
+    return 0;
+  ((char *)a)[6] = 3;
+  foo (a);
+  if (((char *)a)[0] != 0 || ((char *)a)[1] != 2
+      || ((char *)a)[2] != 3 || ((char *)a)[3] != 1)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/store_merging_22.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_22.c	(revision 264232)
@@ -0,0 +1,16 @@ 
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+  *((char *)p + 3) = 1;
+  *((char *)p + 1) = 2;
+  *((char *)p + 2) = *((char *)p + 38);
+}
+
+/* { dg-final { scan-tree-dump-times "Merging successful" 1 "store-merging" } } */
+/* { dg-final { scan-tree-dump-times "New sequence of 1 stmts to replace old one of 3 stmts" 1 "store-merging" } } */
--- gcc/testsuite/gcc.dg/store_merging_23.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_23.c	(revision 264232)
@@ -0,0 +1,16 @@ 
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+  int one = 1;
+  __builtin_memcpy ((char *) p + 3, &one, sizeof (int));
+  *((char *)p + 4) = *((char *)p + 36);
+  *((char *)p + 1) = 2;
+}
+
+/* { dg-final { scan-tree-dump-not "Merging successful" "store-merging" } } */