OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / omp-low.c
index 47114b6..60b1480 100644 (file)
@@ -993,7 +993,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
        case OMP_CLAUSE_SHARED:
          gcc_assert (is_parallel_ctx (ctx));
          decl = OMP_CLAUSE_DECL (c);
-         gcc_assert (!is_variable_sized (decl));
+         gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
+                     || !is_variable_sized (decl));
          by_ref = use_pointer_for_field (decl, ctx);
          /* Global variables don't need to be copied,
             the receiver side will use them directly.  */
@@ -2625,7 +2626,7 @@ expand_omp_parallel (struct omp_region *region)
 
       /* Declare local variables needed in CHILD_CFUN.  */
       block = DECL_INITIAL (child_fn);
-      BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
+      BLOCK_VARS (block) = list2chain (child_cfun->local_decls);
       DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
 
       /* Reset DECL_CONTEXT on function arguments.  */
@@ -4195,8 +4196,10 @@ gate_expand_omp_ssa (void)
   return flag_openmp_ssa && flag_openmp != 0 && errorcount == 0;
 }
 
-struct tree_opt_pass pass_expand_omp_ssa = 
+struct gimple_opt_pass pass_expand_omp_ssa = 
 {
+ {
+  GIMPLE_PASS,
   "ompexpssa",                         /* name */
   gate_expand_omp_ssa,                 /* gate */
   execute_expand_omp,                  /* execute */
@@ -4208,8 +4211,8 @@ struct tree_opt_pass pass_expand_omp_ssa =
   PROP_gimple_lomp,                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };
 
 /* OMP expansion -- the default pass, run before creation of SSA form.  */
@@ -4221,8 +4224,10 @@ gate_expand_omp (void)
          && flag_openmp != 0 && errorcount == 0);
 }
 
-struct tree_opt_pass pass_expand_omp = 
+struct gimple_opt_pass pass_expand_omp = 
 {
+ {
+  GIMPLE_PASS,
   "ompexp",                            /* name */
   gate_expand_omp,                     /* gate */
   execute_expand_omp,                  /* execute */
@@ -4234,8 +4239,8 @@ struct tree_opt_pass pass_expand_omp =
   PROP_gimple_lomp,                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };
 \f
 /* Routines to lower OpenMP directives into OMP-GIMPLE.  */
@@ -4880,184 +4885,177 @@ lower_omp_parallel (tree *stmt_p, omp_context *ctx)
   pop_gimplify_context (NULL_TREE);
 }
 
-
-/* Pass *TP back through the gimplifier within the context determined by WI.
-   This handles replacement of DECL_VALUE_EXPR, as well as adjusting the 
-   flags on ADDR_EXPR.  */
-
-static void
-lower_regimplify (tree *tp, struct walk_stmt_info *wi)
-{
-  enum gimplify_status gs;
-  tree pre = NULL;
-
-  if (wi->is_lhs)
-    gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
-  else if (wi->val_only)
-    gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
-  else
-    gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
-  gcc_assert (gs == GS_ALL_DONE);
-
-  if (pre)
-    tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
-}
-
-/* Copy EXP into a temporary.  Insert the initialization statement before TSI.  */
+/* Callback for lower_omp_1.  Return non-NULL if *tp needs to be
+   regimplified.  */
 
 static tree
-init_tmp_var (tree exp, tree_stmt_iterator *tsi)
+lower_omp_2 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
-  tree t, stmt;
-
-  t = create_tmp_var (TREE_TYPE (exp), NULL);
-  DECL_GIMPLE_REG_P (t) = 1;
-  stmt = build_gimple_modify_stmt (t, exp);
-  SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
-  tsi_link_before (tsi, stmt, TSI_SAME_STMT);
-
-  return t;
-}
-
-/* Similarly, but copy from the temporary and insert the statement
-   after the iterator.  */
+  tree t = *tp;
 
