[committed] Backports to 6.x branch

Jakub Jelinek jakub@redhat.com
Thu Sep 1 11:52:00 GMT 2016


Hi!

I've committed following backports of some trunk fixes,
after bootstrapping/regtesting them on x86_64-linux and i686-linux.

	Jakub
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR target/71910
	* tree-cfg.c (execute_fixup_cfg): Add node variable, use it.  Before inlining,
	add cgraph edge for the added __builtin_unreachable call.

	* g++.dg/gomp/pr71910.C: New test.

--- gcc/tree-cfg.c	(revision 239507)
+++ gcc/tree-cfg.c	(revision 239508)
@@ -8987,16 +8987,14 @@ execute_fixup_cfg (void)
   gcov_type count_scale;
   edge e;
   edge_iterator ei;
+  cgraph_node *node = cgraph_node::get (current_function_decl);
 
   count_scale
-      = GCOV_COMPUTE_SCALE (cgraph_node::get (current_function_decl)->count,
-			    ENTRY_BLOCK_PTR_FOR_FN (cfun)->count);
+    = GCOV_COMPUTE_SCALE (node->count, ENTRY_BLOCK_PTR_FOR_FN (cfun)->count);
 
-  ENTRY_BLOCK_PTR_FOR_FN (cfun)->count =
-			    cgraph_node::get (current_function_decl)->count;
-  EXIT_BLOCK_PTR_FOR_FN (cfun)->count =
-			    apply_scale (EXIT_BLOCK_PTR_FOR_FN (cfun)->count,
-                                       count_scale);
+  ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count;
+  EXIT_BLOCK_PTR_FOR_FN (cfun)->count
+    = apply_scale (EXIT_BLOCK_PTR_FOR_FN (cfun)->count, count_scale);
 
   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     e->count = apply_scale (e->count, count_scale);
@@ -9089,10 +9087,19 @@ execute_fixup_cfg (void)
 	    {
 	      if (stmt && is_gimple_call (stmt))
 		gimple_call_set_ctrl_altering (stmt, false);
-	      stmt = gimple_build_call
-		  (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
+	      tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+	      stmt = gimple_build_call (fndecl, 0);
 	      gimple_stmt_iterator gsi = gsi_last_bb (bb);
 	      gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+	      if (!cfun->after_inlining)
+		{
+		  gcall *call_stmt = dyn_cast <gcall *> (stmt);
+		  int freq
+		    = compute_call_stmt_bb_frequency (current_function_decl,
+						      bb);
+		  node->create_edge (cgraph_node::get_create (fndecl),
+				     call_stmt, bb->count, freq);
+		}
 	    }
 	}
     }
--- gcc/testsuite/g++.dg/gomp/pr71910.C	(revision 0)
+++ gcc/testsuite/g++.dg/gomp/pr71910.C	(revision 239508)
@@ -0,0 +1,13 @@
+// PR target/71910
+// { dg-do compile }
+// { dg-additional-options "-O2" }
+
+#include <vector>
+
+int
+main ()
+{
+  std::vector<double> vec(10);
+#pragma omp parallel
+  __builtin_exit (0);
+}
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR middle-end/77259
	* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): If
	turning a call into __builtin_unreachable-like noreturn call, adjust
	gimple_call_set_fntype.
	* tree-cfgcleanup.c (fixup_noreturn_call): Remove lhs also if
	gimple_call_fntype has void return type.

	* g++.dg/ipa/devirt-52.C: New test.

--- gcc/tree-cfgcleanup.c	(revision 239536)
+++ gcc/tree-cfgcleanup.c	(revision 239537)
@@ -602,10 +602,15 @@ fixup_noreturn_call (gimple *stmt)
   /* If there is an LHS, remove it, but only if its type has fixed size.
      The LHS will need to be recreated during RTL expansion and creating
      temporaries of variable-sized types is not supported.  Also don't
-     do this with TREE_ADDRESSABLE types, as assign_temp will abort.  */
+     do this with TREE_ADDRESSABLE types, as assign_temp will abort.
+     Drop LHS regardless of TREE_ADDRESSABLE, if the function call
+     has been changed into a call that does not return a value, like
+     __builtin_unreachable or __cxa_pure_virtual.  */
   tree lhs = gimple_call_lhs (stmt);
