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  <ja...@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.

--- 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"
+

        Jakub

Reply via email to