diff mbox series

Backports to 8.x branch

Message ID 20180530073955.GM14160@tucnak
State New
Headers show
Series Backports to 8.x branch | expand

Commit Message

Jakub Jelinek May 30, 2018, 7:39 a.m. UTC
Hi!

I've backported a couple of patches to 8.x, after bootstrapping/regtesting
them there:

	Jakub
2018-05-30  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/85683
	* config/i386/i386.md: Add peepholes for mem {+,-,&,|,^}= x; mem != 0
	after cmpelim optimization.

	* gcc.target/i386/pr49095.c: Add -masm=att to dg-options.  Add
	scan-assembler-times checking that except for [fh]*xor other functions
	don't use any load instructions.
2018-05-30  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/85662
	* c-common.h (fold_offsetof_1): Removed.
	(fold_offsetof): Add TYPE argument defaulted to size_type_node and
	CTX argument defaulted to ERROR_MARK.
	* c-common.c (fold_offsetof_1): Renamed to ...
	(fold_offsetof): ... this.  Remove wrapper function.  Add TYPE
	argument, convert the pointer constant to TYPE and use size_binop
	with PLUS_EXPR instead of fold_build_pointer_plus if type is not
	a pointer type.  Adjust recursive calls.

	* c-fold.c (c_fully_fold_internal): Use fold_offsetof rather than
	fold_offsetof_1, pass TREE_TYPE (expr) as TYPE to it and drop the
	fold_convert_loc.
	* c-typeck.c (build_unary_op): Use fold_offsetof rather than
	fold_offsetof_1, pass argtype as TYPE to it and drop the
	fold_convert_loc.

	* cp-gimplify.c (cp_fold): Use fold_offsetof rather than
	fold_offsetof_1, pass TREE_TYPE (x) as TYPE to it and drop the
	fold_convert.

	* g++.dg/ext/offsetof2.C: New test.

--- gcc/c-family/c-common.c	(revision 260118)
+++ gcc/c-family/c-common.c	(revision 260119)
@@ -6168,10 +6168,11 @@ c_common_to_target_charset (HOST_WIDE_IN
 
 /* Fold an offsetof-like expression.  EXPR is a nested sequence of component
    references with an INDIRECT_REF of a constant at the bottom; much like the
-   traditional rendering of offsetof as a macro.  Return the folded result.  */
+   traditional rendering of offsetof as a macro.  TYPE is the desired type of
+   the whole expression.  Return the folded result.  */
 
 tree
-fold_offsetof_1 (tree expr, enum tree_code ctx)
+fold_offsetof (tree expr, tree type, enum tree_code ctx)
 {
   tree base, off, t;
   tree_code code = TREE_CODE (expr);
@@ -6196,10 +6197,10 @@ fold_offsetof_1 (tree expr, enum tree_co
 	  error ("cannot apply %<offsetof%> to a non constant address");
 	  return error_mark_node;
 	}
-      return TREE_OPERAND (expr, 0);
+      return convert (type, TREE_OPERAND (expr, 0));
 
     case COMPONENT_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code);
+      base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
       if (base == error_mark_node)
 	return base;
 
@@ -6216,7 +6217,7 @@ fold_offsetof_1 (tree expr, enum tree_co
       break;
 
     case ARRAY_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code);
+      base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
       if (base == error_mark_node)
 	return base;
 
@@ -6273,23 +6274,16 @@ fold_offsetof_1 (tree expr, enum tree_co
       /* Handle static members of volatile structs.  */
       t = TREE_OPERAND (expr, 1);
       gcc_checking_assert (VAR_P (get_base_address (t)));
-      return fold_offsetof_1 (t);
+      return fold_offsetof (t, type);
 
     default:
       gcc_unreachable ();
     }
 
+  if (!POINTER_TYPE_P (type))
+    return size_binop (PLUS_EXPR, base, convert (type, off));
   return fold_build_pointer_plus (base, off);
 }