-  if (lhs && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST
-      && !TREE_ADDRESSABLE (TREE_TYPE (lhs)))
+  if (lhs
+      && ((TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST
+	   && !TREE_ADDRESSABLE (TREE_TYPE (lhs)))
+	  || VOID_TYPE_P (TREE_TYPE (gimple_call_fntype (stmt)))))
     {
       gimple_call_set_lhs (stmt, NULL_TREE);
 
--- gcc/tree-ssa-pre.c	(revision 239536)
+++ gcc/tree-ssa-pre.c	(revision 239537)
@@ -4543,6 +4543,15 @@ eliminate_dom_walker::before_dom_childre
 				       lang_hooks.decl_printable_name (fn, 2));
 		    }
 		  gimple_call_set_fndecl (call_stmt, fn);
+		  /* If changing the call to __builtin_unreachable
+		     or similar noreturn function, adjust gimple_call_fntype
+		     too.  */
+		  if (gimple_call_noreturn_p (call_stmt)
+		      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
+		      && TYPE_ARG_TYPES (TREE_TYPE (fn))
+		      && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fn)))
+			  == void_type_node))
+		    gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));
 		  maybe_remove_unused_call_args (cfun, call_stmt);
 		  gimple_set_modified (stmt, true);
 		}
--- gcc/testsuite/g++.dg/ipa/devirt-52.C	(revision 0)
+++ gcc/testsuite/g++.dg/ipa/devirt-52.C	(revision 239537)
@@ -0,0 +1,56 @@
+// PR middle-end/77259
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+template <typename, typename = int> class A;
+template <typename, typename> struct A
+{
+  A (A &&);
+};
+template <typename S, typename T, typename U>
+A<S> operator+(S *, const A<T, U> &);
+template <typename S, typename T, typename U>
+void operator+(const A<T, U> &, S *);
+struct B
+{
+  template <typename V> B (V);
+};
+template <typename V> V foo (B) {}
+class C;
+template <typename> struct D
+{
+  C *operator->() { return d; }
+  C *d;
+};
+struct C
+{
+  virtual A<int> bar ();
+};
+struct E
+{
+  ~E ();
+  virtual A<char> bar (const B &) const;
+};
+template <typename> struct F : E
+{
+};
+template <typename W> struct F<D<W>> : E
+{
+  A<char> bar (const B &) const try
+    {
+      D<W> a = baz ();
+    }
+  catch (int)
+    {
+    }
+  D<W> baz () const
+  {
+    D<C> b = foo<D<C>>(0);
+    "" + b->bar () + "";
+  }
+};
+struct G : F<D<int>>
+{
+  G (int);
+};
+void test () { G (0); }
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	* config/i386/t-i386 (i386-c.o): Don't depend on
	i386-builtin-types.inc.
	(i386.o): Depend on i386-builtin-types.inc.

--- gcc/config/i386/t-i386	(revision 239614)
+++ gcc/config/i386/t-i386	(revision 239615)
@@ -19,10 +19,12 @@
 OPTIONS_H_EXTRA += $(srcdir)/config/i386/stringop.def
 TM_H += $(srcdir)/config/i386/x86-tune.def
 
-i386-c.o: $(srcdir)/config/i386/i386-c.c i386-builtin-types.inc
+i386-c.o: $(srcdir)/config/i386/i386-c.c
 	  $(COMPILE) $<
 	  $(POSTCOMPILE)
 
+i386.o: i386-builtin-types.inc
+
 i386-builtin-types.inc: s-i386-bt ; @true
 s-i386-bt: $(srcdir)/config/i386/i386-builtin-types.awk \
   $(srcdir)/config/i386/i386-builtin-types.def
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/69281
	* trans-openmp.c (gfc_trans_omp_parallel, gfc_trans_omp_task,
	gfc_trans_omp_target): Wrap gfc_trans_omp_code result in an extra
	BIND_EXPR with its own forced BLOCK.

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

--- gcc/fortran/trans-openmp.c	(revision 239617)
+++ gcc/fortran/trans-openmp.c	(revision 239618)
@@ -3554,7 +3554,9 @@ gfc_trans_omp_parallel (gfc_code *code)
   gfc_start_block (&block);
   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
 				       code->loc);
