OSDN Git Service

2007-02-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-openmp.c
index df8723b..4936866 100644 (file)
@@ -94,6 +94,29 @@ gfc_omp_predetermined_sharing (tree decl)
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
 
+
+/* Return code to initialize DECL with its default constructor, or
+   NULL if there's nothing to do.  */
+
+tree
+gfc_omp_clause_default_ctor (tree clause ATTRIBUTE_UNUSED, tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  stmtblock_t block;
+
+  if (! GFC_DESCRIPTOR_TYPE_P (type))
+    return NULL;
+
+  /* Allocatable arrays in PRIVATE clauses need to be set to
+     "not currently allocated" allocation status.  */
+  gfc_init_block (&block);
+
+  gfc_conv_descriptor_data_set_tuples (&block, decl, null_pointer_node);
+
+  return gfc_finish_block (&block);
+}
+
+
 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
    disregarded in OpenMP construct, because it is going to be
    remapped during OpenMP lowering.  SHARED is true if DECL
@@ -182,40 +205,56 @@ gfc_trans_add_clause (tree node, tree tail)
   return node;
 }
 
-/* TODO make references to parent function results, as done in
-   gfc_conv_variable.  */
-
 static tree
 gfc_trans_omp_variable (gfc_symbol *sym)
 {
   tree t = gfc_get_symbol_decl (sym);
+  tree parent_decl;
+  int parent_flag;
+  bool return_value;
+  bool alternate_entry;
+  bool entry_master;
+
+  return_value = sym->attr.function && sym->result == sym;
+  alternate_entry = sym->attr.function && sym->attr.entry
+                   && sym->result == sym;
+  entry_master = sym->attr.result
+                && sym->ns->proc_name->attr.entry_master
+                && !gfc_return_by_reference (sym->ns->proc_name);
+  parent_decl = DECL_CONTEXT (current_function_decl);
+
+  if ((t == parent_decl && return_value)
+       || (sym->ns && sym->ns->proc_name
+          && sym->ns->proc_name->backend_decl == parent_decl
+          && (alternate_entry || entry_master)))
+    parent_flag = 1;
+  else
+    parent_flag = 0;
 
   /* Special case for assigning the return value of a function.
      Self recursive functions must have an explicit return value.  */
-  if (t == current_function_decl && sym->attr.function
-      && (sym->result == sym))
-    t = gfc_get_fake_result_decl (sym, 0);
+  if (return_value && (t == current_function_decl || parent_flag))
+    t = gfc_get_fake_result_decl (sym, parent_flag);
 
   /* Similarly for alternate entry points.  */
-  else if (sym->attr.function && sym->attr.entry
-          && (sym->result == sym)
-          && sym->ns->proc_name->backend_decl == current_function_decl)
+  else if (alternate_entry
+          && (sym->ns->proc_name->backend_decl == current_function_decl
+              || parent_flag))
     {
       gfc_entry_list *el = NULL;
 
       for (el = sym->ns->entries; el; el = el->next)
        if (sym == el->sym)
          {
-           t = gfc_get_fake_result_decl (sym, 0);
+           t = gfc_get_fake_result_decl (sym, parent_flag);
            break;
          }
     }
 
-  else if (sym->attr.result
-          && sym->ns->proc_name->backend_decl == current_function_decl
-          && sym->ns->proc_name->attr.entry_master
-          && !gfc_return_by_reference (sym->ns->proc_name))
-    t = gfc_get_fake_result_decl (sym, 0);
+  else if (entry_master
+          && (sym->ns->proc_name->backend_decl == current_function_decl
+              || parent_flag))
+    t = gfc_get_fake_result_decl (sym, parent_flag);
 
   return t;
 }
@@ -246,7 +285,7 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
   gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
   gfc_expr *e1, *e2, *e3, *e4;
   gfc_ref *ref;
-  tree decl, backend_decl;
+  tree decl, backend_decl, stmt;
   locus old_loc = gfc_current_locus;
   const char *iname;
   try t;
@@ -261,6 +300,7 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
   init_val_sym.ts = sym->ts;
   init_val_sym.attr.referenced = 1;
   init_val_sym.declared_at = where;
+  init_val_sym.attr.flavor = FL_VARIABLE;
   backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
   init_val_sym.backend_decl = backend_decl;
 
@@ -269,6 +309,7 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
   outer_sym.as = gfc_copy_array_spec (sym->as);
   outer_sym.attr.dummy = 0;
   outer_sym.attr.result = 0;
+  outer_sym.attr.flavor = FL_VARIABLE;
   outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
 
   /* Create fake symtrees for it.  */
@@ -384,10 +425,22 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
   gcc_assert (t == SUCCESS);
 
   /* Create the init statement list.  */
-  OMP_CLAUSE_REDUCTION_INIT (c) = gfc_trans_assignment (e1, e2);
+  pushlevel (0);
+  stmt = gfc_trans_assignment (e1, e2, false);
+  if (TREE_CODE (stmt) != BIND_EXPR)
+    stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
+  else
+    poplevel (0, 0, 0);
+  OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
 
   /* Create the merge statement list.  */
-  OMP_CLAUSE_REDUCTION_MERGE (c) = gfc_trans_assignment (e3, e4);
+  pushlevel (0);
+  stmt = gfc_trans_assignment (e3, e4, false);
+  if (TREE_CODE (stmt) != BIND_EXPR)
+    stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
+  else
+    poplevel (0, 0, 0);
+  OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
 
   /* And stick the placeholder VAR_DECL into the clause as well.  */
   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