-
-/* Likewise, but convert it to the return type of offsetof.  */
-
-tree
-fold_offsetof (tree expr)
-{
-  return convert (size_type_node, fold_offsetof_1 (expr));
-}
-
 
 /* *PTYPE is an incomplete array.  Complete it with a domain based on
    INITIAL_VALUE.  If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
--- gcc/c-family/c-common.h	(revision 260118)
+++ gcc/c-family/c-common.h	(revision 260119)
@@ -1033,8 +1033,8 @@ extern bool c_dump_tree (void *, tree);
 
 extern void verify_sequence_points (tree);
 
-extern tree fold_offsetof_1 (tree, tree_code ctx = ERROR_MARK);
-extern tree fold_offsetof (tree);
+extern tree fold_offsetof (tree, tree = size_type_node,
+			   tree_code ctx = ERROR_MARK);
 
 extern int complete_array_type (tree *, tree, bool);
 
--- gcc/c/c-fold.c	(revision 260118)
+++ gcc/c/c-fold.c	(revision 260119)
@@ -473,7 +473,7 @@ c_fully_fold_internal (tree expr, bool i
 	  && (op1 = get_base_address (op0)) != NULL_TREE
 	  && INDIRECT_REF_P (op1)
 	  && TREE_CONSTANT (TREE_OPERAND (op1, 0)))
-	ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
+	ret = fold_offsetof (op0, TREE_TYPE (expr));
       else if (op0 != orig_op0 || in_init)
 	ret = in_init
 	  ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
--- gcc/c/c-typeck.c	(revision 260118)
+++ gcc/c/c-typeck.c	(revision 260119)
@@ -4676,7 +4676,7 @@ build_unary_op (location_t location, enu
       if (val && INDIRECT_REF_P (val)
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
 	{
-	  ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
+	  ret = fold_offsetof (arg, argtype);
 	  goto return_build_unary_op;
 	}
 
--- gcc/cp/cp-gimplify.c	(revision 260118)
+++ gcc/cp/cp-gimplify.c	(revision 260119)
@@ -2232,7 +2232,7 @@ cp_fold (tree x)
 	      val = TREE_OPERAND (val, 0);
 	      STRIP_NOPS (val);
 	      if (TREE_CODE (val) == INTEGER_CST)
-		return fold_convert (TREE_TYPE (x), fold_offsetof_1 (op0));
+		return fold_offsetof (op0, TREE_TYPE (x));
 	    }
 	}
       goto finish_unary;
--- gcc/testsuite/g++.dg/ext/offsetof2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ext/offsetof2.C	(revision 260119)
@@ -0,0 +1,6 @@
+// PR c++/85662
+// { dg-do compile { target c++11 } }
+
+struct S { unsigned long x[31]; };
+struct T { bool b; S f; };
+static_assert (__builtin_offsetof (T, f.x[31 - 1]) == __builtin_offsetof (T, f.x[30]), "");
2018-05-30  Jakub Jelinek  <jakub@redhat.com>

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

	PR c/85696
	* c-omp.c (c_omp_predetermined_sharing): Return
	OMP_CLAUSE_DEFAULT_SHARED for artificial vars with integral type.

	* cp-tree.h (cxx_omp_predetermined_sharing_1): New prototype.
	* cp-gimplify.c (cxx_omp_predetermined_sharing): New wrapper around
	cxx_omp_predetermined_sharing_1.  Rename old function to ...
	(cxx_omp_predetermined_sharing_1): ... this.
	* semantics.c (finish_omp_clauses): Use cxx_omp_predetermined_sharing_1
	instead of cxx_omp_predetermined_sharing.

	* c-c++-common/gomp/pr85696.c: New test.

--- gcc/c-family/c-omp.c	(revision 260155)
+++ gcc/c-family/c-omp.c	(revision 260156)
@@ -1611,5 +1611,13 @@ c_omp_predetermined_sharing (tree decl)
   if (TREE_READONLY (decl))
     return OMP_CLAUSE_DEFAULT_SHARED;
 
+  /* Predetermine artificial variables holding integral values, those
+     are usually result of gimplify_one_sizepos or SAVE_EXPR
+     gimplification.  */
+  if (VAR_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+    return OMP_CLAUSE_DEFAULT_SHARED;
+
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
--- gcc/cp/cp-gimplify.c	(revision 260155)
+++ gcc/cp/cp-gimplify.c	(revision 260156)
@@ -1957,7 +1957,7 @@ cxx_omp_const_qual_no_mutable (tree decl
 /* True if OpenMP sharing attribute of DECL is predetermined.  */
 
 enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+cxx_omp_predetermined_sharing_1 (tree decl)
 {
   /* Static data members are predetermined shared.  */
   if (TREE_STATIC (decl))
@@ -1973,6 +1973,32 @@ cxx_omp_predetermined_sharing (tree decl
     return OMP_CLAUSE_DEFAULT_SHARED;
 
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+}
+
+/* Likewise, but also include the artificial vars.  We don't want to
+   disallow the artificial vars being mentioned in explicit clauses,
+   as we use artificial vars e.g. for loop constructs with random
+   access iterators other than pointers, but during gimplification
+   we want to treat them as predetermined.  */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+  enum omp_clause_default_kind ret = cxx_omp_predetermined_sharing_1 (decl);
+  if (ret != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+    return ret;
+
+  /* Predetermine artificial variables holding integral values, those
+     are usually result of gimplify_one_sizepos or SAVE_EXPR
+     gimplification.  */
+  if (VAR_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && INTEGRAL_TYPE_P (TREE_TYPE (decl))
+      && !(DECL_LANG_SPECIFIC (decl)
+	   && DECL_OMP_PRIVATIZED_MEMBER (decl)))
+    return OMP_CLAUSE_DEFAULT_SHARED;
+
+  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
 
 /* Finalize an implicitly determined clause.  */
--- gcc/cp/semantics.c	(revision 260155)
+++ gcc/cp/semantics.c	(revision 260156)
@@ -7297,7 +7297,7 @@ finish_omp_clauses (tree clauses, enum c
 
 	  if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
 	    share_name = "threadprivate";
-	  else switch (cxx_omp_predetermined_sharing (t))
+	  else switch (cxx_omp_predetermined_sharing_1 (t))
 	    {
 	    case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
 	      break;
--- gcc/cp/cp-tree.h	(revision 260155)
+++ gcc/cp/cp-tree.h	(revision 260156)
@@ -7383,6 +7383,7 @@ extern int cp_gimplify_expr			(tree *, g
 						 gimple_seq *);
 extern void cp_genericize			(tree);
 extern bool cxx_omp_const_qual_no_mutable	(tree);
+extern enum omp_clause_default_kind cxx_omp_predetermined_sharing_1 (tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
 extern tree cxx_omp_clause_default_ctor		(tree, tree, tree);
 extern tree cxx_omp_clause_copy_ctor		(tree, tree, tree);
--- gcc/testsuite/c-c++-common/gomp/pr85696.c	(nonexistent)
+++ gcc/testsuite/c-c++-common/gomp/pr85696.c	(revision 260156)
@@ -0,0 +1,20 @@
+/* PR c/85696 */
+
+#ifndef __cplusplus
+void
+foo (int n, int a[][n])
+{
+  #pragma omp parallel shared(a) default(none)
+  #pragma omp master
+    a[23][0] = 42;
+}
+#endif
+
+void
+bar (int n, void *p)
+{
+  int (*a)[n] = (int (*)[n]) p;
+  #pragma omp parallel shared(a) default(none)
+  #pragma omp master
+    a[23][0] = 42;
+}
2018-05-30  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/85756
	* config/i386/i386.md: Disallow non-commutative arithmetics in
	last twpeephole for mem {+,-,&,|,^}= x; mem != 0 after cmpelim
	optimization.  Use COMMUTATIVE_ARITH_P test rather than != MINUS
	in the peephole2 before it.

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

--- gcc/config/i386/i386.md	(revision 260230)
+++ gcc/config/i386/i386.md	(revision 260231)
@@ -19370,7 +19370,7 @@ (define_peephole2
    (set (match_dup 1) (match_dup 0))
    (set (reg FLAGS_REG) (compare (match_dup 0) (const_int 0)))]
   "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
-   && GET_CODE (operands[2]) != MINUS
+   && COMMUTATIVE_ARITH_P (operands[2])
    && peep2_reg_dead_p (3, operands[0])
    && !reg_overlap_mentioned_p (operands[0], operands[1])
    && ix86_match_ccmode (peep2_next_insn (2),
@@ -19400,11 +19400,11 @@ (define_peephole2
 	      (set (match_dup 0) (match_dup 2))])
    (set (match_dup 1) (match_dup 0))]
   "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && COMMUTATIVE_ARITH_P (operands[2])
    && peep2_reg_dead_p (2, operands[0])
    && !reg_overlap_mentioned_p (operands[0], operands[1])
    && ix86_match_ccmode (peep2_next_insn (0),
-			 (GET_CODE (operands[2]) == PLUS
-			  || GET_CODE (operands[2]) == MINUS)
+			 GET_CODE (operands[2]) == PLUS
 			 ? CCGOCmode : CCNOmode)"
   [(parallel [(set (match_dup 3) (match_dup 5))
 	      (set (match_dup 1) (match_dup 4))])]
--- gcc/testsuite/gcc.c-torture/execute/pr85756.c	(nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr85756.c	(revision 260231)
@@ -0,0 +1,50 @@
+/* PR target/85756 */
+
+#if __CHAR_BIT__ == 8 && __SIZEOF_SHORT__ == 2 && __SIZEOF_INT__ == 4
+int a, c, *e, f, h = 10;
+short b;
+unsigned int p;
+
+__attribute__((noipa)) void
+bar (int a)
+{
+  asm volatile ("" : : "r" (a) : "memory");
+}
+
+void
+foo ()
+{
+  unsigned j = 1, m = 430523;
+  int k, n = 1, *l = &h;
+lab:
+  p = m;
+  m = -((~65535U | j) - n);
+  f = b << ~(n - 8);
+  n = (m || b) ^ f;
+  j = p;
+  if (p < m)
+    *l = k < 3;
+  if (!n)
+    l = &k;
+  if (c)
+    {
+      bar (a);
+      goto lab;
+    }
+  if (!*l)
+    *e = 1;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+#else
+int
+main ()
+{
+  return 0;
+}
+#endif
2018-05-30  Jakub Jelinek  <jakub@redhat.com>

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

	PR c++/85952
	* init.c (build_aggr_init): For structured binding initialized from
	array call mark_rvalue_use on the initializer.

	* g++.dg/warn/Wunused-var-33.C: New test.

--- gcc/cp/init.c	(revision 260898)
+++ gcc/cp/init.c	(revision 260899)
@@ -1678,6 +1678,7 @@ build_aggr_init (tree exp, tree init, in
       if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp))
 	{
 	  from_array = 1;
+	  init = mark_rvalue_use (init);
 	  if (init && DECL_P (init)
 	      && !(flags & LOOKUP_ONLYCONVERTING))
 	    {
--- gcc/testsuite/g++.dg/warn/Wunused-var-33.C	(nonexistent)
+++ gcc/testsuite/g++.dg/warn/Wunused-var-33.C	(revision 260899)
@@ -0,0 +1,37 @@
+// PR c++/85952
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused-but-set-variable" }
+
+int
+foo ()
+{
+  int a[2] = {1, 2};	// { dg-bogus "set but not used" } */
+  auto [x, y] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return x + y;
+}
+
+struct S { int d, e; };
+
+int
+bar ()
+{
+  S a = {1, 2};
+  auto [x, y] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return x + y;
+}
+
+int
+baz ()
+{
+  S a = {1, 2};
+  auto & [x, y] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return x + y;
+}
+
+int
+qux ()
+{
+  int a[2] = {1, 2};
+  auto & [x, y] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
+  return x + y;
+}
diff mbox series

Patch

--- gcc/config/i386/i386.md	(revision 260044)
+++ gcc/config/i386/i386.md	(revision 260045)
@@ -19286,6 +19286,37 @@  (define_peephole2
 		       const0_rtx);
 })
 
+;; Likewise for cmpelim optimized pattern.
+(define_peephole2
+  [(set (match_operand:SWI 0 "register_operand")
+	(match_operand:SWI 1 "memory_operand"))
+   (parallel [(set (reg FLAGS_REG)
+		   (compare (match_operator:SWI 3 "plusminuslogic_operator"
+			      [(match_dup 0)
+			       (match_operand:SWI 2 "<nonmemory_operand>")])
+			    (const_int 0)))
+	      (set (match_dup 0) (match_dup 3))])
+   (set (match_dup 1) (match_dup 0))]
+  "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (3, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && !reg_overlap_mentioned_p (operands[0], operands[2])
+   && ix86_match_ccmode (peep2_next_insn (1),
+			 (GET_CODE (operands[3]) == PLUS
+			  || GET_CODE (operands[3]) == MINUS)
+			 ? CCGOCmode : CCNOmode)"
+  [(parallel [(set (match_dup 4) (match_dup 6))
+	      (set (match_dup 1) (match_dup 5))])]
+{
+  operands[4] = SET_DEST (XVECEXP (PATTERN (peep2_next_insn (1)), 0, 0));
+  operands[5]
+    = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
+		      copy_rtx (operands[1]), operands[2]);
+  operands[6]
+    = gen_rtx_COMPARE (GET_MODE (operands[4]), copy_rtx (operands[5]),
+		       const0_rtx);
+})
+
 ;; Likewise for instances where we have a lea pattern.
 (define_peephole2
   [(set (match_operand:SWI 0 "register_operand")
@@ -19349,6 +19380,34 @@  (define_peephole2
 		       const0_rtx);
 })
 
+;; Likewise for cmpelim optimized pattern.
+(define_peephole2
+  [(parallel [(set (reg FLAGS_REG)
+		   (compare (match_operator:SWI 2 "plusminuslogic_operator"
+			      [(match_operand:SWI 0 "register_operand")
+			       (match_operand:SWI 1 "memory_operand")])
+			    (const_int 0)))
+	      (set (match_dup 0) (match_dup 2))])
+   (set (match_dup 1) (match_dup 0))]
+  "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (2, operands[0])
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && ix86_match_ccmode (peep2_next_insn (0),
+			 (GET_CODE (operands[2]) == PLUS
+			  || GET_CODE (operands[2]) == MINUS)
+			 ? CCGOCmode : CCNOmode)"
+  [(parallel [(set (match_dup 3) (match_dup 5))
+	      (set (match_dup 1) (match_dup 4))])]
+{
+  operands[3] = SET_DEST (XVECEXP (PATTERN (peep2_next_insn (0)), 0, 0));
+  operands[4]
+    = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+		      copy_rtx (operands[1]), operands[0]);
+  operands[5]
+    = gen_rtx_COMPARE (GET_MODE (operands[3]), copy_rtx (operands[4]),
+		       const0_rtx);
+})
+
 (define_peephole2
   [(set (match_operand:SWI12 0 "register_operand")
 	(match_operand:SWI12 1 "memory_operand"))
--- gcc/testsuite/gcc.target/i386/pr49095.c	(revision 260044)
+++ gcc/testsuite/gcc.target/i386/pr49095.c	(revision 260045)
@@ -1,6 +1,6 @@ 
 /* PR rtl-optimization/49095 */
 /* { dg-do compile } */
-/* { dg-options "-Os -fno-shrink-wrap" } */
+/* { dg-options "-Os -fno-shrink-wrap -masm=att" } */
 /* { dg-additional-options "-mregparm=2" { target ia32 } } */
 
 void foo (void *);
@@ -71,3 +71,6 @@  G (int)
 G (long)
 
 /* { dg-final { scan-assembler-not "test\[lq\]" } } */
+/* The {f,h}{char,short,int,long}xor functions aren't optimized into
+   a RMW instruction, so need load, modify and store.  FIXME eventually.  */
+/* { dg-final { scan-assembler-times "\\), %" 8 } } */