+  pushlevel ();
   stmt = gfc_trans_omp_code (code->block->next, true);
+  stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
   stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
 		     omp_clauses);
   gfc_add_expr_to_block (&block, stmt);
@@ -4062,7 +4064,9 @@ gfc_trans_omp_task (gfc_code *code)
   gfc_start_block (&block);
   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
 				       code->loc);
+  pushlevel ();
   stmt = gfc_trans_omp_code (code->block->next, true);
+  stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
   stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
 		     omp_clauses);
   gfc_add_expr_to_block (&block, stmt);
@@ -4215,7 +4219,11 @@ gfc_trans_omp_target (gfc_code *code)
       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
 			       code->loc);
   if (code->op == EXEC_OMP_TARGET)
-    stmt = gfc_trans_omp_code (code->block->next, true);
+    {
+      pushlevel ();
+      stmt = gfc_trans_omp_code (code->block->next, true);
+      stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+    }
   else
     {
       pushlevel ();
--- gcc/testsuite/gfortran.dg/gomp/pr69281.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr69281.f90	(revision 239618)
@@ -0,0 +1,63 @@
+! PR fortran/69281
+! { dg-do compile }
+! { dg-additional-options "-fstack-arrays -O2" }
+
+program pr69281
+  implicit none
+  call foo1((/ 1, 3, 3, 7 /))
+  call foo2((/ 1, 3, 3, 7 /))
+  call foo3((/ 1, 3, 3, 7 /))
+  call foo4((/ 1, 3, 3, 7 /))
+  call foo5((/ 1, 3, 3, 7 /))
+  call foo6((/ 1, 3, 3, 7 /))
+contains
+  subroutine foo1(x)
+    integer, intent(in) :: x(:)
+    !$omp parallel
+      call baz(bar(x))
+    !$omp end parallel
+  end subroutine
+  subroutine foo2(x)
+    integer, intent(in) :: x(:)
+    !$omp task
+      call baz(bar(x))
+    !$omp end task
+  end subroutine
+  subroutine foo3(x)
+    integer, intent(in) :: x(:)
+    !$omp target
+      call baz(bar(x))
+    !$omp end target
+  end subroutine
+  subroutine foo4(x)
+    integer, intent(in) :: x(:)
+    !$omp target teams
+      call baz(bar(x))
+    !$omp end target teams
+  end subroutine
+  subroutine foo5(x)
+    integer, intent(in) :: x(:)
+    integer :: i
+    !$omp parallel do
+      do i = 1, 1
+        call baz(bar(x))
+      end do
+  end subroutine
+  subroutine foo6(x)
+    integer, intent(in) :: x(:)
+    integer :: i
+    !$omp target teams distribute parallel do
+      do i = 1, 1
+        call baz(bar(x))
+      end do
+  end subroutine
+  function bar(x) result(a)
+    integer, dimension(:), intent(in) :: x
+    integer, dimension(2,size(x)) :: a
+    a(1,:) = 1
+    a(2,:) = x
+  end function
+  subroutine baz(a)
+    integer, dimension(:,:), intent(in) :: a
+  end subroutine
+end program
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/72744
	* gfortran.dg/gomp/pr72744.f90: New test.

--- gcc/testsuite/gfortran.dg/gomp/pr72744.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr72744.f90	(revision 239619)
@@ -0,0 +1,18 @@
+! PR fortran/72744
+! { dg-do compile }
+! { dg-additional-options "-Ofast" }
+
+program pr72744
+  integer, parameter :: n = 20
+  integer :: i, z(n), h(n)
+  z = [(i, i=1,n)]
+  h = [(i, i=n,1,-1)]
+  call sub (n, h)
+  if ( any(h/=z) ) call abort
+end
+subroutine sub (n, x)
+  integer :: n, x(n)
+!$omp parallel
+  x(:) = x(n:1:-1)
+!$omp end parallel
+end
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR fortran/71014
	* resolve.c (gfc_resolve): For ns->construct_entities don't save, clear
	and restore omp state around the resolving.

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

--- gcc/fortran/resolve.c	(revision 239619)
+++ gcc/fortran/resolve.c	(revision 239620)
@@ -15587,7 +15587,8 @@ gfc_resolve (gfc_namespace *ns)
   /* As gfc_resolve can be called during resolution of an OpenMP construct
      body, we should clear any state associated to it, so that say NS's
      DO loops are not interpreted as OpenMP loops.  */
-  gfc_omp_save_and_clear_state (&old_omp_state);
+  if (!ns->construct_entities)
+    gfc_omp_save_and_clear_state (&old_omp_state);
 
   resolve_types (ns);
   component_assignment_level = 0;
@@ -15599,5 +15600,6 @@ gfc_resolve (gfc_namespace *ns)
 
   gfc_run_passes (ns);
 
-  gfc_omp_restore_state (&old_omp_state);
+  if (!ns->construct_entities)
+    gfc_omp_restore_state (&old_omp_state);
 }
