Hi!

BIT_INSERT_EXPR is only defined for integral and vector types, so if we have
an array type which is bitfield representative if there is no integral type,
this fails to gimplify.  This still uses BIT_INSERT_EXPR with those types
to hold the expressions between c-omp.c and gimplification, but fixes it
there.

Bootstrapped/regtested on {x86_64,i686,powerpc64{,le}}-linux, committed to
trunk, queued for backports.

2019-01-22  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/88968
        * gimplify.c (gimplify_omp_atomic): Handle bitfield atomics with
        non-integral DECL_BIT_FIELD_REPRESENTATIVEs.

        * c-omp.c (c_finish_omp_atomic): For bitfield atomics, update type
        variable after using BIT_FIELD_REF.

        * c-c++-common/gomp/atomic-23.c: New test.

--- gcc/gimplify.c.jj   2019-01-01 12:37:19.881930257 +0100
+++ gcc/gimplify.c      2019-01-22 15:42:28.112511624 +0100
@@ -11969,9 +11969,36 @@ gimplify_omp_atomic (tree *expr_p, gimpl
   loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
                                           OMP_ATOMIC_MEMORY_ORDER (*expr_p));
   gimplify_seq_add_stmt (pre_p, loadstmt);
-  if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
-      != GS_ALL_DONE)
-    return GS_ERROR;
+  if (rhs)
+    {
+      /* BIT_INSERT_EXPR is not valid for non-integral bitfield
+        representatives.  Use BIT_FIELD_REF on the lhs instead.  */
+      if (TREE_CODE (rhs) == BIT_INSERT_EXPR
+         && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
+       {
+         tree bitpos = TREE_OPERAND (rhs, 2);
+         tree op1 = TREE_OPERAND (rhs, 1);
+         tree bitsize;
+         tree tmp_store = tmp_load;
+         if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
+           tmp_store = get_initialized_tmp_var (tmp_load, pre_p, NULL);
+         if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
+           bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
+         else
+           bitsize = TYPE_SIZE (TREE_TYPE (op1));
+         gcc_assert (TREE_OPERAND (rhs, 0) == tmp_load);
+         tree t = build2_loc (EXPR_LOCATION (rhs),
+                              MODIFY_EXPR, void_type_node,
+                              build3_loc (EXPR_LOCATION (rhs), BIT_FIELD_REF,
+                                          TREE_TYPE (op1), tmp_store, bitsize,
+                                          bitpos), op1);
+         gimplify_and_add (t, pre_p);
+         rhs = tmp_store;
+       }
+      if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
+         != GS_ALL_DONE)
+       return GS_ERROR;
+    }
 
   if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
     rhs = tmp_load;
--- gcc/c-family/c-omp.c.jj     2019-01-01 12:37:51.324414364 +0100
+++ gcc/c-family/c-omp.c        2019-01-22 15:28:39.110981144 +0100
@@ -378,8 +378,11 @@ c_finish_omp_atomic (location_t loc, enu
            }
        }
       if (blhs)
-       x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
-                       bitsize_int (bitsize), bitsize_int (bitpos));
+       {
+         x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
+                         bitsize_int (bitsize), bitsize_int (bitpos));
+         type = TREE_TYPE (blhs);
+       }
       x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
                             loc, x, NULL_TREE);
       if (rhs1 && rhs1 != orig_lhs)
--- gcc/testsuite/c-c++-common/gomp/atomic-23.c.jj      2019-01-22 
15:56:23.289958860 +0100
+++ gcc/testsuite/c-c++-common/gomp/atomic-23.c 2019-01-22 15:56:01.331314322 
+0100
@@ -0,0 +1,47 @@
+/* PR middle-end/88968 */
+/* { dg-do compile } */
+
+struct __attribute__((packed)) S {
+  unsigned int a : 16;
+  unsigned int b : 1;
+} s;
+
+void
+f1 (void)
+{
+#pragma omp atomic
+  ++s.a;
+}
+
+int
+f2 (void)
+{
+  int r;
+#pragma omp atomic capture
+  {
+    r = s.a;
+    s.a = 0;
+  }
+  return r;
+}
+
+int
+f3 (void)
+{
+  int r;
+#pragma omp atomic capture
+  {
+    r = s.a;
+    s.a = s.a + 32;
+  }
+  return r;
+}
+
+int
+f4 (void)
+{
+  int r;
+#pragma omp atomic capture
+  r = s.a = s.a + 32;
+  return r;
+}

        Jakub

Reply via email to