diff mbox

Backports to 4.9.4

Message ID 20160707215854.GV7387@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek July 7, 2016, 9:58 p.m. UTC
Hi!

I've bootstrapped/regtested on x86_64-linux and i686-linux and committed
following backports from gcc-5-branch and trunk to gcc-4_9-branch:

	Jakub
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-12-12  Richard Biener  <rguenther@suse.de>

	PR middle-end/64280
	* tree-cfg.c (replace_uses_by): Guard assert properly.

	* g++.dg/torture/pr64280.C: New testcase.
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

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

	PR middle-end/70022
	* gcc.dg/pr70022.c: Add -w -Wno-psabi to dg-options.

--- gcc/testsuite/gcc.dg/pr70022.c	(revision 233904)
+++ gcc/testsuite/gcc.dg/pr70022.c	(revision 233905)
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-options "-w -Wno-psabi" } */
 
 typedef int v4si __attribute__ ((vector_size (16)));
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/69797
	* c-common.c (sync_resolve_size): Diagnose too few arguments
	even when params is non-NULL empty vector.

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

--- gcc/c-family/c-common.c	(revision 234548)
+++ gcc/c-family/c-common.c	(revision 234549)
@@ -10511,7 +10511,7 @@ sync_resolve_size (tree function, vec<tr
   tree type;
   int size;
 
-  if (!params)
+  if (vec_safe_is_empty (params))
     {
       error ("too few arguments to function %qE", function);
       return 0;
--- gcc/testsuite/c-c++-common/pr69797.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pr69797.c	(revision 234549)
@@ -0,0 +1,8 @@
+/* PR c++/69797 */
+/* { dg-do compile } */
+
+void
+foo () 
+{
+  __atomic_fetch_add ();	/* { dg-error "too few arguments to function" } */
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

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

	PR tree-optimization/69802
	* tree-ssa-reassoc.c (update_range_test): If op is
	SSA_NAME_IS_DEFAULT_DEF, give up unless tem is a positive
	op == 1 test of precision 1 integral op, otherwise handle
	that case as op itself.  Fix up formatting.
	(optimize_range_tests_to_bit_test, optimize_range_tests): Fix
	up formatting.

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

--- gcc/tree-ssa-reassoc.c	(revision 234549)
+++ gcc/tree-ssa-reassoc.c	(revision 234550)
@@ -2091,10 +2091,33 @@ update_range_test (struct range_entry *r
   tree tem = build_range_check (loc, optype, exp, in_p, low, high);
   enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
   gimple_stmt_iterator gsi;
+  unsigned int uid;
 
   if (tem == NULL_TREE)
     return false;
 
+  /* If op is default def SSA_NAME, there is no place to insert the
+     new comparison.  Give up, unless we can use OP itself as the
+     range test.  */
+  if (op && SSA_NAME_IS_DEFAULT_DEF (op))
+    {
+      if (op == range->exp
+	  && ((TYPE_PRECISION (optype) == 1 && TYPE_UNSIGNED (optype))
+	      || TREE_CODE (optype) == BOOLEAN_TYPE)
+	  && (op == tem
+	      || (TREE_CODE (tem) == EQ_EXPR
+		  && TREE_OPERAND (tem, 0) == op
+		  && integer_onep (TREE_OPERAND (tem, 1))))
+	  && opcode != BIT_IOR_EXPR
+	  && (opcode != ERROR_MARK || oe->rank != BIT_IOR_EXPR))
+	{
+	  stmt = NULL;
+	  tem = op;
+	}
+      else
+	return false;
+    }
+
   if (strict_overflow_p && issue_strict_overflow_warning (wc))
     warning_at (loc, OPT_Wstrict_overflow,
 		"assuming signed overflow does not occur "
@@ -2128,11 +2151,22 @@ update_range_test (struct range_entry *r
     tem = invert_truthvalue_loc (loc, tem);
 
   tem = fold_convert_loc (loc, optype, tem);
-  gsi = gsi_for_stmt (stmt);
+  if (stmt)
+    {
+      gsi = gsi_for_stmt (stmt);
+      uid = gimple_uid (stmt);
+    }
+  else
+    {
+      gsi = gsi_none ();
+      uid = 0;
+    }
+  if (stmt == NULL)
+    gcc_checking_assert (tem == op);
   /* In rare cases range->exp can be equal to lhs of stmt.
      In that case we have to insert after the stmt rather then before
      it.  */
-  if (op == range->exp)
+  else if (op == range->exp)
     tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, false,
 				    GSI_CONTINUE_LINKING);
   else
@@ -2145,7 +2179,7 @@ update_range_test (struct range_entry *r
     if (gimple_uid (gsi_stmt (gsi)))
       break;
     else
-      gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt));
+      gimple_set_uid (gsi_stmt (gsi), uid);
 
   oe->op = tem;
   range->exp = exp;
--- gcc/testsuite/gcc.dg/pr69802.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr69802.c	(revision 234550)
@@ -0,0 +1,23 @@
+/* PR tree-optimization/69802 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+struct S { unsigned f : 1; };
+int a, d;
+
+int
+foo (void)
+{
+  unsigned b = 0;
+  struct S c;
+  d = ((1 && b) < c.f) & c.f;	/* { dg-warning "is used uninitialized" } */
+  return a;
+}
+
+int
+bar (_Bool c)
+{
+  unsigned b = 0;
+  d = ((1 && b) < c) & c;
+  return a;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/67767
	* parser.c (cp_parser_std_attribute_spec_seq): Don't assume
	attr_spec is always single element chain, chain all the attributes
	properly together in the right order.

	* g++.dg/cpp0x/pr67767.C: New test.

--- gcc/cp/parser.c	(revision 234550)
+++ gcc/cp/parser.c	(revision 234551)
@@ -22645,7 +22645,8 @@ cp_parser_std_attribute_spec (cp_parser
 static tree
 cp_parser_std_attribute_spec_seq (cp_parser *parser)
 {
-  tree attr_specs = NULL;
+  tree attr_specs = NULL_TREE;
+  tree attr_last = NULL_TREE;
 
   while (true)
     {
@@ -22655,11 +22656,13 @@ cp_parser_std_attribute_spec_seq (cp_par
       if (attr_spec == error_mark_node)
 	return error_mark_node;
 
-      TREE_CHAIN (attr_spec) = attr_specs;
-      attr_specs = attr_spec;
+      if (attr_last)
+	TREE_CHAIN (attr_last) = attr_spec;
+      else
+	attr_specs = attr_last = attr_spec;
+      attr_last = tree_last (attr_last);
     }
 
-  attr_specs = nreverse (attr_specs);
   return attr_specs;
 }
 
--- gcc/testsuite/g++.dg/cpp0x/pr67767.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/pr67767.C	(revision 234551)
@@ -0,0 +1,10 @@
+// PR c++/67767
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wsuggest-attribute=noreturn" }
+
+void foo [[gnu::cold, gnu::noreturn]] ();
+
+void foo ()	// { dg-bogus "function might be candidate for attribute" }
+{
+  throw 1;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-02-26  Jakub Jelinek  <jakub@redhat.com>
		    Eric Botcazou  <ebotcazou@adacore.com>

	PR rtl-optimization/69891
	* dse.c (scan_insn): If we can't figure out memset arguments
	or they are non-constant, call clear_rhs_from_active_local_stores.

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

--- gcc/dse.c	(revision 234554)
+++ gcc/dse.c	(revision 234555)
@@ -2582,6 +2582,8 @@ scan_insn (bb_info_t bb_info, rtx insn)
 		      active_local_stores = insn_info;
 		    }
 		}
+	      else
+		clear_rhs_from_active_local_stores ();
 	    }
 	}
 
--- gcc/testsuite/gcc.target/i386/pr69891.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr69891.c	(revision 234555)
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/69891 */
+/* { dg-do run } */
+/* { dg-options "-O -fno-tree-fre -mstringop-strategy=libcall -Wno-psabi" } */
+/* { dg-additional-options "-mno-sse" { target ia32 } } */
+
+typedef unsigned short A;
+typedef unsigned short B __attribute__ ((vector_size (32)));
+typedef unsigned int C;
+typedef unsigned int D __attribute__ ((vector_size (32)));
+typedef unsigned long long E;
+typedef unsigned long long F __attribute__ ((vector_size (32)));
+
+__attribute__((noinline, noclone)) unsigned
+foo(D a, B b, D c, F d)
+{
+  b /= (B) {1, -c[0]} | 1;
+  c[0] |= 7;
+  a %= c | 1;
+  c ^= c;
+  return a[0] + b[15] + c[0] + d[3];
+}
+
+int
+main ()
+{
+  unsigned x = foo ((D) {}, (B) {}, (D) {}, (F) {});
+  if (x != 0)
+    __builtin_abort ();
+  return 0;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-03-09  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/70152
	* tree-sra.c (replace_removed_params_ssa_names): Copy over
	SSA_NAME_OCCURS_IN_ABNORMAL_PHI from old_name to new_name.

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

--- gcc/tree-sra.c	(revision 234560)
+++ gcc/tree-sra.c	(revision 234561)
@@ -4609,6 +4609,8 @@ replace_removed_params_ssa_names (tree o
 
   repl = get_replaced_param_substitute (adj);
   new_name = make_ssa_name (repl, stmt);
+  SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name)
+    = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name);
 
   if (dump_file)
     {
--- gcc/testsuite/gcc.dg/pr70152.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr70152.c	(revision 234561)
@@ -0,0 +1,27 @@
+/* PR tree-optimization/70152 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int a;
+int foo (void);
+int setjmp (char *);
+char buf[64];
+
+static int
+bar (int x)
+{
+  x = 0;
+  setjmp (buf);
+  for (;;)
+    {
+    switch (x)
+      case 5:
+	x = foo ();
+    }
+}
+
+void
+baz (void)
+{
+  bar (a);
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-03-11  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/70169
	* tree-ssa-loop.c (gen_lsm_tmp_name): Handle FUNCTION_DECL and
	LABEL_DECL like VAR_DECL.  Emit nothing instead of gcc_unreachable
	for unknown codes.

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

--- gcc/tree-ssa-loop.c	(revision 234561)
+++ gcc/tree-ssa-loop.c	(revision 234562)
@@ -698,6 +698,8 @@ gen_lsm_tmp_name (tree ref)
     case SSA_NAME:
     case VAR_DECL:
     case PARM_DECL:
+    case FUNCTION_DECL:
+    case LABEL_DECL:
       name = get_name (ref);
       if (!name)
 	name = "D";
@@ -713,11 +715,9 @@ gen_lsm_tmp_name (tree ref)
       break;
 
     case INTEGER_CST:
+    default:
       /* Nothing.  */
       break;
-
-    default:
-      gcc_unreachable ();
     }
 }
 
--- gcc/testsuite/gcc.dg/pr70169.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr70169.c	(revision 234562)
@@ -0,0 +1,40 @@
+/* PR tree-optimization/70169 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing -fno-tree-dce" } */
+
+int printf (const char *, ...); 
+
+void
+foo ()
+{
+  unsigned char *p = (unsigned char *) &printf;
+  for (;;)
+    (*p)++;
+}
+
+void
+bar (int x)
+{
+  unsigned char *p = (unsigned char *) &printf;
+  int i;
+  for (i = 0; i < x; i++)
+    (*p)++;
+}
+
+void
+baz (int x, int y)
+{
+  unsigned char *p = (unsigned char *) &&lab;
+  int i;
+  if (y)
+    {
+      for (i = 0; i < x; i++)
+	(*p)++;
+    }
+  else
+    {
+     lab:
+      asm volatile ("");
+      foo ();
+    }
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-03-15  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/70222
	* combine.c (simplify_shift_const_1): For A >> B >> C LSHIFTRT
	optimization if mode is different from result_mode, queue up masking
	of the result in outer_op.  Formatting fix.

	* gcc.c-torture/execute/pr70222-1.c: New test.
	* gcc.c-torture/execute/pr70222-2.c: New test.

--- gcc/combine.c	(revision 234562)
+++ gcc/combine.c	(revision 234563)
@@ -10476,9 +10476,19 @@ simplify_shift_const_1 (enum rtx_code co
 		   && CONST_INT_P (XEXP (varop, 0))
 		   && !CONST_INT_P (XEXP (varop, 1)))
 	    {
+	      /* For ((unsigned) (cstULL >> count)) >> cst2 we have to make
+		 sure the result will be masked.  See PR70222.  */
+	      if (code == LSHIFTRT
+		  && mode != result_mode
+		  && !merge_outer_ops (&outer_op, &outer_const, AND,
+				       GET_MODE_MASK (result_mode)
+				       >> orig_count, result_mode,
+				       &complement_p))
+		break;
+
 	      rtx new_rtx = simplify_const_binary_operation (code, mode,
-							 XEXP (varop, 0),
-							 GEN_INT (count));
+							     XEXP (varop, 0),
+							     GEN_INT (count));
 	      varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1));
 	      count = 0;
 	      continue;
--- gcc/testsuite/gcc.c-torture/execute/pr70222-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr70222-1.c	(revision 234563)
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/70222 */
+
+int a = 1;
+unsigned int b = 2;
+int c = 0;
+int d = 0;
+
+void
+foo ()
+{
+  int e = ((-(c >= c)) < b) > ((int) (-1ULL >> ((a / a) * 15)));
+  d = -e;
+}
+
+__attribute__((noinline, noclone)) void
+bar (int x)
+{
+  if (x != -1)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+  foo ();
+  bar (d);
+#endif
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr70222-2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr70222-2.c	(revision 234563)
@@ -0,0 +1,20 @@
+/* PR rtl-optimization/70222 */
+
+#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+__attribute__((noinline, noclone)) unsigned int
+foo (int x)
+{
+  unsigned long long y = -1ULL >> x;
+  return (unsigned int) y >> 31;
+}
+#endif
+
+int
+main ()
+{
+#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+  if (foo (15) != 1 || foo (32) != 1 || foo (33) != 0)
+    __builtin_abort ();
+#endif
+  return 0;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-03-29  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/70429
	* combine.c (simplify_shift_const_1): For ASHIFTRT don't optimize
	(cst1 >> count) >> cst2 into (cst1 >> cst2) >> count if
	mode != result_mode.

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

--- gcc/combine.c	(revision 234566)
+++ gcc/combine.c	(revision 234567)
@@ -10485,6 +10485,11 @@ simplify_shift_const_1 (enum rtx_code co
 				       >> orig_count, result_mode,
 				       &complement_p))
 		break;
+	      /* For ((int) (cstLL >> count)) >> cst2 just give up.  Queuing
+		 up outer sign extension (often left and right shift) is
+		 hardly more efficient than the original.  See PR70429.  */
+	      if (code == ASHIFTRT && mode != result_mode)
+		break;
 
 	      rtx new_rtx = simplify_const_binary_operation (code, mode,
 							     XEXP (varop, 0),
--- gcc/testsuite/gcc.c-torture/execute/pr70429.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr70429.c	(revision 234567)
@@ -0,0 +1,17 @@
+/* PR rtl-optimization/70429 */
+
+__attribute__((noinline, noclone)) int
+foo (int a)
+{
+  return (int) (0x14ff6e2207db5d1fLL >> a) >> 4;
+}
+
+int
+main ()
+{
+  if (sizeof (int) != 4 || sizeof (long long) != 8 || __CHAR_BIT__ != 8)
+    return 0;
+  if (foo (1) != 0x3edae8 || foo (2) != -132158092)
+    __builtin_abort ();
+  return 0;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-05-17  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/71160
	* asan/asan_malloc_linux.cc: Cherry pick upstream r254395
	and r269633.

--- libsanitizer/asan/asan_malloc_linux.cc	(revision 236432)
+++ libsanitizer/asan/asan_malloc_linux.cc	(revision 236433)
@@ -58,39 +58,62 @@ void ReplaceSystemMalloc() {
 // ---------------------- Replacement functions ---------------- {{{1
 using namespace __asan;  // NOLINT
 
+static uptr allocated_for_dlsym;
+static const uptr kDlsymAllocPoolSize = 1024;
+static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
+
+static bool IsInDlsymAllocPool(const void *ptr) {
+  uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
+  return off < sizeof(alloc_memory_for_dlsym);
+}
+
+static void *AllocateFromLocalPool(uptr size_in_bytes) {
+  uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize;
+  void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym];
+  allocated_for_dlsym += size_in_words;
+  CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize);
+  return mem;
+}
+
 INTERCEPTOR(void, free, void *ptr) {
   GET_STACK_TRACE_FREE;
+  if (UNLIKELY(IsInDlsymAllocPool(ptr)))
+    return;
   asan_free(ptr, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void, cfree, void *ptr) {
   GET_STACK_TRACE_FREE;
+  if (UNLIKELY(IsInDlsymAllocPool(ptr)))
+    return;
   asan_free(ptr, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void*, malloc, uptr size) {
+  if (UNLIKELY(!asan_inited))
+    // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym.
+    return AllocateFromLocalPool(size);
   GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
 
 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
-  if (!asan_inited) {
+  if (UNLIKELY(!asan_inited))
     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
-    const uptr kCallocPoolSize = 1024;
-    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
-    static uptr allocated;
-    uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
-    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
-    allocated += size_in_words;
-    CHECK(allocated < kCallocPoolSize);
-    return mem;
-  }
+    return AllocateFromLocalPool(nmemb * size);
   GET_STACK_TRACE_MALLOC;
   return asan_calloc(nmemb, size, &stack);
 }
 
 INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
   GET_STACK_TRACE_MALLOC;
+  if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
+    uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
+    uptr copy_size = Min(size, kDlsymAllocPoolSize - offset);
+    void *new_ptr = asan_malloc(size, &stack);
+    internal_memcpy(new_ptr, ptr, copy_size);
+    return new_ptr;
+  }
   return asan_realloc(ptr, size, &stack);
 }
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

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

	PR middle-end/71494
	* tree-nested.c (convert_nonlocal_reference_stmt): For GIMPLE_GOTO
	without LABEL_DECL, set *handled_ops_p to false instead of true.

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

--- gcc/tree-nested.c	(revision 237448)
+++ gcc/tree-nested.c	(revision 237449)
@@ -1348,7 +1348,7 @@ convert_nonlocal_reference_stmt (gimple_
 	{
 	  wi->val_only = true;
 	  wi->is_lhs = false;
-	  *handled_ops_p = true;
+	  *handled_ops_p = false;
 	  return NULL_TREE;
 	}
       break;
--- gcc/testsuite/gcc.c-torture/execute/pr71494.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71494.c	(revision 237449)
@@ -0,0 +1,22 @@
+/* PR middle-end/71494 */
+
+int
+main ()
+{
+  void *label = &&out;
+  int i = 0;
+  void test (void)
+  {
+    label = &&out2;
+    goto *label;
+   out2:;
+    i++;
+  }
+  goto *label;
+ out:
+  i += 2;
+  test ();
+  if (i != 3)
+    __builtin_abort ();
+  return 0;
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-21  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/71588
	* tree-ssa-strlen.c (valid_builtin_call): New function.
	(adjust_last_stmt, strlen_optimize_stmt): Use it.

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

--- gcc/tree-ssa-strlen.c	(revision 237632)
+++ gcc/tree-ssa-strlen.c	(revision 237633)
@@ -768,6 +768,49 @@ find_equal_ptrs (tree ptr, int idx)
     }
 }
 
+/* Return true if STMT is a call to a builtin function with the right
+   arguments and attributes that should be considered for optimization
+   by this pass.  */
+
+static bool
+valid_builtin_call (gimple stmt)
+{
+  if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+    return false;
+
+  tree callee = gimple_call_fndecl (stmt);
+  switch (DECL_FUNCTION_CODE (callee))
+    {
+    case BUILT_IN_STRCHR:
+    case BUILT_IN_STRLEN:
+      /* The above functions should be pure.  Punt if they aren't.  */
+      if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
+	return false;
+      break;
+
+    case BUILT_IN_MEMCPY:
+    case BUILT_IN_MEMCPY_CHK:
+    case BUILT_IN_MEMPCPY:
+    case BUILT_IN_MEMPCPY_CHK:
+    case BUILT_IN_STPCPY:
+    case BUILT_IN_STPCPY_CHK:
+    case BUILT_IN_STRCAT:
+    case BUILT_IN_STRCAT_CHK:
+    case BUILT_IN_STRCPY:
+    case BUILT_IN_STRCPY_CHK:
+      /* The above functions should be neither const nor pure.  Punt if they
+	 aren't.  */
+      if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
+	return false;
+      break;
+
+    default:
+      break;
+    }
+
+  return true;
+}
+
 /* If the last .MEM setter statement before STMT is
    memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
    and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
@@ -842,7 +885,7 @@ adjust_last_stmt (strinfo si, gimple stm
       return;
     }
 
-  if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL))
+  if (!valid_builtin_call (last.stmt))
     return;
 
   callee = gimple_call_fndecl (last.stmt);
@@ -1827,7 +1870,7 @@ strlen_optimize_stmt (gimple_stmt_iterat
   if (is_gimple_call (stmt))
     {
       tree callee = gimple_call_fndecl (stmt);
-      if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+      if (valid_builtin_call (stmt))
 	switch (DECL_FUNCTION_CODE (callee))
 	  {
 	  case BUILT_IN_STRLEN:
--- gcc/testsuite/gcc.dg/pr71558.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr71558.c	(revision 237633)
@@ -0,0 +1,17 @@
+/* PR tree-optimization/71588 */
+
+/* strcpy must not be pure, but make sure we don't ICE even when
+   it is declared incorrectly.  */
+char *strcpy (char *, const char *) __attribute__ ((__pure__));
+__SIZE_TYPE__ strlen (const char *);
+void *malloc (__SIZE_TYPE__);
+
+char a[20];
+
+char *
+foo (void)
+{
+  __SIZE_TYPE__ b = strlen (a);
+  char *c = malloc (b);
+  return strcpy (c, a);
+}
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-28  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/71626
	* config/i386/i386.c (ix86_expand_vector_move): For SUBREG of
	a constant, force its SUBREG_REG into memory or register instead
	of whole op1.

	* gcc.c-torture/execute/pr71626-1.c: New test.
	* gcc.c-torture/execute/pr71626-2.c: New test.

--- gcc/config/i386/i386.c	(revision 237938)
+++ gcc/config/i386/i386.c	(revision 237939)
@@ -16918,12 +16918,29 @@ ix86_expand_vector_move (enum machine_mo
      of the register, once we have that information we may be able
      to handle some of them more efficiently.  */
   if (can_create_pseudo_p ()
-      && register_operand (op0, mode)
       && (CONSTANT_P (op1)
 	  || (GET_CODE (op1) == SUBREG
 	      && CONSTANT_P (SUBREG_REG (op1))))
-      && !standard_sse_constant_p (op1))
-    op1 = validize_mem (force_const_mem (mode, op1));
+      && ((register_operand (op0, mode)
+	   && !standard_sse_constant_p (op1))
+	  /* ix86_expand_vector_move_misalign() does not like constants.  */
+	  || (SSE_REG_MODE_P (mode)
+	      && MEM_P (op0)
+	      && MEM_ALIGN (op0) < align)))
+    {
+      if (GET_CODE (op1) == SUBREG)
+	{
+	  machine_mode imode = GET_MODE (SUBREG_REG (op1));
+	  rtx r = force_const_mem (imode, SUBREG_REG (op1));
+	  if (r)
+	    r = validize_mem (r);
+	  else
+	    r = force_reg (imode, SUBREG_REG (op1));
+	  op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
+	}
+      else
+	op1 = validize_mem (force_const_mem (mode, op1));
+    }
 
   /* We need to check memory alignment for SSE mode since attribute
      can make operands unaligned.  */
@@ -16934,13 +16951,8 @@ ix86_expand_vector_move (enum machine_mo
     {
       rtx tmp[2];
 
-      /* ix86_expand_vector_move_misalign() does not like constants ... */
-      if (CONSTANT_P (op1)
-	  || (GET_CODE (op1) == SUBREG
-	      && CONSTANT_P (SUBREG_REG (op1))))
-	op1 = validize_mem (force_const_mem (mode, op1));
-
-      /* ... nor both arguments in memory.  */
+      /* ix86_expand_vector_move_misalign() does not like both
+	 arguments in memory.  */
       if (!register_operand (op0, mode)
 	  && !register_operand (op1, mode))
 	op1 = force_reg (mode, op1);
--- gcc/testsuite/gcc.c-torture/execute/pr71626-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71626-1.c	(revision 237939)
@@ -0,0 +1,19 @@
+/* PR middle-end/71626 */
+
+typedef __INTPTR_TYPE__ V __attribute__((__vector_size__(sizeof (__INTPTR_TYPE__))));
+
+__attribute__((noinline, noclone)) V
+foo ()
+{
+  V v = { (__INTPTR_TYPE__) foo };
+  return v;
+}
+
+int
+main ()
+{
+  V v = foo ();
+  if (v[0] != (__INTPTR_TYPE__) foo)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr71626-2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr71626-2.c	(revision 237939)
@@ -0,0 +1,4 @@
+/* PR middle-end/71626 */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+#include "pr71626-1.c"
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71705
	* trans-openmp.c (gfc_trans_omp_clauses): Set TREE_ADDRESSABLE on
	decls in to/from clauses.

	* gfortran.dg/gomp/pr71705.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 237940)
+++ gcc/fortran/trans-openmp.c	(revision 237941)
@@ -2180,6 +2180,8 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
 		  tree decl = gfc_get_symbol_decl (n->sym);
 		  if (gfc_omp_privatize_by_reference (decl))
 		    decl = build_fold_indirect_ref (decl);
+		  else if (DECL_P (decl))
+		    TREE_ADDRESSABLE (decl) = 1;
 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
 		    {
 		      tree type = TREE_TYPE (decl);
--- gcc/testsuite/gfortran.dg/gomp/pr71705.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr71705.f90	(revision 237941)
@@ -0,0 +1,7 @@
+! PR fortran/71705
+! { dg-do compile }
+
+  real :: x
+  x = 0.0
+  !$omp target update to(x)
+end
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71704
	* parse.c (matchs, matcho): If spec_only, only gfc_match the keyword
	and if successful, goto do_spec_only.
	(matchds, matchdo): Define.
	(decode_omp_directive): Add spec_only local var and set it.
	Use matchds or matchdo macros instead of matchs or matcho
	for declare target, declare simd, declare reduction and threadprivate
	directives.  Return ST_GET_FCN_CHARACTERISTICS if a non-declarative
	directive could be matched.
	(next_statement): For ST_GET_FCN_CHARACTERISTICS restore
	gfc_current_locus from old_locus even if there is no label.

	* gfortran.dg/gomp/pr71704.f90: New test.

--- gcc/fortran/parse.c	(revision 237941)
+++ gcc/fortran/parse.c	(revision 237942)
@@ -559,9 +559,12 @@ decode_statement (void)
   return ST_NONE;
 }
 
-/* Like match, but set a flag simd_matched if keyword matched.  */
+/* Like match, but set a flag simd_matched if keyword matched
+   and if spec_only, goto do_spec_only without actually matching.  */
 #define matchs(keyword, subr, st)				\
     do {							\
+      if (spec_only && gfc_match (keyword) == MATCH_YES)	\
+	goto do_spec_only;					\
       if (match_word_omp_simd (keyword, subr, &old_locus,	\
 			       &simd_matched) == MATCH_YES)	\
 	return st;						\
@@ -569,11 +572,36 @@ decode_statement (void)
 	undo_new_statement ();				  	\
     } while (0);
 
-/* Like match, but don't match anything if not -fopenmp.  */
+/* Like match, but don't match anything if not -fopenmp
+   and if spec_only, goto do_spec_only without actually matching.  */
 #define matcho(keyword, subr, st)				\
     do {							\
       if (!gfc_option.gfc_flag_openmp)				\
 	;							\
+      else if (spec_only && gfc_match (keyword) == MATCH_YES)	\
+	goto do_spec_only;					\
+      else if (match_word (keyword, subr, &old_locus)		\
+	       == MATCH_YES)					\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
+/* Like match, but set a flag simd_matched if keyword matched.  */
+#define matchds(keyword, subr, st)				\
+    do {							\
+      if (match_word_omp_simd (keyword, subr, &old_locus,	\
+			       &simd_matched) == MATCH_YES)	\
+	return st;						\
+      else							\
+	undo_new_statement ();				  	\
+    } while (0);
+
+/* Like match, but don't match anything if not -fopenmp.  */
+#define matchdo(keyword, subr, st)				\
+    do {							\
+      if (!gfc_option.gfc_flag_openmp)				\
+	;							\
       else if (match_word (keyword, subr, &old_locus)		\
 	       == MATCH_YES)					\
 	return st;						\
@@ -587,6 +615,7 @@ decode_omp_directive (void)
   locus old_locus;
   char c;
   bool simd_matched = false;
+  bool spec_only = false;
 
   gfc_enforce_clean_symbol_state ();
 
@@ -601,6 +630,10 @@ decode_omp_directive (void)
       return ST_NONE;
     }
 
+  if (gfc_current_state () == COMP_FUNCTION
+      && gfc_current_block ()->result->ts.kind == -1)
+    spec_only = true;
+
   gfc_unset_implicit_pure (NULL);
 
   old_locus = gfc_current_locus;
@@ -629,12 +662,12 @@ decode_omp_directive (void)
       matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
       break;
     case 'd':
-      matchs ("declare reduction", gfc_match_omp_declare_reduction,
-	      ST_OMP_DECLARE_REDUCTION);
-      matchs ("declare simd", gfc_match_omp_declare_simd,
-	      ST_OMP_DECLARE_SIMD);
-      matcho ("declare target", gfc_match_omp_declare_target,
-	      ST_OMP_DECLARE_TARGET);
+      matchds ("declare reduction", gfc_match_omp_declare_reduction,
+	       ST_OMP_DECLARE_REDUCTION);
+      matchds ("declare simd", gfc_match_omp_declare_simd,
+	       ST_OMP_DECLARE_SIMD);
+      matchdo ("declare target", gfc_match_omp_declare_target,
+	       ST_OMP_DECLARE_TARGET);
       matchs ("distribute parallel do simd",
 	      gfc_match_omp_distribute_parallel_do_simd,
 	      ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD);
@@ -754,8 +787,8 @@ decode_omp_directive (void)
       matcho ("teams distribute", gfc_match_omp_teams_distribute,
 	      ST_OMP_TEAMS_DISTRIBUTE);
       matcho ("teams", gfc_match_omp_teams, ST_OMP_TEAMS);
-      matcho ("threadprivate", gfc_match_omp_threadprivate,
-	      ST_OMP_THREADPRIVATE);
+      matchdo ("threadprivate", gfc_match_omp_threadprivate,
+	       ST_OMP_THREADPRIVATE);
       break;
     case 'w':
       matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE);
@@ -778,6 +811,13 @@ decode_omp_directive (void)
   gfc_error_recovery ();
 
   return ST_NONE;
+
+ do_spec_only:
+  reject_statement ();
+  gfc_clear_error ();
+  gfc_buffer_error (false);
+  gfc_current_locus = old_locus;
+  return ST_GET_FCN_CHARACTERISTICS;
 }
 
 static gfc_statement
@@ -1126,10 +1166,13 @@ next_statement (void)
 
   gfc_buffer_error (0);
 
-  if (st == ST_GET_FCN_CHARACTERISTICS && gfc_statement_label != NULL)
+  if (st == ST_GET_FCN_CHARACTERISTICS)
     {
-      gfc_free_st_label (gfc_statement_label);
-      gfc_statement_label = NULL;
+      if (gfc_statement_label != NULL)
+	{
+	  gfc_free_st_label (gfc_statement_label);
+	  gfc_statement_label = NULL;
+	}
       gfc_current_locus = old_locus;
     }
 
--- gcc/testsuite/gfortran.dg/gomp/pr71704.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr71704.f90	(revision 237942)
@@ -0,0 +1,58 @@
+! PR fortran/71704
+! { dg-do compile }
+
+real function f0 ()
+!$omp declare simd (f0)
+  f0 = 1
+end
+
+real function f1 ()
+!$omp declare target (f1)
+  f1 = 1
+end
+
+real function f2 ()
+!$omp declare reduction (foo : integer : omp_out = omp_out + omp_in) &
+!$omp & initializer (omp_priv = 0)
+  f2 = 1
+end
+
+real function f3 ()
+  real, save :: t
+!$omp threadprivate (t)
+  f3 = 1
+end
+
+real function f4 ()
+!$omp taskwait
+  f4 = 1
+end
+
+real function f5 ()
+!$omp barrier
+  f5 = 1
+end
+
+real function f6 ()
+!$omp parallel
+!$omp end parallel
+  f6 = 1
+end
+
+real function f7 ()
+!$omp single
+!$omp end single
+  f7 = 1
+end
+
+real function f8 ()
+!$omp critical
+!$omp end critical
+  f8 = 1
+end
+
+real function f9 ()
+!$omp critical
+!$omp end critical
+  f9 = 1
+end
2016-07-07  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-07-01  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/71717
	* trans-openmp.c (gfc_omp_privatize_by_reference): Return false
	for GFC_DECL_ASSOCIATE_VAR_P with POINTER_TYPE.

	* testsuite/libgomp.fortran/associate3.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 237942)
+++ gcc/fortran/trans-openmp.c	(revision 237943)
@@ -61,6 +61,7 @@ gfc_omp_privatize_by_reference (const_tr
       if (GFC_DECL_GET_SCALAR_POINTER (decl)
 	  || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
 	  || GFC_DECL_CRAY_POINTEE (decl)
+	  || GFC_DECL_ASSOCIATE_VAR_P (decl)
 	  || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
 	return false;
 
--- libgomp/testsuite/libgomp.fortran/associate3.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/associate3.f90	(revision 237943)
@@ -0,0 +1,20 @@
+! PR fortran/71717
+! { dg-do run }
+
+  type t
+    real, allocatable :: f(:)
+  end type
+  type (t) :: v
+  integer :: i, j
+  allocate (v%f(4))
+  v%f = 19.
+  i = 5
+  associate (u => v, k => i)
+  !$omp parallel do
+  do j = 1, 4
+    u%f(j) = 21.
+    if (j.eq.1) k = 7
+  end do
+  end associate
+  if (any (v%f(:).ne.21.) .or. i.ne.7) call abort
+end
diff mbox

Patch

--- gcc/tree-cfg.c	(revision 218667)
+++ gcc/tree-cfg.c	(revision 218668)
@@ -1719,7 +1719,8 @@  replace_uses_by (tree name, tree val)
 	  if (gimple_code (stmt) == GIMPLE_PHI)
 	    {
 	      e = gimple_phi_arg_edge (stmt, PHI_ARG_INDEX_FROM_USE (use));
-	      if (e->flags & EDGE_ABNORMAL)
+	      if (e->flags & EDGE_ABNORMAL
+		  && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val))
 		{
 		  /* This can only occur for virtual operands, since
 		     for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
--- gcc/testsuite/g++.dg/torture/pr64280.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr64280.C	(revision 218668)
@@ -0,0 +1,42 @@ 
+// { dg-do compile }
+
+class A
+{
+public:
+  A ();
+};
+class B
+{
+public:
+  B (int);
+  operator void *() { return m_fn1 () ? 0 : this; }
+  int m_fn1 ();
+};
+typedef int jmp_buf[];
+struct C
+{
+  jmp_buf cond_;
+};
+class F
+{
+  C what_;
+  bool m_fn2 ();
+};
+int _setjmp (int[]);
+void longjmp ();
+class D
+{
+public:
+  D () { longjmp (); }
+};
+bool
+F::m_fn2 ()
+{
+  B a (0);
+  if (a)
+    if (_setjmp (what_.cond_))
+      return 0;
+    else
+      D ();
+  A b;
+}