]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR libgomp/61200 (internal compiler error: Segmentation fault, assert...
authorJakub Jelinek <jakub@redhat.com>
Fri, 28 Nov 2014 17:03:01 +0000 (18:03 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 28 Nov 2014 17:03:01 +0000 (18:03 +0100)
Backported from mainline
2014-10-03  Jakub Jelinek  <jakub@redhat.com>

PR libgomp/61200
* omp-low.c (taskreg_contexts): New variable.
(scan_omp_parallel): Push newly created context into taskreg_contexts
vector and move record layout code to finish_taskreg_scan.
(scan_omp_task): Likewise.
(finish_taskreg_scan): New function.
(execute_lower_omp): Call finish_taskreg_scan on all taskreg_contexts
vector elements and release it.

* c-c++-common/gomp/pr61200.c: New test.

* testsuite/libgomp.c/pr61200.c: New test.

From-SVN: r218165

gcc/ChangeLog
gcc/omp-low.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/gomp/pr61200.c [new file with mode: 0644]
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/pr61200.c [new file with mode: 0644]

index 2951d52cd006b498bbe101a96002116b3a386044..87730ce16ba8afe7dfbb7e8aad9d6808535d87bb 100644 (file)
@@ -1,3 +1,17 @@
+2014-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+       Backported from mainline
+       2014-10-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR libgomp/61200
+       * omp-low.c (taskreg_contexts): New variable.
+       (scan_omp_parallel): Push newly created context into taskreg_contexts
+       vector and move record layout code to finish_taskreg_scan.
+       (scan_omp_task): Likewise.
+       (finish_taskreg_scan): New function.
+       (execute_lower_omp): Call finish_taskreg_scan on all taskreg_contexts
+       vector elements and release it.
+
 2014-11-26  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
index 49fadc3a699797aa953af1459cab50d5706bff3b..fc7c9910168d003b41e5b87cdc914b8f386f44b2 100644 (file)
@@ -128,6 +128,7 @@ static splay_tree all_contexts;
 static int taskreg_nesting_level;
 struct omp_region *root_omp_region;
 static bitmap task_shared_vars;
+static vec<omp_context *> taskreg_contexts;
 
 static void scan_omp (gimple_seq *, omp_context *);
 static tree scan_omp_1_op (tree *, int *, void *);
@@ -1655,6 +1656,7 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
     }
 
   ctx = new_omp_context (stmt, outer_ctx);
+  taskreg_contexts.safe_push (ctx);
   if (taskreg_nesting_level > 1)
     ctx->is_nested = true;
   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
@@ -1674,11 +1676,6 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
 
   if (TYPE_FIELDS (ctx->record_type) == NULL)
     ctx->record_type = ctx->receiver_decl = NULL;
-  else
-    {
-      layout_type (ctx->record_type);
-      fixup_child_record_type (ctx);
-    }
 }
 
 /* Scan an OpenMP task directive.  */
@@ -1689,7 +1686,6 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
   omp_context *ctx;
   tree name, t;
   gimple stmt = gsi_stmt (*gsi);
-  location_t loc = gimple_location (stmt);
 
   /* Ignore task directives with empty bodies.  */
   if (optimize > 0
@@ -1700,6 +1696,7 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
     }
 
   ctx = new_omp_context (stmt, outer_ctx);
+  taskreg_contexts.safe_push (ctx);
   if (taskreg_nesting_level > 1)
     ctx->is_nested = true;
   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
@@ -1737,8 +1734,71 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
       t = build_int_cst (long_integer_type_node, 1);
       gimple_omp_task_set_arg_align (stmt, t);
     }