-static tree
-save_tmp_var (tree exp, tree_stmt_iterator *tsi)
-{
-  tree t, stmt;
+  /* Any variable with DECL_VALUE_EXPR needs to be regimplified.  */
+  if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
+    return t;
 
-  t = create_tmp_var (TREE_TYPE (exp), NULL);
-  DECL_GIMPLE_REG_P (t) = 1;
-  stmt = build_gimple_modify_stmt (exp, t);
-  SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
-  tsi_link_after (tsi, stmt, TSI_SAME_STMT);
+  /* If a global variable has been privatized, TREE_CONSTANT on
+     ADDR_EXPR might be wrong.  */
+  if (TREE_CODE (t) == ADDR_EXPR)
+    recompute_tree_invariant_for_addr_expr (t);
 
-  return t;
+  *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
+  return NULL_TREE;
 }
 
-/* Callback for walk_stmts.  Lower the OpenMP directive pointed by TP.  */
-
-static tree
-lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
+static void
+lower_omp_1 (tree *tp, omp_context *ctx, tree_stmt_iterator *tsi)
 {
-  struct walk_stmt_info *wi = data;
-  omp_context *ctx = wi->info;
   tree t = *tp;
 
+  if (!t)
+    return;
+
+  if (EXPR_HAS_LOCATION (t))
+    input_location = EXPR_LOCATION (t);
+
   /* If we have issued syntax errors, avoid doing any heavy lifting.
      Just replace the OpenMP directives with a NOP to avoid
      confusing RTL expansion.  */
-  if (errorcount && OMP_DIRECTIVE_P (*tp))
+  if (errorcount && OMP_DIRECTIVE_P (t))
     {
       *tp = build_empty_stmt ();
-      return NULL_TREE;
+      return;
     }
 
-  *walk_subtrees = 0;
-  switch (TREE_CODE (*tp))
+  switch (TREE_CODE (t))
     {
+    case STATEMENT_LIST:
+      {
+       tree_stmt_iterator i;
+       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+         lower_omp_1 (tsi_stmt_ptr (i), ctx, &i);
+      }
+      break;
+
+    case COND_EXPR:
+      lower_omp_1 (&COND_EXPR_THEN (t), ctx, NULL);
+      lower_omp_1 (&COND_EXPR_ELSE (t), ctx, NULL);
+      if (ctx
+         && walk_tree (&COND_EXPR_COND (t), lower_omp_2, ctx, NULL))
+       {
+         tree pre = NULL;
+         gimplify_expr (&COND_EXPR_COND (t), &pre, NULL,
+                        is_gimple_condexpr, fb_rvalue);
+         if (pre)
+           {
+             if (tsi)
+               tsi_link_before (tsi, pre, TSI_SAME_STMT);
+             else
+               {
+                 append_to_statement_list (t, &pre);
+                 *tp = pre;
+               }
+           }
+       }
+      break;
+    case CATCH_EXPR:
+      lower_omp_1 (&CATCH_BODY (t), ctx, NULL);
+      break;
+    case EH_FILTER_EXPR:
+      lower_omp_1 (&EH_FILTER_FAILURE (t), ctx, NULL);
+      break;
+    case TRY_CATCH_EXPR:
+    case TRY_FINALLY_EXPR:
+      lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
+      lower_omp_1 (&TREE_OPERAND (t, 1), ctx, NULL);
+      break;
+    case BIND_EXPR:
+      lower_omp_1 (&BIND_EXPR_BODY (t), ctx, NULL);
+      break;
+    case RETURN_EXPR:
+      lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
+      break;
+
     case OMP_PARALLEL:
       ctx = maybe_lookup_ctx (t);
       lower_omp_parallel (tp, ctx);
       break;
-
     case OMP_FOR:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_for (tp, ctx);
       break;
-
     case OMP_SECTIONS:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_sections (tp, ctx);
       break;
-
     case OMP_SINGLE:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_single (tp, ctx);
       break;
-
     case OMP_MASTER:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_master (tp, ctx);
       break;
-
     case OMP_ORDERED:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_ordered (tp, ctx);
       break;
-
     case OMP_CRITICAL:
       ctx = maybe_lookup_ctx (t);
       gcc_assert (ctx);
       lower_omp_critical (tp, ctx);
       break;
 
-    case VAR_DECL:
-      if (ctx && DECL_HAS_VALUE_EXPR_P (t))
+    default:
+      if (ctx && walk_tree (tp, lower_omp_2, ctx, NULL))
        {
-         lower_regimplify (&t, wi);
-         if (wi->val_only)
+         /* The gimplifier doesn't gimplify CALL_EXPR_STATIC_CHAIN.
+            Handle that here.  */
+         tree call = get_call_expr_in (t);
+         if (call
+             && CALL_EXPR_STATIC_CHAIN (call)
+             && walk_tree (&CALL_EXPR_STATIC_CHAIN (call), lower_omp_2,
+                           ctx, NULL))
            {
-             if (wi->is_lhs)
-               t = save_tmp_var (t, &wi->tsi);
-             else
-               t = init_tmp_var (t, &wi->tsi);
+             tree pre = NULL;
+             gimplify_expr (&CALL_EXPR_STATIC_CHAIN (call), &pre, NULL,
+                            is_gimple_val, fb_rvalue);
+             if (pre)
+               {
+                 if (tsi)
+                   tsi_link_before (tsi, pre, TSI_SAME_STMT);
+                 else
+                   {
+                     append_to_statement_list (t, &pre);
+                     lower_omp_1 (&pre, ctx, NULL);
+                     *tp = pre;
+                     return;
+                   }
+               }
            }
-         *tp = t;
-       }
-      break;
-
-    case ADDR_EXPR:
-      if (ctx)
-       lower_regimplify (tp, wi);
-      break;
-
-    case ARRAY_REF:
-    case ARRAY_RANGE_REF:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    case COMPONENT_REF:
-    case VIEW_CONVERT_EXPR:
-      if (ctx)
-       lower_regimplify (tp, wi);
-      break;
 
-    case INDIRECT_REF:
-      if (ctx)
-       {
-         wi->is_lhs = false;
-         wi->val_only = true;
-         lower_regimplify (&TREE_OPERAND (t, 0), wi);
+         if (tsi == NULL)
+           gimplify_stmt (tp);
+         else
+           {
+             tree pre = NULL;
+             gimplify_expr (tp, &pre, NULL, is_gimple_stmt, fb_none);
+             if (pre)
+               tsi_link_before (tsi, pre, TSI_SAME_STMT);
+           }
        }
       break;
-
-    default:
-      if (!TYPE_P (t) && !DECL_P (t))
-       *walk_subtrees = 1;
-      break;
     }
-
-  return NULL_TREE;
 }
 
 static void
 lower_omp (tree *stmt_p, omp_context *ctx)
 {
-  struct walk_stmt_info wi;
-
-  memset (&wi, 0, sizeof (wi));
-  wi.callback = lower_omp_1;
-  wi.info = ctx;
-  wi.val_only = true;
-  wi.want_locations = true;
-
-  walk_stmts (&wi, stmt_p);
+  lower_omp_1 (stmt_p, ctx, NULL);
 }
 \f
 /* Main entry point.  */
@@ -5088,8 +5086,10 @@ gate_lower_omp (void)
   return flag_openmp != 0;
 }
 
-struct tree_opt_pass pass_lower_omp = 
+struct gimple_opt_pass pass_lower_omp = 
 {
+ {
+  GIMPLE_PASS,
   "omplower",                          /* name */
   gate_lower_omp,                      /* gate */
   execute_lower_omp,                   /* execute */
@@ -5101,8 +5101,8 @@ struct tree_opt_pass pass_lower_omp =
   PROP_gimple_lomp,                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };
 \f
 /* The following is a utility to diagnose OpenMP structured block violations.