--- libgomp/testsuite/libgomp.fortran/pr71014.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/pr71014.f90	(revision 239620)
@@ -0,0 +1,20 @@
+! PR fortran/71014
+! { dg-do run }
+! { dg-additional-options "-O0" }
+
+program pr71014
+  implicit none
+  integer :: i, j
+  integer, parameter :: t = 100*101/2
+  integer :: s(16)
+  s(:) = 0
+!$omp parallel do
+  do j = 1, 16
+    associate (k => j)
+      do i = 1, 100
+        s(j) = s(j) + i
+      end do
+    end associate
+  end do
+  if (any(s /= t)) call abort
+end program pr71014
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR middle-end/77377
	* simplify-rtx.c (avoid_constant_pool_reference): For out of bounds
	constant pool reference return x instead of c.

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

--- gcc/simplify-rtx.c	(revision 239853)
+++ gcc/simplify-rtx.c	(revision 239854)
@@ -251,15 +251,14 @@ avoid_constant_pool_reference (rtx x)
       /* If we're accessing the constant in a different mode than it was
          originally stored, attempt to fix that up via subreg simplifications.
          If that fails we have no choice but to return the original memory.  */
-      if ((offset != 0 || cmode != GET_MODE (x))
-	  && offset >= 0 && offset < GET_MODE_SIZE (cmode))
+      if (offset == 0 && cmode == GET_MODE (x))
+	return c;
+      else if (offset >= 0 && offset < GET_MODE_SIZE (cmode))
         {
           rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset);
           if (tem && CONSTANT_P (tem))
             return tem;
         }
-      else
-        return c;
     }
 
   return x;
--- gcc/testsuite/gcc.target/i386/pr77377.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr77377.c	(revision 239854)
@@ -0,0 +1,6 @@
+/* PR middle-end/77377 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse" } */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+#include "../../c-c++-common/pr59037.c"
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR debug/77363
	* dwarf2out.c (modified_type_die): Use lookup_type_die (type)
	instead of lookup_type_die (type_main_variant (type)) even for array
	types.

	* g++.dg/debug/dwarf2/pr77363.C: New test.

--- gcc/dwarf2out.c	(revision 239854)
+++ gcc/dwarf2out.c	(revision 239855)
@@ -11474,7 +11474,8 @@ modified_type_die (tree type, int cv_qua
 	 copy was created to help us keep track of typedef names) and
 	 that copy might have a different TYPE_UID from the original
 	 ..._TYPE node.  */