@@ -408,7 +461,7 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
 
 static tree
 gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list, 
-                              enum tree_code reduction_code, locus where)
+                             enum tree_code reduction_code, locus where)
 {
   for (; namelist != NULL; namelist = namelist->next)
     if (namelist->sym->attr.referenced)
@@ -779,7 +832,7 @@ gfc_trans_omp_atomic (gfc_code *code)
          tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
          gfc_actual_arglist *arg;
 
-         gfc_add_modify_expr (&block, accum, rse.expr);
+         gfc_add_modify_stmt (&block, accum, rse.expr);
          for (arg = expr2->value.function.actual->next->next; arg;
               arg = arg->next)
            {
@@ -787,7 +840,7 @@ gfc_trans_omp_atomic (gfc_code *code)
              gfc_conv_expr (&rse, arg->expr);
              gfc_add_block_to_block (&block, &rse.pre);
              x = fold_build2 (op, TREE_TYPE (accum), accum, rse.expr);
-             gfc_add_modify_expr (&block, accum, x);
+             gfc_add_modify_stmt (&block, accum, x);
            }
 
          rse.expr = accum;
@@ -822,7 +875,7 @@ static tree
 gfc_trans_omp_barrier (void)
 {
   tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
-  return build_function_call_expr (decl, NULL);
+  return build_call_expr (decl, 0);
 }
 
 static tree
@@ -837,7 +890,7 @@ gfc_trans_omp_critical (gfc_code *code)
 
 static tree
 gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
-                 gfc_omp_clauses *clauses)
+                 gfc_omp_clauses *do_clauses)
 {
   gfc_se se;
   tree dovar, stmt, from, to, step, type, init, cond, incr;
@@ -846,6 +899,7 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
   stmtblock_t body;
   int simple = 0;
   bool dovar_found = false;
+  gfc_omp_clauses *clauses = code->ext.omp_clauses;
 
   code = code->block->next;
   gcc_assert (code->op == EXEC_DO);
@@ -856,7 +910,7 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
       pblock = &block;
     }
 
-  omp_clauses = gfc_trans_omp_clauses (pblock, clauses, code->loc);
+  omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
   if (clauses)
     {
       gfc_namelist *n;
@@ -903,11 +957,11 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
   /* Loop body.  */
   if (simple)
     {
-      init = build2_v (MODIFY_EXPR, dovar, from);
+      init = build2_v (GIMPLE_MODIFY_STMT, dovar, from);
       cond = build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node,
                     dovar, to);
       incr = fold_build2 (PLUS_EXPR, type, dovar, step);
-      incr = fold_build2 (MODIFY_EXPR, type, dovar, incr);
+      incr = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar, incr);
       if (pblock != &block)
        {
          pushlevel (0);
@@ -929,10 +983,10 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
       tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
       tmp = gfc_evaluate_now (tmp, pblock);
       count = gfc_create_var (type, "count");
-      init = build2_v (MODIFY_EXPR, count, build_int_cst (type, 0));
+      init = build2_v (GIMPLE_MODIFY_STMT, count, build_int_cst (type, 0));
       cond = build2 (LT_EXPR, boolean_type_node, count, tmp);
       incr = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1));
-      incr = fold_build2 (MODIFY_EXPR, type, count, incr);
+      incr = fold_build2 (GIMPLE_MODIFY_STMT, type, count, incr);
 
       if (pblock != &block)
        {
@@ -944,7 +998,7 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
       /* Initialize DOVAR.  */
       tmp = fold_build2 (MULT_EXPR, type, count, step);
       tmp = build2 (PLUS_EXPR, type, from, tmp);
-      gfc_add_modify_expr (&body, dovar, tmp);
+      gfc_add_modify_stmt (&body, dovar, tmp);
     }
 
   if (!dovar_found)
@@ -1000,7 +1054,7 @@ static tree
 gfc_trans_omp_flush (void)
 {
   tree decl = built_in_decls [BUILT_IN_SYNCHRONIZE];
-  return build_function_call_expr (decl, NULL);
+  return build_call_expr (decl, 0);
 }
 
 static tree
@@ -1067,6 +1121,7 @@ gfc_trans_omp_parallel_do (gfc_code *code)
   else
     poplevel (0, 0, 0);
   stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
+  OMP_PARALLEL_COMBINED (stmt) = 1;
   gfc_add_expr_to_block (&block, stmt);
   return gfc_finish_block (&block);
 }
@@ -1091,6 +1146,7 @@ gfc_trans_omp_parallel_sections (gfc_code *code)
   else
     poplevel (0, 0, 0);
   stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
+  OMP_PARALLEL_COMBINED (stmt) = 1;
   gfc_add_expr_to_block (&block, stmt);
   return gfc_finish_block (&block);
 }
@@ -1115,6 +1171,7 @@ gfc_trans_omp_parallel_workshare (gfc_code *code)
   else
     poplevel (0, 0, 0);
   stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
+  OMP_PARALLEL_COMBINED (stmt) = 1;
   gfc_add_expr_to_block (&block, stmt);
   return gfc_finish_block (&block);
 }
@@ -1145,7 +1202,7 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
     }
   stmt = gfc_finish_block (&body);
 
-  stmt = build3_v (OMP_SECTIONS, stmt, omp_clauses, NULL);
+  stmt = build2_v (OMP_SECTIONS, stmt, omp_clauses);
   gfc_add_expr_to_block (&block, stmt);
 
   return gfc_finish_block (&block);