diff mbox

[committed] Fix C omp for verification (PR c/45784)

Message ID 20170727191734.GE2123@tucnak
State New
Headers show

Commit Message

Jakub Jelinek July 27, 2017, 7:17 p.m. UTC
Hi!

Apparently for C sizeof on VLA the FE tends to emit something that
is folded into a COMPOUND_EXPR with the VLA decl on lhs and the actual
condition on rhs.  In the bar routine in the testcase I'm actually
testing a case where there are multiple such COMPOUND_EXPRs.

This patch accepts those and moves those to the non-decl operand of
the comparison, which is really the only spot where it could be actually
used anyway.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk,
queued for backporting to release branches.

2017-07-27  Jakub Jelinek  <jakub@redhat.com>

	PR c/45784
	* c-omp.c (c_finish_omp_for): If the condition is wrapped in
	rhs of COMPOUND_EXPR(s), skip them and readd their lhs into
	new COMPOUND_EXPRs around the rhs of the comparison.

	* testsuite/libgomp.c/pr45784.c: New test.
	* testsuite/libgomp.c++/pr45784.C: New test.


	Jakub
diff mbox

Patch

--- gcc/c-family/c-omp.c.jj	2017-01-01 12:45:46.000000000 +0100
+++ gcc/c-family/c-omp.c	2017-07-27 18:33:40.764274882 +0200
@@ -531,6 +531,12 @@  c_finish_omp_for (location_t locus, enum
 	{
 	  bool cond_ok = false;
 
+	  /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
+	     evaluation of the vla VAR_DECL.  We need to readd
+	     them to the non-decl operand.  See PR45784.  */
+	  while (TREE_CODE (cond) == COMPOUND_EXPR)
+	    cond = TREE_OPERAND (cond, 1);
+
 	  if (EXPR_HAS_LOCATION (cond))
 	    elocus = EXPR_LOCATION (cond);
 
@@ -605,6 +611,21 @@  c_finish_omp_for (location_t locus, enum
 		  else if (code != CILK_SIMD && code != CILK_FOR)
 		    cond_ok = false;
 		}
+
+	      if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
+		{
+		  tree ce = NULL_TREE, *pce = &ce;
+		  tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
+		  for (tree c = TREE_VEC_ELT (condv, i); c != cond;
+		       c = TREE_OPERAND (c, 1))
+		    {
+		      *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
+				     TREE_OPERAND (cond, 1));
+		      pce = &TREE_OPERAND (*pce, 1);
+		    }
+		  TREE_OPERAND (cond, 1) = ce;
+		  TREE_VEC_ELT (condv, i) = cond;
+		}
 	    }
 
 	  if (!cond_ok)
--- libgomp/testsuite/libgomp.c/pr45784.c.jj	2017-07-27 18:50:53.230801321 +0200
+++ libgomp/testsuite/libgomp.c/pr45784.c	2017-07-27 18:51:08.436617805 +0200
@@ -0,0 +1,41 @@ 
+/* PR c/45784 */
+/* { dg-do run } */
+
+void
+foo (int n)
+{
+  char *p, vla[2 * n];
+  int i;
+  #pragma omp parallel for
+  for (p = vla; p < vla + (sizeof (vla) / sizeof (vla[0])); p++)
+    *p = ' ';
+  #pragma omp parallel for
+  for (i = 0; i < 2 * n; i++)
+    if (vla[i] != ' ')
+      __builtin_abort ();
+}
+
+void
+bar (int n)
+{
+  char *p, vla1[n], vla2[n * 2], vla3[n * 3], vla4[n * 4];
+  int i;
+  __builtin_memset (vla4, ' ', n * 4);
+  #pragma omp parallel for
+  for (p = vla4 + sizeof (vla1); p < vla4 + sizeof (vla3) - sizeof (vla2) + sizeof (vla1); p += sizeof (vla4) / sizeof (vla4))
+    p[0] = '!';
+  #pragma omp parallel for
+  for (i = 0; i < n * 4; i++)
+    if (vla4[i] != ((i >= n && i < 2 * n) ? '!' : ' '))
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  volatile int n;
+  n = 128;
+  foo (n);
+  bar (n);
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/pr45784.C.jj	2017-07-27 18:51:38.545254431 +0200
+++ libgomp/testsuite/libgomp.c++/pr45784.C	2017-07-27 18:51:32.404328545 +0200
@@ -0,0 +1,5 @@ 
+// PR c/45784
+// { dg-do run }
+
+#include "../libgomp.c/pr45784.c"
+