-      if (TREE_CODE (type) != VECTOR_TYPE)
+      if (TREE_CODE (type) != VECTOR_TYPE
+	  && TREE_CODE (type) != ARRAY_TYPE)
 	return lookup_type_die (type_main_variant (type));
       else
 	/* Vectors have the debugging information in the type,
--- gcc/testsuite/g++.dg/debug/dwarf2/pr77363.C	(revision 0)
+++ gcc/testsuite/g++.dg/debug/dwarf2/pr77363.C	(revision 239855)
@@ -0,0 +1,20 @@
+// PR debug/77363
+// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings" }
+// { dg-final { scan-assembler "DIE \\(\[^\n\r\]*\\) DW_TAG_typedef\[^\n\r\]*\[\n\r]*\[^\n\r\]*type2\[^\n\r\]* DW_AT_name\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_file\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_line\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_type" } }
+// { dg-final { scan-assembler "DIE \\(\[^\n\r\]*\\) DW_TAG_typedef\[^\n\r\]*\[\n\r]*\[^\n\r\]*type3\[^\n\r\]* DW_AT_name\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_file\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_line\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_type" } }
+// { dg-final { scan-assembler "DIE \\(\[^\n\r\]*\\) DW_TAG_typedef\[^\n\r\]*\[\n\r]*\[^\n\r\]*type4\[^\n\r\]* DW_AT_name\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_file\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_line\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_type" } }
+// { dg-final { scan-assembler "DIE \\(\[^\n\r\]*\\) DW_TAG_typedef\[^\n\r\]*\[\n\r]*\[^\n\r\]*type5\[^\n\r\]* DW_AT_name\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_file\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_decl_line\[^\n\r\]*\[\n\r]*\[^\n\r\]* DW_AT_type" } }
+
+typedef unsigned short type1;
+typedef unsigned char type2;
+typedef type2 type3[16];
+typedef unsigned char type4[16];
+typedef struct
+{
+  struct
+  {
+    type3 a;
+    type4 b;
+  } c;
+} type5;
+type5 var;
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

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

	PR tree-optimization/72866
	* tree-vect-patterns.c (search_type_for_mask): Turn into
	a small wrapper, move all code to ...
	(search_type_for_mask_1): ... this new function.  Add caching
	and adjust recursive calls.

	* gcc.dg/vect/pr72866.c: New test.

--- gcc/tree-vect-patterns.c	(revision 239855)
+++ gcc/tree-vect-patterns.c	(revision 239856)
@@ -3459,13 +3459,11 @@ adjust_bool_stmts (hash_set <gimple *> &
   return gimple_assign_lhs (pattern_stmt);
 }
 
-/* Return the proper type for converting bool VAR into
-   an integer value or NULL_TREE if no such type exists.
-   The type is chosen so that converted value has the
-   same number of elements as VAR's vector type.  */
+/* Helper for search_type_for_mask.  */
 
 static tree
