diff mbox

Fix simdclone pass for addressable linear/uniform parameters (PR middle-end/66702)

Message ID 20150630121912.GH10247@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek June 30, 2015, 12:19 p.m. UTC
Hi!

As the first testcase shows, we were mishandling addressable uniform/linear
parameters, in that case keeping them to use the (D) ssa name for uniform
or doing the iteration for linear doesn't work, so we need to handle it
slightly differently.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to
trunk/5.2.

2015-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/66702
	* omp-low.c (simd_clone_adjust): Handle addressable linear
	or uniform parameters or non-gimple type uniform parameters.

	* testsuite/libgomp.c++/pr66702-1.C: New test.
	* testsuite/libgomp.c++/pr66702-2.C: New test.


	Jakub
diff mbox

Patch

--- gcc/omp-low.c.jj	2015-06-17 20:11:10.000000000 +0200
+++ gcc/omp-low.c	2015-06-30 11:38:24.550092307 +0200
@@ -13427,12 +13427,54 @@  simd_clone_adjust (struct cgraph_node *n
      uniform args with __builtin_assume_aligned (arg_N(D), alignment)
      lhs.  Handle linear by adding PHIs.  */
   for (unsigned i = 0; i < node->simdclone->nargs; i++)
-    if (node->simdclone->args[i].alignment
-	&& node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
-	&& (node->simdclone->args[i].alignment
-	    & (node->simdclone->args[i].alignment - 1)) == 0
-	&& TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
-	   == POINTER_TYPE)
+    if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+	&& (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
+	    || !is_gimple_reg_type
+			(TREE_TYPE (node->simdclone->args[i].orig_arg))))
+      {
+	tree orig_arg = node->simdclone->args[i].orig_arg;
+	if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
+	  iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+	else
+	  {
+	    iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
+	    gimple_add_tmp_var (iter1);
+	  }
+	gsi = gsi_after_labels (entry_bb);
+	g = gimple_build_assign (iter1, orig_arg);
+	gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+	gsi = gsi_after_labels (body_bb);
+	g = gimple_build_assign (orig_arg, iter1);
+	gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+      }
+    else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+	     && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
+	     && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+		== REFERENCE_TYPE
+	     && TREE_ADDRESSABLE
+		  (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+      {
+	tree orig_arg = node->simdclone->args[i].orig_arg;
+	tree def = ssa_default_def (cfun, orig_arg);
+	if (def && !has_zero_uses (def))
+	  {
+	    iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
+	    gimple_add_tmp_var (iter1);
+	    gsi = gsi_after_labels (entry_bb);
+	    g = gimple_build_assign (iter1, build_simple_mem_ref (def));
+	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+	    gsi = gsi_after_labels (body_bb);
+	    g = gimple_build_assign (build_simple_mem_ref (def), iter1);
+	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+	  }
+      }
+    else if (node->simdclone->args[i].alignment
+	     && node->simdclone->args[i].arg_type
+		== SIMD_CLONE_ARG_TYPE_UNIFORM
+	     && (node->simdclone->args[i].alignment
+		 & (node->simdclone->args[i].alignment - 1)) == 0
+	     && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+		== POINTER_TYPE)
       {
 	unsigned int alignment = node->simdclone->args[i].alignment;
 	tree orig_arg = node->simdclone->args[i].orig_arg;
@@ -13482,13 +13524,31 @@  simd_clone_adjust (struct cgraph_node *n
 	     == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
       {
 	tree orig_arg = node->simdclone->args[i].orig_arg;
-	tree def = ssa_default_def (cfun, orig_arg);
 	gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
 		    || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
-	if (def && !has_zero_uses (def))
+	tree def = NULL_TREE;
+	if (TREE_ADDRESSABLE (orig_arg))
+	  {
+	    def = make_ssa_name (TREE_TYPE (orig_arg));
+	    iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+	    iter2 = make_ssa_name (TREE_TYPE (orig_arg));
+	    gsi = gsi_after_labels (entry_bb);
+	    g = gimple_build_assign (def, orig_arg);
+	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+	  }
+	else
+	  {
+	    def = ssa_default_def (cfun, orig_arg);
+	    if (!def || has_zero_uses (def))
+	      def = NULL_TREE;
+	    else
+	      {
+		iter1 = make_ssa_name (orig_arg);
+		iter2 = make_ssa_name (orig_arg);
+	      }
+	  }
+	if (def)
 	  {
-	    iter1 = make_ssa_name (orig_arg);
-	    iter2 = make_ssa_name (orig_arg);
 	    phi = create_phi_node (iter1, body_bb);
 	    add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
 	    add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
@@ -13505,12 +13565,19 @@  simd_clone_adjust (struct cgraph_node *n
 	    imm_use_iterator iter;
 	    use_operand_p use_p;
 	    gimple use_stmt;
-	    FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
-	      if (use_stmt == phi)
-		continue;
-	      else
-		FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-		  SET_USE (use_p, iter1);
+	    if (TREE_ADDRESSABLE (orig_arg))
+	      {
+		gsi = gsi_after_labels (body_bb);
+		g = gimple_build_assign (orig_arg, iter1);
+		gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+	      }
+	    else
+	      FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+		if (use_stmt == phi)
+		  continue;
+		else
+		  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+		    SET_USE (use_p, iter1);
 	  }
       }
 
--- libgomp/testsuite/libgomp.c++/pr66702-1.C.jj	2015-06-30 11:43:58.621078611 +0200
+++ libgomp/testsuite/libgomp.c++/pr66702-1.C	2015-06-30 11:45:04.260093508 +0200
@@ -0,0 +1,49 @@ 
+// PR middle-end/66702
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+void
+bar (int &a, int &b, int *&c, int &d)
+{
+  volatile int x;
+  int *volatile y;
+  x = a; a = x;
+  x = b; b = x;
+  y = c; c = y;
+  x = d; d = x;
+}
+
+void (*volatile barp) (int &, int &, int *&, int &) = bar;
+
+#pragma omp declare simd uniform(b, c) linear(d:2) aligned(c:32) notinbranch
+int
+foo (int a, int b, int *c, int d)
+{
+  a++;
+  b++;
+  c += 8;
+  d += 2;
+  barp (a, b, c, d);
+  return a + b + *c + d;
+}
+
+volatile int e = 5;
+int c[64] __attribute__((aligned (32)));
+
+int
+main ()
+{
+  int d = 7, r = 0;
+  int b = e;
+  for (int i = 0; i < 64; i++)
+    c[i] = i;
+  #pragma omp simd reduction(+:r) linear(d:2)
+  for (int i = 0; i < 64; i++)
+    {
+      r += foo (i, b, c, d);
+      d += 2;
+    }
+  if (r != 7584)
+    __builtin_abort ();
+}
--- libgomp/testsuite/libgomp.c++/pr66702-2.C.jj	2015-06-30 11:47:23.723000466 +0200
+++ libgomp/testsuite/libgomp.c++/pr66702-2.C	2015-06-30 11:47:59.524463162 +0200
@@ -0,0 +1,34 @@ 
+// PR middle-end/66702
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+struct S { int s1, s2; };
+struct T { T (); ~T (); int t; };
+
+T::T () : t(0) {}
+T::~T () {}
+
+#pragma omp declare simd uniform(b, c) notinbranch
+__attribute__((noinline)) int
+foo (int a, S b, T c)
+{
+  a++;
+  b.s1++;
+  b.s2++;
+  c.t++;
+  return a + b.s1 + b.s2 + c.t;
+}
+
+int
+main ()
+{
+  int r = 0;
+  S s = { 2, 3 };
+  T t;
+  #pragma omp simd reduction(+:r)
+  for (int i = 0; i < 64; i++)
+    r += foo (i, s, t);
+  if (r != 2592)
+    __builtin_abort ();
+}