+}
+
+
+/* If any decls have been made addressable during scan_omp,
+   adjust their fields if needed, and layout record types
+   of parallel/task constructs.  */
+
+static void
+finish_taskreg_scan (omp_context *ctx)
+{
+  if (ctx->record_type == NULL_TREE)
+    return;
+
+  /* If any task_shared_vars were needed, verify all
+     OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
+     statements if use_pointer_for_field hasn't changed
+     because of that.  If it did, update field types now.  */
+  if (task_shared_vars)
+    {
+      tree c;
+
+      for (c = gimple_omp_taskreg_clauses (ctx->stmt);
+          c; c = OMP_CLAUSE_CHAIN (c))
+       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+         {
+           tree decl = OMP_CLAUSE_DECL (c);
+
+           /* Global variables don't need to be copied,
+              the receiver side will use them directly.  */
+           if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
+             continue;
+           if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
+               || !use_pointer_for_field (decl, ctx))
+             continue;
+           tree field = lookup_field (decl, ctx);
+           if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
+               && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
+             continue;
+           TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
+           TREE_THIS_VOLATILE (field) = 0;
+           DECL_USER_ALIGN (field) = 0;
+           DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
+           if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
+             TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
+           if (ctx->srecord_type)
+             {
+               tree sfield = lookup_sfield (decl, ctx);
+               TREE_TYPE (sfield) = TREE_TYPE (field);
+               TREE_THIS_VOLATILE (sfield) = 0;
+               DECL_USER_ALIGN (sfield) = 0;
+               DECL_ALIGN (sfield) = DECL_ALIGN (field);
+               if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
+                 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
+             }
+         }
+    }
+
+  if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
+    {
+      layout_type (ctx->record_type);
+      fixup_child_record_type (ctx);
+    }
   else
     {
+      location_t loc = gimple_location (ctx->stmt);
       tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
       /* Move VLA fields to the end.  */
       p = &TYPE_FIELDS (ctx->record_type);
@@ -1758,12 +1818,12 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
       fixup_child_record_type (ctx);
       if (ctx->srecord_type)
        layout_type (ctx->srecord_type);
-      t = fold_convert_loc (loc, long_integer_type_node,
-                       TYPE_SIZE_UNIT (ctx->record_type));
-      gimple_omp_task_set_arg_size (stmt, t);
+      tree t = fold_convert_loc (loc, long_integer_type_node,
+                                TYPE_SIZE_UNIT (ctx->record_type));
+      gimple_omp_task_set_arg_size (ctx->stmt, t);
       t = build_int_cst (long_integer_type_node,
                         TYPE_ALIGN_UNIT (ctx->record_type));
-      gimple_omp_task_set_arg_align (stmt, t);
+      gimple_omp_task_set_arg_align (ctx->stmt, t);
     }
 }
 
@@ -7112,6 +7172,8 @@ static unsigned int
 execute_lower_omp (void)
 {
   gimple_seq body;
+  int i;
+  omp_context *ctx;
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
@@ -7124,6 +7186,9 @@ execute_lower_omp (void)
   body = gimple_body (current_function_decl);
   scan_omp (&body, NULL);
   gcc_assert (taskreg_nesting_level == 0);
+  FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
+    finish_taskreg_scan (ctx);
+  taskreg_contexts.release ();
 
   if (all_contexts->root)
     {
index 0ae6f0e1736843a2eab0351daa8e27a2742f5281..7b57f1222c7c3173b4bfcf7360bf1be6c7a3df44 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+       Backported from mainline
+       2014-10-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR libgomp/61200
+       * c-c++-common/gomp/pr61200.c: New test.
+
 2014-11-26  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
diff --git a/gcc/testsuite/c-c++-common/gomp/pr61200.c b/gcc/testsuite/c-c++-common/gomp/pr61200.c
new file mode 100644 (file)
index 0000000..d0d699d
--- /dev/null
@@ -0,0 +1,13 @@
+/* PR libgomp/61200 */
+
+int
+main ()
+{
+  int var = 1;
+  #pragma omp parallel
+    if (var != 1)
+      __builtin_abort ();
+  #pragma omp task shared(var)
+    var = 2;
+  return 0;
+}
index fc2bbee0da7df7eeded3cd5550300f4aa6760051..8b549f7e41e2d6f2d8485e7d0530976fb5109d06 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+       Backported from mainline
+       2014-10-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR libgomp/61200
+       * testsuite/libgomp.c/pr61200.c: New test.
+
 2014-05-22  Release Manager
 
        * GCC 4.8.3 released.
diff --git a/libgomp/testsuite/libgomp.c/pr61200.c b/libgomp/testsuite/libgomp.c/pr61200.c
new file mode 100644 (file)
index 0000000..ba3ed37
--- /dev/null
@@ -0,0 +1,87 @@
+/* PR libgomp/61200 */
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+volatile int x;
+
+void
+foo ()
+{
+  int var = 1;
+  int i;
+
+  for (i = 0; i < 2; i++)
+    {
+      if (i == 1)
+       {
+         #pragma omp parallel num_threads(2)
+           if (x)
+             var++;
+           else
+             {
+               #pragma omp single
+                 sleep (2);
+             }
+       }
+      else
+       {
+         #pragma omp task shared(var)
+         {
+           sleep (1);
+           var = 2;
+         }
+       }
+    }
+  #pragma omp taskwait
+  if (var != 2)
+    abort ();
+}
+
+void
+bar ()
+{
+  int var = 1;
+  int i;
+
+  for (i = 0; i < 2; i++)
+    {
+      if (i == 0)
+       {
+         #pragma omp task shared(var)
+         {
+           sleep (1);
+           var = 2;
+         }
+       }
+      else
+       {
+         #pragma omp parallel num_threads(2)
+           if (x)
+             var++;
+           else
+             {
+               #pragma omp single
+                 sleep (2);
+             }
+       }
+    }
+  #pragma omp taskwait
+  if (var != 2)
+    abort ();
+}
+
+int
+main ()
+{
+  omp_set_nested (1);
+  #pragma omp parallel num_threads(2)
+    #pragma omp single
+      foo ();
+  #pragma omp parallel num_threads(2)
+    #pragma omp single
+      bar ();
+  return 0;
+}