-search_type_for_mask (tree var, vec_info *vinfo)
+search_type_for_mask_1 (tree var, vec_info *vinfo,
+			hash_map<gimple *, tree> &cache)
 {
   gimple *def_stmt;
   enum vect_def_type dt;
@@ -3490,6 +3488,10 @@ search_type_for_mask (tree var, vec_info
   if (!is_gimple_assign (def_stmt))
     return NULL_TREE;
 
+  tree *c = cache.get (def_stmt);
+  if (c)
+    return *c;
+
   rhs_code = gimple_assign_rhs_code (def_stmt);
   rhs1 = gimple_assign_rhs1 (def_stmt);
 
@@ -3498,14 +3500,15 @@ search_type_for_mask (tree var, vec_info
     case SSA_NAME:
     case BIT_NOT_EXPR:
     CASE_CONVERT:
-      res = search_type_for_mask (rhs1, vinfo);
+      res = search_type_for_mask_1 (rhs1, vinfo, cache);
       break;
 
     case BIT_AND_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
-      res = search_type_for_mask (rhs1, vinfo);
-      res2 = search_type_for_mask (gimple_assign_rhs2 (def_stmt), vinfo);
+      res = search_type_for_mask_1 (rhs1, vinfo, cache);
+      res2 = search_type_for_mask_1 (gimple_assign_rhs2 (def_stmt), vinfo,
+				     cache);
       if (!res || (res2 && TYPE_PRECISION (res) > TYPE_PRECISION (res2)))
 	res = res2;
       break;
@@ -3517,8 +3520,9 @@ search_type_for_mask (tree var, vec_info
 
 	  if (TREE_CODE (TREE_TYPE (rhs1)) == BOOLEAN_TYPE)
 	    {
-	      res = search_type_for_mask (rhs1, vinfo);
-	      res2 = search_type_for_mask (gimple_assign_rhs2 (def_stmt), vinfo);
+	      res = search_type_for_mask_1 (rhs1, vinfo, cache);
+	      res2 = search_type_for_mask_1 (gimple_assign_rhs2 (def_stmt),
+					     vinfo, cache);
 	      if (!res || (res2 && TYPE_PRECISION (res) > TYPE_PRECISION (res2)))
 		res = res2;
 	      break;
@@ -3526,12 +3530,18 @@ search_type_for_mask (tree var, vec_info
 
 	  comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
 	  if (comp_vectype == NULL_TREE)
-	    return NULL_TREE;
+	    {
+	      res = NULL_TREE;
+	      break;
+	    }
 
 	  mask_type = get_mask_type_for_scalar_type (TREE_TYPE (rhs1));
 	  if (!mask_type
 	      || !expand_vec_cmp_expr_p (comp_vectype, mask_type))
-	    return NULL_TREE;
+	    {
+	      res = NULL_TREE;
+	      break;
+	    }
 
 	  if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
 	      || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
@@ -3544,9 +3554,21 @@ search_type_for_mask (tree var, vec_info
 	}
     }
 
+  cache.put (def_stmt, res);
   return res;
 }
 
+/* Return the proper type for converting bool VAR into
+   an integer value or NULL_TREE if no such type exists.
+   The type is chosen so that converted value has the
+   same number of elements as VAR's vector type.  */
+
+static tree
+search_type_for_mask (tree var, vec_info *vinfo)
+{
+  hash_map<gimple *, tree> cache;
+  return search_type_for_mask_1 (var, vinfo, cache);
+}
 
 /* Function vect_recog_bool_pattern
 
--- gcc/testsuite/gcc.dg/vect/pr72866.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vect/pr72866.c	(revision 239856)
@@ -0,0 +1,19 @@
+/* PR tree-optimization/72866 */
+/* { dg-do compile } */
+
+unsigned int dl;
+int rx, lb;
+
+void
+fo (int jv, int be)
+{
+  const unsigned int xw = 16;
+  unsigned int ya, wo;
+
+  for (ya = 0; ya < 2; ++ya)
+    for (wo = 0; wo < xw; ++wo)
+      {
+	dl += (jv ? be : rx);
+	rx += ((lb == 0) + 1);
+      }
+}
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-08-31  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/77374
	* parse.c (parse_omp_oacc_atomic): Copy over cp->ext.omp_atomic
	to cp->block->ext.omp_atomic.
	* resolve.c (gfc_resolve_blocks): Assert block with one or two
	EXEC_ASSIGNs for EXEC_*_ATOMIC.
	* openmp.c (resolve_omp_atomic): Don't assert one or two
	EXEC_ASSIGNs, instead return quietly for EXEC_NOPs and otherwise
	error unexpected statements.

	* gfortran.dg/gomp/pr77374.f08: New test.

--- gcc/fortran/openmp.c	(revision 239902)
+++ gcc/fortran/openmp.c	(revision 239903)
@@ -3946,12 +3946,33 @@ resolve_omp_atomic (gfc_code *code)
     = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
 
   code = code->block->next;
-  gcc_assert (code->op == EXEC_ASSIGN);
-  gcc_assert (((aop != GFC_OMP_ATOMIC_CAPTURE) && code->next == NULL)
-	      || ((aop == GFC_OMP_ATOMIC_CAPTURE)
-		  && code->next != NULL
-		  && code->next->op == EXEC_ASSIGN
-		  && code->next->next == NULL));
+  /* resolve_blocks asserts this is initially EXEC_ASSIGN.
+     If it changed to EXEC_NOP, assume an error has been emitted already.  */
+  if (code->op == EXEC_NOP)
+    return;
+  if (code->op != EXEC_ASSIGN)
+    {
+    unexpected:
+      gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
+      return;
+    }
+  if (aop != GFC_OMP_ATOMIC_CAPTURE)
+    {
+      if (code->next != NULL)
+	goto unexpected;
+    }
+  else
+    {
+      if (code->next == NULL)
+	goto unexpected;
+      if (code->next->op == EXEC_NOP)
+	return;
+      if (code->next->op != EXEC_ASSIGN || code->next->next)
+	{
+	  code = code->next;
+	  goto unexpected;
+	}
+    }
 
   if (code->expr1->expr_type != EXPR_VARIABLE
       || code->expr1->symtree == NULL
--- gcc/fortran/resolve.c	(revision 239902)
+++ gcc/fortran/resolve.c	(revision 239903)
@@ -9519,6 +9519,24 @@ gfc_resolve_blocks (gfc_code *b, gfc_nam
 	case EXEC_WAIT:
 	  break;
 
+	case EXEC_OMP_ATOMIC:
+	case EXEC_OACC_ATOMIC:
+	  {
+	    gfc_omp_atomic_op aop
+	      = (gfc_omp_atomic_op) (b->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
+
+	    /* Verify this before calling gfc_resolve_code, which might
+	       change it.  */
+	    gcc_assert (b->next && b->next->op == EXEC_ASSIGN);
+	    gcc_assert (((aop != GFC_OMP_ATOMIC_CAPTURE)
+			 && b->next->next == NULL)
+			|| ((aop == GFC_OMP_ATOMIC_CAPTURE)
+			    && b->next->next != NULL
+			    && b->next->next->op == EXEC_ASSIGN
+			    && b->next->next->next == NULL));
+	  }
+	  break;
+
 	case EXEC_OACC_PARALLEL_LOOP:
 	case EXEC_OACC_PARALLEL:
 	case EXEC_OACC_KERNELS_LOOP:
@@ -9531,9 +9549,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_nam
 	case EXEC_OACC_CACHE:
 	case EXEC_OACC_ENTER_DATA:
 	case EXEC_OACC_EXIT_DATA:
-	case EXEC_OACC_ATOMIC:
 	case EXEC_OACC_ROUTINE:
-	case EXEC_OMP_ATOMIC:
 	case EXEC_OMP_CRITICAL:
 	case EXEC_OMP_DISTRIBUTE:
 	case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
--- gcc/fortran/parse.c	(revision 239902)
+++ gcc/fortran/parse.c	(revision 239903)
@@ -4695,6 +4695,7 @@ parse_omp_oacc_atomic (bool omp_p)
   np = new_level (cp);
   np->op = cp->op;
   np->block = NULL;
+  np->ext.omp_atomic = cp->ext.omp_atomic;
   count = 1 + ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
 	       == GFC_OMP_ATOMIC_CAPTURE);
 
--- gcc/testsuite/gfortran.dg/gomp/pr77374.f08	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77374.f08	(revision 239903)
@@ -0,0 +1,21 @@
+! PR fortran/77374
+! { dg-do compile }
+
+subroutine foo (a, b)
+  integer :: a, b
+!$omp atomic
+  b = b + a
+!$omp atomic
+  z(1) = z(1) + 1	! { dg-error "must have the pointer attribute" }
+end subroutine
+subroutine bar (a, b)
+  integer :: a, b
+  interface
+    function baz (i) result (res)
+      integer, pointer :: res
+      integer :: i
+    end function
+  end interface
+!$omp atomic
+  baz (i) = 1		! { dg-error "unexpected" }
+end subroutine
-------------- next part --------------
2016-09-01  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2016-08-31  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/77352
	* trans-openmp.c (gfc_trans_omp_parallel_workshare): Always add a
	BIND_EXPR with BLOCK around what gfc_trans_omp_workshare returns.

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

--- gcc/fortran/trans-openmp.c	(revision 239903)
+++ gcc/fortran/trans-openmp.c	(revision 239904)
@@ -4001,10 +4001,7 @@ gfc_trans_omp_parallel_workshare (gfc_co
 				       code->loc);
   pushlevel ();
   stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
-  if (TREE_CODE (stmt) != BIND_EXPR)
-    stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
-  else
-    poplevel (0, 0);
+  stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
   stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
 		     omp_clauses);
   OMP_PARALLEL_COMBINED (stmt) = 1;
--- gcc/testsuite/gfortran.dg/gomp/pr77352.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77352.f90	(revision 239904)
@@ -0,0 +1,16 @@
+! PR fortran/77352
+! { dg-do compile }
+! { dg-additional-options "-fstack-arrays -O2" }
+! { dg-additional-options "-fopenacc" { target fopenacc } }
+
+program pr77352
+  real, allocatable :: a(:,:), b(:)
+  integer :: m, n
+  m = 4
+  n = 2
+  allocate (a(m,n), b(m))
+  a = 1.0
+!$omp parallel workshare
+  b(:) = [ sum(a, dim=1) ]
+!$omp end parallel workshare
+end


More information about the Gcc-patches mailing list