summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-06-06 13:01:54 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-06-06 13:01:54 +0000
commitfd6481cf2e4413bca3ef43b1e504e1c78de6025d (patch)
tree5d5537ea17855b77cca7b9c90a262e584c441592 /gcc/fortran
parentcbdcfa59ffeb7d51f7cbdfe64e1a99e43c82b2ac (diff)
downloadgcc-fd6481cf2e4413bca3ef43b1e504e1c78de6025d.tar.gz
* c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP value to
200805. * langhooks.h (struct lang_hooks_for_decls): Add omp_finish_clause. Add omp_private_outer_ref hook, add another argument to omp_clause_default_ctor hook. * langhooks-def.h (LANG_HOOKS_OMP_FINISH_CLAUSE): Define. (LANG_HOOKS_OMP_PRIVATE_OUTER_REF): Define. (LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR): Change to hook_tree_tree_tree_tree_null. (LANG_HOOKS_DECLS): Add LANG_HOOKS_OMP_FINISH_CLAUSE and LANG_HOOKS_OMP_PRIVATE_OUTER_REF. * hooks.c (hook_tree_tree_tree_tree_null): New function. * hooks.h (hook_tree_tree_tree_tree_null): New prototype. * tree.def (OMP_TASK): New tree code. * tree.h (OMP_TASK_COPYFN, OMP_TASK_ARG_SIZE, OMP_TASK_ARG_ALIGN, OMP_CLAUSE_PRIVATE_OUTER_REF, OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_COLLAPSE_ITERVAR, OMP_CLAUSE_COLLAPSE_COUNT, OMP_TASKREG_CHECK, OMP_TASKREG_BODY, OMP_TASKREG_CLAUSES, OMP_TASKREG_FN, OMP_TASKREG_DATA_ARG, OMP_TASK_BODY, OMP_TASK_CLAUSES, OMP_TASK_FN, OMP_TASK_DATA_ARG, OMP_CLAUSE_COLLAPSE_EXPR): Define. (enum omp_clause_default_kind): Add OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. (OMP_DIRECTIVE_P): Add OMP_TASK. (OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED): New clause codes. (OMP_CLAUSE_SCHEDULE_AUTO): New schedule kind. * tree.c (omp_clause_code_name): Add OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED entries. (omp_clause_num_ops): Likewise. Increase OMP_CLAUSE_LASTPRIVATE num_ops to 2. (walk_tree_1): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Walk OMP_CLAUSE_LASTPRIVATE_STMT. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_SCHEDULE_AUTO, OMP_CLAUSE_UNTIED, OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. (dump_generic_node): Handle OMP_TASK and collapsed OMP_FOR loops. * c-omp.c (c_finish_omp_for): Allow pointer iterators. Remove warning about unsigned iterators. Change decl/init/cond/incr arguments to TREE_VECs, check arguments for all collapsed loops. (c_finish_omp_taskwait): New function. (c_split_parallel_clauses): Put OMP_CLAUSE_COLLAPSE clause to ws_clauses. * c-parser.c (c_parser_omp_for_loop): Parse collapsed loops. Call default_function_array_conversion on init. Add par_clauses argument. If decl is present in parallel's lastprivate clause, change it to shared and add lastprivate clause for decl to OMP_FOR_CLAUSES. Add clauses argument, on success set OMP_FOR_CLAUSES to it. Look up collapse count in clauses. (c_parser_omp_for, c_parser_omp_parallel): Adjust c_parser_omp_for_loop callers. (OMP_FOR_CLAUSE_MASK): Add 1 << PRAGMA_OMP_CLAUSE_COLLAPSE. (c_parser_pragma): Handle PRAGMA_OMP_TASKWAIT. (c_parser_omp_clause_name): Handle collapse and untied clauses. (c_parser_omp_clause_collapse, c_parser_omp_clause_untied): New functions. (c_parser_omp_clause_schedule): Handle schedule(auto). Include correct location in the error message. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_COLLAPSE and PRAGMA_OMP_CLAUSE_UNTIED. (OMP_TASK_CLAUSE_MASK): Define. (c_parser_omp_task, c_parser_omp_taskwait): New functions. (c_parser_omp_construct): Handle PRAGMA_OMP_TASK. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Handle OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_REDUCTION_INIT, OMP_CLAUSE_REDUCTION_MERGE, OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Don't handle TREE_STATIC or DECL_EXTERNAL VAR_DECLs in OMP_CLAUSE_DECL. (conver_nonlocal_reference, convert_local_reference, convert_call_expr): Handle OMP_TASK the same as OMP_PARALLEL. Use OMP_TASKREG_* macros rather than OMP_PARALLEL_*. (walk_omp_for): Adjust for OMP_FOR_{INIT,COND,INCR} changes. * tree-gimple.c (is_gimple_stmt): Handle OMP_TASK. * c-tree.h (c_begin_omp_task, c_finish_omp_task): New prototypes. * c-pragma.h (PRAGMA_OMP_TASK, PRAGMA_OMP_TASKWAIT): New. (PRAGMA_OMP_CLAUSE_COLLAPSE, PRAGMA_OMP_CLAUSE_UNTIED): New. * c-typeck.c (c_begin_omp_task, c_finish_omp_task): New functions. (c_finish_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. * c-pragma.c (init_pragma): Init omp task and omp taskwait pragmas. * c-common.h (c_finish_omp_taskwait): New prototype. * gimple-low.c (lower_stmt): Handle OMP_TASK. * tree-parloops.c (create_parallel_loop): Create 1 entry vectors for OMP_FOR_{INIT,COND,INCR}. * tree-cfg.c (remove_useless_stmts_1): Handle OMP_* containers. (make_edges): Handle OMP_TASK. * tree-ssa-operands.c (get_expr_operands): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. * tree-inline.c (estimate_num_insns_1): Handle OMP_TASK. * builtin-types.def (BT_PTR_ULONGLONG, BT_PTR_FN_VOID_PTR_PTR, BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): New. * omp-builtins.def (BUILT_IN_GOMP_TASK, BUILT_IN_GOMP_TASKWAIT, BUILT_IN_GOMP_LOOP_ULL_STATIC_START, BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_START, BUILT_IN_GOMP_LOOP_ULL_GUIDED_START, BUILT_IN_GOMP_LOOP_ULL_RUNTIME_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_START, BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_GUIDED_NEXT, BUILT_IN_GOMP_LOOP_ULL_RUNTIME_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT): New builtins. * gimplify.c (gimplify_omp_for): Allow pointer type for decl, handle POINTER_PLUS_EXPR. If loop counter has been replaced and original iterator is present in lastprivate clause or if collapse > 1, set OMP_CLAUSE_LASTPRIVATE_STMT. Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. (gimplify_expr): Handle OMP_SECTIONS_SWITCH and OMP_TASK. (enum gimplify_omp_var_data): Add GOVD_PRIVATE_OUTER_REF. (omp_notice_variable): Set GOVD_PRIVATE_OUTER_REF if needed, if it is set, lookup var in outer contexts too. Handle OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. Handle vars that are supposed to be implicitly determined firstprivate for task regions. (gimplify_scan_omp_clauses): Set GOVD_PRIVATE_OUTER_REF if needed, if it is set, lookup var in outer contexts too. Set OMP_CLAUSE_PRIVATE_OUTER_REF if GOVD_PRIVATE_OUTER_REF is set. Handle OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Take region_type as last argument instead of in_parallel and in_combined_parallel. (gimplify_omp_parallel, gimplify_omp_for, gimplify_omp_workshare): Adjust callers. (gimplify_adjust_omp_clauses_1): Set OMP_CLAUSE_PRIVATE_OUTER_REF if GOVD_PRIVATE_OUTER_REF is set. Call omp_finish_clause langhook. (new_omp_context): Set default_kind to OMP_CLAUSE_DEFAULT_UNSPECIFIED for OMP_TASK regions. (omp_region_type): New enum. (struct gimplify_omp_ctx): Remove is_parallel and is_combined_parallel fields, add region_type. (new_omp_context): Take region_type as argument instead of is_parallel and is_combined_parallel. (gimple_add_tmp_var, omp_firstprivatize_variable, omp_notice_variable, omp_is_private, omp_check_private): Adjust ctx->is_parallel and ctx->is_combined_parallel checks. (gimplify_omp_task): New function. (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. * omp-low.c (extract_omp_for_data): Use schedule(static) for schedule(auto). Handle pointer and unsigned iterators. Compute fd->iter_type. Handle POINTER_PLUS_EXPR increments. Add loops argument. Extract data for collapsed OMP_FOR loops. (expand_parallel_call): Assert sched_kind isn't auto, map runtime schedule to index 3. (struct omp_for_data_loop): New type. (struct omp_for_data): Remove v, n1, n2, step, cond_code fields. Add loop, loops, collapse and iter_type fields. (workshare_safe_to_combine_p): Disallow combined for if iter_type is unsigned long long. Don't combine collapse > 1 loops unless all bounds and steps are constant. Adjust extract_omp_for_data caller. (expand_omp_for_generic): Handle pointer, unsigned and long long iterators. Handle collapsed OMP_FOR loops. Adjust for struct omp_for_data changes. If libgomp function doesn't return boolean_type_node, add comparison of the return value with 0. (expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Handle pointer, unsigned and long long iterators. Adjust for struct omp_for_data changes. (expand_omp_for): Assert sched_kind isn't auto, map runtime schedule to index 3. Use GOMP_loop_ull*{start,next} if iter_type is unsigned long long. Allocate loops array, pass it to extract_omp_for_data. For collapse > 1 loops use always expand_omp_for_generic. (omp_context): Add sfield_map and srecord_type fields. (is_task_ctx, lookup_sfield): New functions. (use_pointer_for_field): Use is_task_ctx helper. Change first argument's type from const_tree to tree. Clarify comment. In OMP_TASK disallow copy-in/out sharing. (build_sender_ref): Call lookup_sfield instead of lookup_field. (install_var_field): Add mask argument. Populate both record_type and srecord_type if needed. (delete_omp_context): Destroy sfield_map, clear DECL_ABSTRACT_ORIGIN in srecord_type. (fixup_child_record_type): Also remap FIELD_DECL's DECL_SIZE{,_UNIT} and DECL_FIELD_OFFSET. (scan_sharing_clauses): Adjust install_var_field callers. For firstprivate clauses on explicit tasks allocate the var by value in record_type unconditionally, rather than by reference. Handle OMP_CLAUSE_PRIVATE_OUTER_REF. Scan OMP_CLAUSE_LASTPRIVATE_STMT. Use is_taskreg_ctx instead of is_parallel_ctx. Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. (create_omp_child_function_name): Add task_copy argument, use *_omp_cpyfn* names if it is true. (create_omp_child_function): Add task_copy argument, if true create *_omp_cpyfn* helper function. (scan_omp_parallel): Adjust create_omp_child_function callers. Rename parallel_nesting_level to taskreg_nesting_level. (scan_omp_task): New function. (lower_rec_input_clauses): Don't run constructors for firstprivate explicit task vars which are initialized by *_omp_cpyfn*. Pass outer var ref to omp_clause_default_ctor hook if OMP_CLAUSE_PRIVATE_OUTER_REF or OMP_CLAUSE_LASTPRIVATE. Replace OMP_CLAUSE_REDUCTION_PLACEHOLDER decls in OMP_CLAUSE_REDUCTION_INIT. (lower_send_clauses): Clear DECL_ABSTRACT_ORIGIN if in task to avoid duplicate setting of fields. Handle OMP_CLAUSE_PRIVATE_OUTER_REF. (lower_send_shared_vars): Use srecord_type if non-NULL. Don't copy-out if TREE_READONLY, only copy-in. (expand_task_copyfn): New function. (expand_task_call): New function. (struct omp_taskcopy_context): New type. (task_copyfn_copy_decl, task_copyfn_remap_type, create_task_copyfn): New functions. (lower_omp_parallel): Rename to... (lower_omp_taskreg): ... this. Use OMP_TASKREG_* macros where needed. Call create_task_copyfn if srecord_type is needed. Adjust sender_decl type. (task_shared_vars): New variable. (check_omp_nesting_restrictions): Warn if work-sharing, barrier, master or ordered region is closely nested inside OMP_TASK. Add warnings for barrier if closely nested inside of work-sharing, ordered, or master region. (scan_omp_1): Call check_omp_nesting_restrictions even for GOMP_barrier calls. Rename parallel_nesting_level to taskreg_nesting_level. Handle OMP_TASK. (lower_lastprivate_clauses): Even if some lastprivate is found on a work-sharing construct, continue looking for them on parent parallel construct. (lower_omp_for_lastprivate): Add lastprivate clauses to the beginning of dlist rather than end. Adjust for struct omp_for_data changes. (lower_omp_for): Add rec input clauses before OMP_FOR_PRE_BODY, not after it. Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes, adjust extract_omp_for_data caller. (get_ws_args_for): Adjust extract_omp_for_data caller. (scan_omp_for): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. (lower_omp_single_simple): If libgomp function doesn't return boolean_type_node, add comparison of the return value with 0. (diagnose_sb_1, diagnose_sb_2): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. Handle OMP_TASK. (parallel_nesting_level): Rename to... (taskreg_nesting_level): ... this. (is_taskreg_ctx): New function. (build_outer_var_ref, omp_copy_decl): Use is_taskreg_ctx instead of is_parallel_ctx. (execute_lower_omp): Rename parallel_nesting_level to taskreg_nesting_level. (expand_omp_parallel): Rename to... (expand_omp_taskreg): ... this. Use OMP_TASKREG_* macros where needed. Call omp_task_call for OMP_TASK regions. (expand_omp): Adjust caller, handle OMP_TASK. (lower_omp_1): Adjust lower_omp_taskreg caller, handle OMP_TASK. * bitmap.c (bitmap_default_obstack_depth): New variable. (bitmap_obstack_initialize, bitmap_obstack_release): Do nothing if argument is NULL and bitmap_default_obstack is already initialized. * ipa-struct-reorg.c (do_reorg_1): Call bitmap_obstack_release at the end. * matrix-reorg.c (matrix_reorg): Likewise. cp/ * cp-tree.h (cxx_omp_finish_clause, cxx_omp_create_clause_info, dependent_omp_for_p, begin_omp_task, finish_omp_task, finish_omp_taskwait): New prototypes. (cxx_omp_clause_default_ctor): Add outer argument. (finish_omp_for): Add new clauses argument. * cp-gimplify.c (cxx_omp_finish_clause): New function. (cxx_omp_predetermined_sharing): Moved from semantics.c, rewritten. (cxx_omp_clause_default_ctor): Add outer argument. (cp_genericize_r): Walk OMP_CLAUSE_LASTPRIVATE_STMT. * cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_CLAUSE): Define. * parser.c (cp_parser_omp_for_loop): Parse collapsed for loops. Add par_clauses argument. If decl is present in parallel's lastprivate clause, change that clause to shared and add a lastprivate clause for decl to OMP_FOR_CLAUSES. Fix wording of error messages. Adjust finish_omp_for caller. Add clauses argument. Parse loops with random access iterators. (cp_parser_omp_clause_collapse, cp_parser_omp_clause_untied): New functions. (cp_parser_omp_for, cp_parser_omp_parallel): Adjust cp_parser_omp_for_loop callers. (cp_parser_omp_for_cond, cp_parser_omp_for_incr): New helper functions. (cp_parser_omp_clause_name): Handle collapse and untied clauses. (cp_parser_omp_clause_schedule): Handle auto schedule. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_COLLAPSE and PRAGMA_OMP_CLAUSE_UNTIED. (OMP_FOR_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_COLLAPSE. (OMP_TASK_CLAUSE_MASK): Define. (cp_parser_omp_task, cp_parser_omp_taskwait): New functions. (cp_parser_omp_construct): Handle PRAGMA_OMP_TASK. (cp_parser_pragma): Handle PRAGMA_OMP_TASK and PRAGMA_OMP_TASKWAIT. * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Handle OMP_CLAUSE_LASTPRIVATE_STMT. (tsubst_omp_for_iterator): New function. (dependent_omp_for_p): New function. (tsubst_expr) <case OMP_FOR>: Use it. Handle collapsed OMP_FOR loops. Adjust finish_omp_for caller. Handle loops with random access iterators. Adjust for OMP_FOR_{INIT,COND,INCR} changes. (tsubst_expr): Handle OMP_TASK. * semantics.c (cxx_omp_create_clause_info): New function. (finish_omp_clauses): Call it. Handle OMP_CLAUSE_UNTIED and OMP_CLAUSE_COLLAPSE. (cxx_omp_predetermined_sharing): Removed. * semantics.c (finish_omp_for): Allow pointer iterators. Use handle_omp_for_class_iterator and dependent_omp_for_p. Handle collapsed for loops. Adjust c_finish_omp_for caller. Add new clauses argument. Fix check for type dependent cond or incr. Set OMP_FOR_CLAUSES to clauses. Use cp_convert instead of fold_convert to convert incr amount to difference_type. Only fold if not in template. If decl is mentioned in lastprivate clause, set OMP_CLAUSE_LASTPRIVATE_STMT. Handle loops with random access iterators. Adjust for OMP_FOR_{INIT,COND,INCR} changes. (finish_omp_threadprivate): Allow static class members of the current class. (handle_omp_for_class_iterator, begin_omp_task, finish_omp_task, finish_omp_taskwait): New functions. * parser.c (cp_parser_binary_expression): Add prec argument. (cp_parser_assignment_expression): Adjust caller. * cp-tree.h (outer_curly_brace_block): New prototype. * decl.c (outer_curly_brace_block): No longer static. fortran/ * scanner.c (skip_free_comments, skip_fixed_comments): Handle tabs. * parse.c (next_free): Allow tab after !$omp. (decode_omp_directive): Handle !$omp task, !$omp taskwait and !$omp end task. (case_executable): Add ST_OMP_TASKWAIT. (case_exec_markers): Add ST_OMP_TASK. (gfc_ascii_statement): Handle ST_OMP_TASK, ST_OMP_END_TASK and ST_OMP_TASKWAIT. (parse_omp_structured_block, parse_executable): Handle ST_OMP_TASK. * gfortran.h (gfc_find_sym_in_expr): New prototype. (gfc_statement): Add ST_OMP_TASK, ST_OMP_END_TASK and ST_OMP_TASKWAIT. (gfc_omp_clauses): Add OMP_SCHED_AUTO to sched_kind, OMP_DEFAULT_FIRSTPRIVATE to default_sharing. Add collapse and untied fields. (gfc_exec_op): Add EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * f95-lang.c (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR, LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP, LANG_HOOKS_OMP_CLAUSE_DTOR, LANG_HOOKS_OMP_PRIVATE_OUTER_REF): Define. * trans.h (gfc_omp_clause_default_ctor): Add another argument. (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op, gfc_omp_clause_dtor, gfc_omp_private_outer_ref): New prototypes. * types.def (BT_ULONGLONG, BT_PTR_ULONGLONG, BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_VOID_PTR_PTR, BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): New. (BT_BOOL): Use integer type with BOOL_TYPE_SIZE rather than boolean_type_node. * dump-parse-tree.c (gfc_show_omp_node): Handle EXEC_OMP_TASK, EXEC_OMP_TASKWAIT, OMP_SCHED_AUTO, OMP_DEFAULT_FIRSTPRIVATE, untied and collapse clauses. (gfc_show_code_node): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * trans.c (gfc_trans_code): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * st.c (gfc_free_statement): Likewise. * resolve.c (gfc_resolve_blocks, resolve_code): Likewise. (find_sym_in_expr): Rename to... (gfc_find_sym_in_expr): ... this. No longer static. (resolve_allocate_expr, resolve_ordinary_assign): Adjust caller. * match.h (gfc_match_omp_task, gfc_match_omp_taskwait): New prototypes. * openmp.c (resolve_omp_clauses): Allow allocatable arrays in firstprivate, lastprivate, reduction, copyprivate and copyin clauses. (omp_current_do_code): Made static. (omp_current_do_collapse): New variable. (gfc_resolve_omp_do_blocks): Compute omp_current_do_collapse, clear omp_current_do_code and omp_current_do_collapse on return. (gfc_resolve_do_iterator): Handle collapsed do loops. (resolve_omp_do): Likewise, diagnose errorneous collapsed do loops. (OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED): Define. (gfc_match_omp_clauses): Handle default (firstprivate), schedule (auto), untied and collapse (n) clauses. (OMP_DO_CLAUSES): Add OMP_CLAUSE_COLLAPSE. (OMP_TASK_CLAUSES): Define. (gfc_match_omp_task, gfc_match_omp_taskwait): New functions. * trans-openmp.c (gfc_omp_private_outer_ref): New function. (gfc_omp_clause_default_ctor): Add outer argument. For allocatable arrays allocate them with the bounds of the outer var if outer var is allocated. (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op, gfc_omp_clause_dtor): New functions. (gfc_trans_omp_array_reduction): If decl is allocatable array, allocate it with outer var's bounds in OMP_CLAUSE_REDUCTION_INIT and deallocate it in OMP_CLAUSE_REDUCTION_MERGE. (gfc_omp_predetermined_sharing): Return OMP_CLAUSE_DEFAULT_SHARED for assumed-size arrays. (gfc_trans_omp_do): Add par_clauses argument. If dovar is present in lastprivate clause and do loop isn't simple, set OMP_CLAUSE_LASTPRIVATE_STMT. If dovar is present in parallel's lastprivate clause, change it to shared and add lastprivate clause to OMP_FOR_CLAUSES. Handle collapsed do loops. (gfc_trans_omp_directive): Adjust gfc_trans_omp_do callers. (gfc_trans_omp_parallel_do): Likewise. Move collapse clause to OMP_FOR from OMP_PARALLEL. (gfc_trans_omp_clauses): Handle OMP_SCHED_AUTO, OMP_DEFAULT_FIRSTPRIVATE, untied and collapse clauses. (gfc_trans_omp_task, gfc_trans_omp_taskwait): New functions. (gfc_trans_omp_directive): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. gcc/testsuite/ * gcc.dg/gomp/collapse-1.c: New test. * gcc.dg/gomp/nesting-1.c: New test. * g++.dg/gomp/task-1.C: New test. * g++.dg/gomp/predetermined-1.C: New test. * g++.dg/gomp/tls-4.C: New test. * gfortran.dg/gomp/collapse1.f90: New test. * gfortran.dg/gomp/sharing-3.f90: New test. * gcc.dg/gomp/pr27499.c (foo): Remove is unsigned dg-warning. * g++.dg/gomp/pr27499.C (foo): Likewise. * g++.dg/gomp/for-16.C (foo): Likewise. * g++.dg/gomp/tls-3.C: Remove dg-error, add S::s definition. * g++.dg/gomp/pr34607.C: Adjust dg-error location. * g++.dg/gomp/for-16.C (foo): Add a new dg-error. * gcc.dg/gomp/appendix-a/a.35.4.c: Add dg-warning. * gcc.dg/gomp/appendix-a/a.35.6.c: Likewise. * gfortran.dg/gomp/appendix-a/a.35.4.f90: Likewise. * gfortran.dg/gomp/appendix-a/a.35.6.f90: Likewise. * gfortran.dg/gomp/omp_parse1.f90: Remove !$omp tab test. * gfortran.dg/gomp/appendix-a/a.33.4.f90: Remove dg-error about allocatable array. * gfortran.dg/gomp/reduction1.f90: Likewise. libgomp/ * configure.ac (LIBGOMP_GNU_SYMBOL_VERSIONING): New AC_DEFINE. Substitute also OMP_*LOCK_25*. * configure: Regenerated. * config.h.in: Regenerated. * Makefile.am (libgomp_la_SOURCES): Add loop_ull.c, iter_ull.c, ptrlock.c and task.c. * Makefile.in: Regenerated. * testsuite/Makefile.in: Regenerated. * task.c: New file. * loop_ull.c: New file. * iter_ull.c: New file. * libgomp.h: Include ptrlock.h. (enum gomp_task_kind): New type. (struct gomp_team): Add task_lock, task_queue, task_count, task_running_count, single_count fields. Add work_share_list_free_lock ifndef HAVE_SYNC_BUILTINS. Remove work_share_lock, generation_mask, oldest_live_gen, num_live_gen and init_work_shares fields, add work work_share_list_alloc, work_share_list_free and work_share_chunk fields. Change work_shares from pointer to pointers into an array. Change ordered_release field into gomp_sem_t ** from flexible array member. Add implicit_task and initial_work_shares fields. Move close to the end of the struct. (struct gomp_team_state): Add single_count, last_work_share, active_level and level fields, remove work_share_generation. (gomp_barrier_handle_tasks): New prototype. (gomp_finish_task): New inline function. (struct gomp_work_share): Move chunk_size, end, incr into transparent union/struct, add chunk_size_ull, end_ll, incr_ll and next_ll fields. Reshuffle fields. Add next_alloc, next_ws, next_free and inline_ordered_team_ids fields, change ordered_team_ids into pointer from flexible array member. Add mode field. Put lock and next into a different cache line from most of the write-once fields. (gomp_iter_ull_static_next, gomp_iter_ull_dynamic_next_locked, gomp_iter_ull_guided_next_locked, gomp_iter_ull_dynamic_next, gomp_iter_ull_guided_next): New prototypes. (gomp_new_icv): New prototype. (struct gomp_thread): Add thread_pool and task fields. (struct gomp_thread_pool): New type. (gomp_new_team): New prototype. (gomp_team_start): Change type of last argument. (gomp_new_work_share): Removed. (gomp_init_work_share, gomp_fini_work_share): New prototypes. (gomp_work_share_init_done): New static inline. (gomp_throttled_spin_count_var, gomp_available_cpus, gomp_managed_threads): New extern decls. (gomp_init_task): New prototype. (gomp_spin_count_var): New extern var decl. (LIBGOMP_GNU_SYMBOL_VERSIONING): Undef if no visibility or no alias support, or if not PIC. (gomp_init_lock_30, gomp_destroy_lock_30, gomp_set_lock_30, gomp_unset_lock_30, gomp_test_lock_30, gomp_init_nest_lock_30, gomp_destroy_nest_lock_30, gomp_set_nest_lock_30, gomp_unset_nest_lock_30, gomp_test_nest_lock_30, gomp_init_lock_25, gomp_destroy_lock_25, gomp_set_lock_25, gomp_unset_lock_25, gomp_test_lock_25, gomp_init_nest_lock_25, gomp_destroy_nest_lock_25, gomp_set_nest_lock_25, gomp_unset_nest_lock_25, gomp_test_nest_lock_25): New prototypes. (omp_lock_symver, strong_alias): Define. (gomp_remaining_threads_count, gomp_remaining_threads_lock): New decls. (gomp_end_task): New. (struct gomp_task_icv, gomp_global_icv): New. (gomp_thread_limit_var, gomp_max_active_levels_var): New. (struct gomp_task): New. (gomp_nthreads_var, gomp_dyn_var, gomp_nest_var, gomp_run_sched_var, gomp_run_sched_chunk): Remove. (gomp_icv): New. (gomp_schedule_type): Reorder enum to match omp_sched_t. * team.c (struct gomp_thread_start_data): Add thread_pool and task fields. (gomp_thread_start): Add gomp_team_barrier_wait call. For non-nested case remove clearing of docked thread thr fields. Use pool fields instead of global gomp_* variables. Use gomp_barrier_wait_last when needed. Initialize ts.active_level. Create tasks for each member thread. (free_team): Only destroy team barrier, task_lock here and free it. (gomp_free_thread): Free last_team if non-NULL. (gomp_team_end): Call gomp_team_barrier_wait instead of gomp_barrier_wait. For nested case call one extra gomp_barrier_wait. Move here some destruction from free_team. Call free_team on pool->last_team if any, rather than freeing current team. Destroy work_share_list_free_lock ifndef HAVE_SYNC_BUILTINS. (gomp_new_icv): New function. (gomp_threads, gomp_threads_size, gomp_threads_used, gomp_threads_dock): Removed. (gomp_thread_destructor): New variable. (gomp_new_thread_pool, gomp_free_pool_helper, gomp_free_thread): New functions. (gomp_team_start): Create new pool if current thread doesn't have one. Use pool fields instead of global gomp_* variables. Initialize thread_pool field for new threads. Clear single_count. Change last argument from ws to team, don't create new team, set ts.work_share to &team->work_shares[0] and clear ts.last_work_share. Don't clear ts.work_share_generation. If number of threads changed, adjust atomically gomp_managed_threads. Use gomp_init_task instead of gomp_new_task, set thr->task to the corresponding implicit_task array entry. Create tasks for each member thread. Initialize ts.level. (initialize_team): Call pthread_key_create on gomp_thread_destructor. (team_destructor): New function. (new_team): Removed. (gomp_new_team): New function. (free_team): Free gomp_work_share blocks chained through next_alloc, instead of freeing work_shares and destroying work_share_lock. (gomp_team_end): Call gomp_fini_work_share. If number of threads changed, adjust atomically gomp_managed_threads. Use gomp_end_task. * barrier.c (GOMP_barrier): Call gomp_team_barrier_wait instead of gomp_barrier_wait. * single.c (GOMP_single_copy_start): Call gomp_team_barrier_wait instead of gomp_barrier_wait. Call gomp_work_share_init_done if gomp_work_share_start returned true. Don't unlock ws->lock. (GOMP_single_copy_end): Call gomp_team_barrier_wait instead of gomp_barrier_wait. (GOMP_single_start): Rewritten if HAVE_SYNC_BUILTINS. Call gomp_work_share_init_done if gomp_work_share_start returned true. Don't unlock ws->lock. * work.c: Include stddef.h. (free_work_share): Use work_share_list_free_lock instead of atomic chaining ifndef HAVE_SYNC_BUILTINS. Add team argument. Call gomp_fini_work_share and then either free ws if orphaned, or put it into work_share_list_free list of the current team. (alloc_work_share, gomp_init_work_share, gomp_fini_work_share): New functions. (gomp_work_share_start, gomp_work_share_end, gomp_work_share_end_nowait): Rewritten. * omp_lib.f90.in Change some tabs to spaces to prevent warnings. (openmp_version): Set to 200805. (omp_sched_kind, omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): New parameters. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New interfaces. * omp_lib.h.in (openmp_version): Set to 200805. (omp_sched_kind, omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): New parameters. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New externals. * loop.c: Include limits.h. (GOMP_loop_runtime_next, GOMP_loop_ordered_runtime_next): Handle GFS_AUTO. (GOMP_loop_runtime_start, GOMP_loop_ordered_runtime_start): Likewise. Use gomp_icv. (gomp_loop_static_start, gomp_loop_dynamic_start): Clear ts.static_trip here. (gomp_loop_static_start, gomp_loop_ordered_static_start): Call gomp_work_share_init_done after gomp_loop_init. Don't unlock ws->lock. (gomp_loop_dynamic_start, gomp_loop_guided_start): Call gomp_work_share_init_done after gomp_loop_init. If HAVE_SYNC_BUILTINS, don't unlock ws->lock, otherwise lock it. (gomp_loop_ordered_dynamic_start, gomp_loop_ordered_guided_start): Call gomp_work_share_init_done after gomp_loop_init. Lock ws->lock. (gomp_parallel_loop_start): Call gomp_new_team instead of gomp_new_work_share. Call gomp_loop_init on &team->work_shares[0]. Adjust gomp_team_start caller. Pass 0 as second argument to gomp_resolve_num_threads. (gomp_loop_init): For GFS_DYNAMIC, multiply ws->chunk_size by incr. If adding ws->chunk_size nthreads + 1 times after end won't overflow, set ws->mode to 1. * libgomp_g.h (GOMP_loop_ull_static_start, GOMP_loop_ull_dynamic_start, GOMP_loop_ull_guided_start, GOMP_loop_ull_runtime_start, GOMP_loop_ull_ordered_static_start, GOMP_loop_ull_ordered_dynamic_start, GOMP_loop_ull_ordered_guided_start, GOMP_loop_ull_ordered_runtime_start, GOMP_loop_ull_static_next, GOMP_loop_ull_dynamic_next, GOMP_loop_ull_guided_next, GOMP_loop_ull_runtime_next, GOMP_loop_ull_ordered_static_next, GOMP_loop_ull_ordered_dynamic_next, GOMP_loop_ull_ordered_guided_next, GOMP_loop_ull_ordered_runtime_next, GOMP_task, GOMP_taskwait): New prototypes. * libgomp.map: Export lock routines also @@OMP_2.0. (GOMP_loop_ordered_dynamic_first, GOMP_loop_ordered_guided_first, GOMP_loop_ordered_runtime_first, GOMP_loop_ordered_static_first): Remove. (GOMP_loop_ull_dynamic_next, GOMP_loop_ull_dynamic_start, GOMP_loop_ull_guided_next, GOMP_loop_ull_guided_start, GOMP_loop_ull_ordered_dynamic_next, GOMP_loop_ull_ordered_dynamic_start, GOMP_loop_ull_ordered_guided_next, GOMP_loop_ull_ordered_guided_start, GOMP_loop_ull_ordered_runtime_next, GOMP_loop_ull_ordered_runtime_start, GOMP_loop_ull_ordered_static_next, GOMP_loop_ull_ordered_static_start, GOMP_loop_ull_runtime_next, GOMP_loop_ull_runtime_start, GOMP_loop_ull_static_next, GOMP_loop_ull_static_start, GOMP_task, GOMP_taskwait): Export @@GOMP_2.0. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level, omp_set_schedule_, omp_set_schedule_8_, omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_, omp_set_max_active_levels_, omp_set_max_active_levels_8_, omp_get_max_active_levels_, omp_get_level_, omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_, omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_): New exports @@OMP_3.0. * omp.h.in (omp_sched_t): New type. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New prototypes. * env.c (gomp_spin_count_var, gomp_throttled_spin_count_var, gomp_available_cpus, gomp_managed_threads, gomp_max_active_levels_var, gomp_thread_limit_var, gomp_remaining_threads_count, gomp_remaining_threads_lock): New variables. (parse_spincount): New function. (initialize_env): Call gomp_init_num_threads unconditionally. Initialize gomp_available_cpus. Call parse_spincount, initialize gomp_{,throttled_}spin_count_var depending on presence and value of OMP_WAIT_POLICY and GOMP_SPINCOUNT env vars. Handle GOMP_BLOCKTIME env var. Handle OMP_WAIT_POLICY, OMP_MAX_ACTIVE_LEVELS, OMP_THREAD_LIMIT, OMP_STACKSIZE env vars. Handle unit specification for GOMP_STACKSIZE. Initialize gomp_remaining_threads_count and gomp_remaining_threads_lock if needed. Use gomp_global_icv. (gomp_nthreads_var, gomp_dyn_var, gomp_nest_var, gomp_run_sched_var, gomp_run_sched_chunk): Remove. (gomp_global_icv): New. (parse_schedule): Use it. Parse "auto". (omp_set_num_threads): Use gomp_icv. (omp_set_dynamic, omp_get_dynamic, omp_set_nested, omp_get_nested): Likewise. (omp_get_max_threads): Move from parallel.c. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels): New functions, add ialias. (parse_stacksize, parse_wait_policy): New functions. * fortran.c: Rewrite lock wrappers, if symbol versioning provide both wrappers for compatibility and new locks. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New ialias_redirect. (omp_set_schedule_, omp_set_schedule_8_, omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_, omp_set_max_active_levels_, omp_set_max_active_levels_8_, omp_get_max_active_levels_, omp_get_level_, omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_, omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_): New functions. * parallel.c: Include limits.h. (gomp_resolve_num_threads): Add count argument. Rewritten. (GOMP_parallel_start): Call gomp_new_team and pass that as last argument to gomp_team_start. Pass 0 as second argument to gomp_resolve_num_threads. (GOMP_parallel_end): Decrease gomp_remaining_threads_count if gomp_thread_limit_var != ULONG_MAX. (omp_in_parallel): Implement using ts.active_level. (omp_get_max_threads): Move to env.c. (omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New functions, add ialias. * sections.c (GOMP_sections_start): Call gomp_work_share_init_done after gomp_sections_init. If HAVE_SYNC_BUILTINS, call gomp_iter_dynamic_next instead of the _locked variant and don't take lock around it, otherwise acquire it before calling gomp_iter_dynamic_next_locked. (GOMP_sections_next): If HAVE_SYNC_BUILTINS, call gomp_iter_dynamic_next instead of the _locked variant and don't take lock around it. (GOMP_parallel_sections_start): Call gomp_new_team instead of gomp_new_work_share. Call gomp_sections_init on &team->work_shares[0]. Adjust gomp_team_start caller. Pass count as second argument to gomp_resolve_num_threads, don't adjust num_threads after the call. Use gomp_icv. * iter.c (gomp_iter_dynamic_next_locked): Don't multiply ws->chunk_size by incr. (gomp_iter_dynamic_next): Likewise. If ws->mode, use more efficient code. * libgomp_f.h.in (omp_lock_25_arg_t, omp_nest_lock_25_arg_t): New types. (omp_lock_25_arg, omp_nest_lock_25_arg): New macros. (omp_check_defines): Check even the compat defines. * config/linux/ptrlock.c: New file. * config/linux/ptrlock.h: New file. * config/linux/wait.h: New file. * config/posix/ptrlock.c: New file. * config/posix/ptrlock.h: New file. * config/linux/bar.h (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New prototypes. (gomp_team_barrier_set_task_pending, gomp_team_barrier_clear_task_pending, gomp_team_barrier_set_waiting_for_tasks, gomp_team_barrier_waiting_for_tasks, gomp_team_barrier_done): New inlines. (gomp_barrier_t): Rewritten. (gomp_barrier_state_t): New typedef. (gomp_barrier_init, gomp_barrier_reinit, gomp_barrier_destroy, gomp_barrier_wait_start): Rewritten. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_barrier_last_thread, gomp_barrier_wait_last): New static inlines. * config/linux/bar.c: Include wait.h instead of libgomp.h and futex.h. (gomp_barrier_wait_end): Rewritten. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake, gomp_barrier_wait_last): New functions. * config/posix/bar.h (gomp_barrier_t): Add generation field. (gomp_barrier_state_t): New typedef. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New prototypes. (gomp_barrier_wait_start): Or all but low 2 bits from generation into the return value. Return gomp_barrier_state_t. (gomp_team_barrier_set_task_pending, gomp_team_barrier_clear_task_pending, gomp_team_barrier_set_waiting_for_tasks, gomp_team_barrier_waiting_for_tasks, gomp_team_barrier_done): New inlines. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_barrier_last_thread, gomp_barrier_wait_last): New static inlines. * config/posix/bar.c (gomp_barrier_init): Clear generation field. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New functions. * config/linux/mutex.c: Include wait.h instead of libgomp.h and futex.h. (gomp_futex_wake, gomp_futex_wait): New variables. (gomp_mutex_lock_slow): Call do_wait instead of futex_wait. * config/linux/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. Include wait.h instead of libgomp.h and futex.h. (gomp_set_nest_lock_25): Call do_wait instead of futex_wait. * config/posix95/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. * config/posix/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. * config/linux/proc.c (gomp_init_num_threads): Use gomp_global_icv. (get_num_procs, gomp_dynamic_max_threads): Use gomp_icv. * config/posix/proc.c, config/mingw32/proc.c: Similarly. * config/linux/powerpc/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/alpha/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/x86/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/s390/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/ia64/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/sparc/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/sem.c: Include wait.h instead of libgomp.h and futex.h. (gomp_sem_wait_slow): Call do_wait instead of futex_wait. * config/linux/affinity.c: Assume HAVE_SYNC_BUILTINS. * config/linux/omp-lock.h (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_nest_lock_t): Change owner into void *, add lock field. * config/posix95/omp-lock.h: Include semaphore.h. (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_lock_t): Use sem_t instead of mutex if semaphores aren't broken. (omp_nest_lock_t): Likewise. Change owner to void *. * config/posix/omp-lock.h: Include semaphore.h. (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_lock_t): Use sem_t instead of mutex if semaphores aren't broken. (omp_nest_lock_t): Likewise. Add owner field. * testsuite/libgomp.c/collapse-1.c: New test. * testsuite/libgomp.c/collapse-2.c: New test. * testsuite/libgomp.c/collapse-3.c: New test. * testsuite/libgomp.c/icv-1.c: New test. * testsuite/libgomp.c/icv-2.c: New test. * testsuite/libgomp.c/lib-2.c: New test. * testsuite/libgomp.c/lock-1.c: New test. * testsuite/libgomp.c/lock-2.c: New test. * testsuite/libgomp.c/lock-3.c: New test. * testsuite/libgomp.c/loop-4.c: New test. * testsuite/libgomp.c/loop-5.c: New test. * testsuite/libgomp.c/loop-6.c: New test. * testsuite/libgomp.c/loop-7.c: New test. * testsuite/libgomp.c/loop-8.c: New test. * testsuite/libgomp.c/loop-9.c: New test. * testsuite/libgomp.c/nested-3.c: New test. * testsuite/libgomp.c/nestedfn-6.c: New test. * testsuite/libgomp.c/sort-1.c: New test. * testsuite/libgomp.c/task-1.c: New test. * testsuite/libgomp.c/task-2.c: New test. * testsuite/libgomp.c/task-3.c: New test. * testsuite/libgomp.c/task-4.c: New test. * testsuite/libgomp.c++/c++.exp: Add libstdc++-v3 build includes to C++ testsuite default compiler options. * testsuite/libgomp.c++/collapse-1.C: New test. * testsuite/libgomp.c++/collapse-2.C: New test. * testsuite/libgomp.c++/ctor-10.C: New test. * testsuite/libgomp.c++/for-1.C: New test. * testsuite/libgomp.c++/for-2.C: New test. * testsuite/libgomp.c++/for-3.C: New test. * testsuite/libgomp.c++/for-4.C: New test. * testsuite/libgomp.c++/for-5.C: New test. * testsuite/libgomp.c++/loop-8.C: New test. * testsuite/libgomp.c++/loop-9.C: New test. * testsuite/libgomp.c++/loop-10.C: New test. * testsuite/libgomp.c++/task-1.C: New test. * testsuite/libgomp.c++/task-2.C: New test. * testsuite/libgomp.c++/task-3.C: New test. * testsuite/libgomp.c++/task-4.C: New test. * testsuite/libgomp.c++/task-5.C: New test. * testsuite/libgomp.c++/task-6.C: New test. * testsuite/libgomp.fortran/allocatable1.f90: New test. * testsuite/libgomp.fortran/allocatable2.f90: New test. * testsuite/libgomp.fortran/allocatable3.f90: New test. * testsuite/libgomp.fortran/allocatable4.f90: New test. * testsuite/libgomp.fortran/collapse1.f90: New test. * testsuite/libgomp.fortran/collapse2.f90: New test. * testsuite/libgomp.fortran/collapse3.f90: New test. * testsuite/libgomp.fortran/collapse4.f90: New test. * testsuite/libgomp.fortran/lastprivate1.f90: New test. * testsuite/libgomp.fortran/lastprivate2.f90: New test. * testsuite/libgomp.fortran/lib4.f90: New test. * testsuite/libgomp.fortran/lock-1.f90: New test. * testsuite/libgomp.fortran/lock-2.f90: New test. * testsuite/libgomp.fortran/nested1.f90: New test. * testsuite/libgomp.fortran/nestedfn4.f90: New test. * testsuite/libgomp.fortran/strassen.f90: New test. * testsuite/libgomp.fortran/tabs1.f90: New test. * testsuite/libgomp.fortran/tabs2.f: New test. * testsuite/libgomp.fortran/task1.f90: New test. * testsuite/libgomp.fortran/task2.f90: New test. * testsuite/libgomp.fortran/vla4.f90: Add dg-warning. * testsuite/libgomp.fortran/vla5.f90: Likewise. * testsuite/libgomp.c/pr26943-2.c: Likewise. * testsuite/libgomp.c/pr26943-3.c: Likewise. * testsuite/libgomp.c/pr26943-4.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@136433 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog84
-rw-r--r--gcc/fortran/dump-parse-tree.c13
-rw-r--r--gcc/fortran/f95-lang.c8
-rw-r--r--gcc/fortran/gfortran.h15
-rw-r--r--gcc/fortran/match.h2
-rw-r--r--gcc/fortran/openmp.c178
-rw-r--r--gcc/fortran/parse.c23
-rw-r--r--gcc/fortran/resolve.c19
-rw-r--r--gcc/fortran/scanner.c18
-rw-r--r--gcc/fortran/st.c2
-rw-r--r--gcc/fortran/trans-openmp.c535
-rw-r--r--gcc/fortran/trans.c2
-rw-r--r--gcc/fortran/trans.h6
-rw-r--r--gcc/fortran/types.def21
14 files changed, 777 insertions, 149 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 826b40972f9..5df5de5cf74 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,87 @@
+2008-06-06 Jakub Jelinek <jakub@redhat.com>
+
+ * scanner.c (skip_free_comments, skip_fixed_comments): Handle tabs.
+ * parse.c (next_free): Allow tab after !$omp.
+ (decode_omp_directive): Handle !$omp task, !$omp taskwait
+ and !$omp end task.
+ (case_executable): Add ST_OMP_TASKWAIT.
+ (case_exec_markers): Add ST_OMP_TASK.
+ (gfc_ascii_statement): Handle ST_OMP_TASK, ST_OMP_END_TASK and
+ ST_OMP_TASKWAIT.
+ (parse_omp_structured_block, parse_executable): Handle ST_OMP_TASK.
+ * gfortran.h (gfc_find_sym_in_expr): New prototype.
+ (gfc_statement): Add ST_OMP_TASK, ST_OMP_END_TASK and ST_OMP_TASKWAIT.
+ (gfc_omp_clauses): Add OMP_SCHED_AUTO to sched_kind,
+ OMP_DEFAULT_FIRSTPRIVATE to default_sharing. Add collapse and
+ untied fields.
+ (gfc_exec_op): Add EXEC_OMP_TASK and EXEC_OMP_TASKWAIT.
+ * f95-lang.c (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR,
+ LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP, LANG_HOOKS_OMP_CLAUSE_DTOR,
+ LANG_HOOKS_OMP_PRIVATE_OUTER_REF): Define.
+ * trans.h (gfc_omp_clause_default_ctor): Add another argument.
+ (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op,
+ gfc_omp_clause_dtor, gfc_omp_private_outer_ref): New prototypes.
+ * types.def (BT_ULONGLONG, BT_PTR_ULONGLONG,
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_FN_VOID_PTR_PTR, BT_PTR_FN_VOID_PTR_PTR,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): New.
+ (BT_BOOL): Use integer type with BOOL_TYPE_SIZE rather
+ than boolean_type_node.
+ * dump-parse-tree.c (gfc_show_omp_node): Handle EXEC_OMP_TASK,
+ EXEC_OMP_TASKWAIT, OMP_SCHED_AUTO, OMP_DEFAULT_FIRSTPRIVATE,
+ untied and collapse clauses.
+ (gfc_show_code_node): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT.
+ * trans.c (gfc_trans_code): Handle EXEC_OMP_TASK and
+ EXEC_OMP_TASKWAIT.
+ * st.c (gfc_free_statement): Likewise.
+ * resolve.c (gfc_resolve_blocks, resolve_code): Likewise.
+ (find_sym_in_expr): Rename to...
+ (gfc_find_sym_in_expr): ... this. No longer static.
+ (resolve_allocate_expr, resolve_ordinary_assign): Adjust caller.
+ * match.h (gfc_match_omp_task, gfc_match_omp_taskwait): New
+ prototypes.
+ * openmp.c (resolve_omp_clauses): Allow allocatable arrays in
+ firstprivate, lastprivate, reduction, copyprivate and copyin
+ clauses.
+ (omp_current_do_code): Made static.
+ (omp_current_do_collapse): New variable.
+ (gfc_resolve_omp_do_blocks): Compute omp_current_do_collapse,
+ clear omp_current_do_code and omp_current_do_collapse on return.
+ (gfc_resolve_do_iterator): Handle collapsed do loops.
+ (resolve_omp_do): Likewise, diagnose errorneous collapsed do loops.
+ (OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED): Define.
+ (gfc_match_omp_clauses): Handle default (firstprivate),
+ schedule (auto), untied and collapse (n) clauses.
+ (OMP_DO_CLAUSES): Add OMP_CLAUSE_COLLAPSE.
+ (OMP_TASK_CLAUSES): Define.
+ (gfc_match_omp_task, gfc_match_omp_taskwait): New functions.
+ * trans-openmp.c (gfc_omp_private_outer_ref): New function.
+ (gfc_omp_clause_default_ctor): Add outer argument. For allocatable
+ arrays allocate them with the bounds of the outer var if outer
+ var is allocated.
+ (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op,
+ gfc_omp_clause_dtor): New functions.
+ (gfc_trans_omp_array_reduction): If decl is allocatable array,
+ allocate it with outer var's bounds in OMP_CLAUSE_REDUCTION_INIT
+ and deallocate it in OMP_CLAUSE_REDUCTION_MERGE.
+ (gfc_omp_predetermined_sharing): Return OMP_CLAUSE_DEFAULT_SHARED
+ for assumed-size arrays.
+ (gfc_trans_omp_do): Add par_clauses argument. If dovar is
+ present in lastprivate clause and do loop isn't simple,
+ set OMP_CLAUSE_LASTPRIVATE_STMT. If dovar is present in
+ parallel's lastprivate clause, change it to shared and add
+ lastprivate clause to OMP_FOR_CLAUSES. Handle collapsed do loops.
+ (gfc_trans_omp_directive): Adjust gfc_trans_omp_do callers.
+ (gfc_trans_omp_parallel_do): Likewise. Move collapse clause to
+ OMP_FOR from OMP_PARALLEL.
+ (gfc_trans_omp_clauses): Handle OMP_SCHED_AUTO,
+ OMP_DEFAULT_FIRSTPRIVATE, untied and collapse clauses.
+ (gfc_trans_omp_task, gfc_trans_omp_taskwait): New functions.
+ (gfc_trans_omp_directive): Handle EXEC_OMP_TASK and
+ EXEC_OMP_TASKWAIT.
+
2008-06-04 Janus Weil <janus@gcc.gnu.org>
PR fortran/36322
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 44a4941e7b4..80ff5bcecb7 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -848,6 +848,8 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_PARALLEL_WORKSHARE: name = "PARALLEL WORKSHARE"; break;
case EXEC_OMP_SECTIONS: name = "SECTIONS"; break;
case EXEC_OMP_SINGLE: name = "SINGLE"; break;
+ case EXEC_OMP_TASK: name = "TASK"; break;
+ case EXEC_OMP_TASKWAIT: name = "TASKWAIT"; break;
case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break;
default:
gcc_unreachable ();
@@ -863,6 +865,7 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_SINGLE:
case EXEC_OMP_WORKSHARE:
case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_TASK:
omp_clauses = c->ext.omp_clauses;
break;
case EXEC_OMP_CRITICAL:
@@ -878,6 +881,7 @@ show_omp_node (int level, gfc_code *c)
}
return;
case EXEC_OMP_BARRIER:
+ case EXEC_OMP_TASKWAIT:
return;
default:
break;
@@ -907,6 +911,7 @@ show_omp_node (int level, gfc_code *c)
case OMP_SCHED_DYNAMIC: type = "DYNAMIC"; break;
case OMP_SCHED_GUIDED: type = "GUIDED"; break;
case OMP_SCHED_RUNTIME: type = "RUNTIME"; break;
+ case OMP_SCHED_AUTO: type = "AUTO"; break;
default:
gcc_unreachable ();
}
@@ -926,7 +931,7 @@ show_omp_node (int level, gfc_code *c)
case OMP_DEFAULT_NONE: type = "NONE"; break;
case OMP_DEFAULT_PRIVATE: type = "PRIVATE"; break;
case OMP_DEFAULT_SHARED: type = "SHARED"; break;
- case OMP_SCHED_RUNTIME: type = "RUNTIME"; break;
+ case OMP_DEFAULT_FIRSTPRIVATE: type = "FIRSTPRIVATE"; break;
default:
gcc_unreachable ();
}
@@ -934,6 +939,10 @@ show_omp_node (int level, gfc_code *c)
}
if (omp_clauses->ordered)
fputs (" ORDERED", dumpfile);
+ if (omp_clauses->untied)
+ fputs (" UNTIED", dumpfile);
+ if (omp_clauses->collapse)
+ fprintf (dumpfile, " COLLAPSE(%d)", omp_clauses->collapse);
for (list_type = 0; list_type < OMP_LIST_NUM; list_type++)
if (omp_clauses->lists[list_type] != NULL
&& list_type != OMP_LIST_COPYPRIVATE)
@@ -1806,6 +1815,8 @@ show_code_node (int level, gfc_code *c)
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKWAIT:
case EXEC_OMP_WORKSHARE:
show_omp_node (level, c);
break;
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 63c380b61ea..42ab57a9606 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -115,8 +115,12 @@ static alias_set_type gfc_get_alias_set (tree);
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
+#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR
+#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
+#undef LANG_HOOKS_OMP_CLAUSE_DTOR
#undef LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR
#undef LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE
+#undef LANG_HOOKS_OMP_PRIVATE_OUTER_REF
#undef LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES
#undef LANG_HOOKS_BUILTIN_FUNCTION
#undef LANG_HOOKS_GET_ARRAY_DESCR_INFO
@@ -137,8 +141,12 @@ static alias_set_type gfc_get_alias_set (tree);
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE gfc_omp_privatize_by_reference
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING gfc_omp_predetermined_sharing
#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR gfc_omp_clause_default_ctor
+#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR gfc_omp_clause_copy_ctor
+#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP gfc_omp_clause_assign_op
+#define LANG_HOOKS_OMP_CLAUSE_DTOR gfc_omp_clause_dtor
#define LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR gfc_omp_disregard_value_expr
#define LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE gfc_omp_private_debug_clause
+#define LANG_HOOKS_OMP_PRIVATE_OUTER_REF gfc_omp_private_outer_ref
#define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
gfc_omp_firstprivatize_type_sizes
#define LANG_HOOKS_BUILTIN_FUNCTION gfc_builtin_function
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index d4f9771e610..8665a48c566 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -228,7 +228,8 @@ typedef enum
ST_OMP_END_WORKSHARE, ST_OMP_DO, ST_OMP_FLUSH, ST_OMP_MASTER, ST_OMP_ORDERED,
ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
- ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_PROCEDURE,
+ ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_OMP_TASK, ST_OMP_END_TASK,
+ ST_OMP_TASKWAIT, ST_PROCEDURE,
ST_GET_FCN_CHARACTERISTICS, ST_NONE
}
gfc_statement;
@@ -927,7 +928,8 @@ typedef struct gfc_omp_clauses
OMP_SCHED_STATIC,
OMP_SCHED_DYNAMIC,
OMP_SCHED_GUIDED,
- OMP_SCHED_RUNTIME
+ OMP_SCHED_RUNTIME,
+ OMP_SCHED_AUTO
} sched_kind;
struct gfc_expr *chunk_size;
enum
@@ -935,9 +937,11 @@ typedef struct gfc_omp_clauses
OMP_DEFAULT_UNKNOWN,
OMP_DEFAULT_NONE,
OMP_DEFAULT_PRIVATE,
- OMP_DEFAULT_SHARED
+ OMP_DEFAULT_SHARED,
+ OMP_DEFAULT_FIRSTPRIVATE
} default_sharing;
- bool nowait, ordered;
+ int collapse;
+ bool nowait, ordered, untied;
}
gfc_omp_clauses;
@@ -1760,7 +1764,7 @@ typedef enum
EXEC_OMP_PARALLEL_SECTIONS, EXEC_OMP_PARALLEL_WORKSHARE,
EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE,
EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT,
- EXEC_OMP_END_SINGLE
+ EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT
}
gfc_exec_op;
@@ -2040,6 +2044,7 @@ bool gfc_post_options (const char **);
/* iresolve.c */
const char * gfc_get_string (const char *, ...) ATTRIBUTE_PRINTF_1;
+bool gfc_find_sym_in_expr (gfc_symbol *, gfc_expr *);
/* error.c */
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 3f8d31074e8..5ee91fb62de 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -119,6 +119,8 @@ match gfc_match_omp_parallel_sections (void);
match gfc_match_omp_parallel_workshare (void);
match gfc_match_omp_sections (void);
match gfc_match_omp_single (void);
+match gfc_match_omp_task (void);
+match gfc_match_omp_taskwait (void);
match gfc_match_omp_threadprivate (void);
match gfc_match_omp_workshare (void);
match gfc_match_omp_end_nowait (void);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 9c0bae497bf..28f1cc24dfd 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -182,6 +182,8 @@ cleanup:
#define OMP_CLAUSE_SCHEDULE (1 << 9)
#define OMP_CLAUSE_DEFAULT (1 << 10)
#define OMP_CLAUSE_ORDERED (1 << 11)
+#define OMP_CLAUSE_COLLAPSE (1 << 12)
+#define OMP_CLAUSE_UNTIED (1 << 13)
/* Match OpenMP directive clauses. MASK is a bitmask of
clauses that are allowed for a particular directive. */
@@ -335,6 +337,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
c->default_sharing = OMP_DEFAULT_PRIVATE;
else if (gfc_match ("default ( none )") == MATCH_YES)
c->default_sharing = OMP_DEFAULT_NONE;
+ else if (gfc_match ("default ( firstprivate )") == MATCH_YES)
+ c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
continue;
}
@@ -351,10 +355,13 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
c->sched_kind = OMP_SCHED_GUIDED;
else if (gfc_match ("runtime") == MATCH_YES)
c->sched_kind = OMP_SCHED_RUNTIME;
+ else if (gfc_match ("auto") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_AUTO;
if (c->sched_kind != OMP_SCHED_NONE)
{
match m = MATCH_NO;
- if (c->sched_kind != OMP_SCHED_RUNTIME)
+ if (c->sched_kind != OMP_SCHED_RUNTIME
+ && c->sched_kind != OMP_SCHED_AUTO)
m = gfc_match (" , %e )", &c->chunk_size);
if (m != MATCH_YES)
m = gfc_match_char (')');
@@ -372,6 +379,36 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
c->ordered = needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_UNTIED) && !c->untied
+ && gfc_match ("untied") == MATCH_YES)
+ {
+ c->untied = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_COLLAPSE) && !c->collapse)
+ {
+ gfc_expr *cexpr = NULL;
+ match m = gfc_match ("collapse ( %e )", &cexpr);
+
+ if (m == MATCH_YES)
+ {
+ int collapse;
+ const char *p = gfc_extract_int (cexpr, &collapse);
+ if (p)
+ {
+ gfc_error (p);
+ collapse = 1;
+ }
+ else if (collapse <= 0)
+ {
+ gfc_error ("COLLAPSE clause argument not constant positive integer at %C");
+ collapse = 1;
+ }
+ c->collapse = collapse;
+ gfc_free_expr (cexpr);
+ continue;
+ }
+ }
break;
}
@@ -393,10 +430,13 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
#define OMP_DO_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
- | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED)
+ | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE)
#define OMP_SECTIONS_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
+#define OMP_TASK_CLAUSES \
+ (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
+ | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED)
match
gfc_match_omp_parallel (void)
@@ -411,6 +451,29 @@ gfc_match_omp_parallel (void)
match
+gfc_match_omp_task (void)
+{
+ gfc_omp_clauses *c;
+ if (gfc_match_omp_clauses (&c, OMP_TASK_CLAUSES) != MATCH_YES)
+ return MATCH_ERROR;
+ new_st.op = EXEC_OMP_TASK;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_taskwait (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ return MATCH_ERROR;
+ new_st.op = EXEC_OMP_TASKWAIT;
+ new_st.ext.omp_clauses = NULL;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_critical (void)
{
char n[GFC_MAX_SYMBOL_LEN+1];
@@ -809,9 +872,6 @@ resolve_omp_clauses (gfc_code *code)
if (!n->sym->attr.threadprivate)
gfc_error ("Non-THREADPRIVATE object '%s' in COPYIN clause"
" at %L", n->sym->name, &code->loc);
- if (n->sym->attr.allocatable)
- gfc_error ("COPYIN clause object '%s' is ALLOCATABLE at %L",
- n->sym->name, &code->loc);
if (n->sym->ts.type == BT_DERIVED && n->sym->ts.derived->attr.alloc_comp)
gfc_error ("COPYIN clause object '%s' at %L has ALLOCATABLE components",
n->sym->name, &code->loc);
@@ -823,9 +883,6 @@ resolve_omp_clauses (gfc_code *code)
if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
gfc_error ("Assumed size array '%s' in COPYPRIVATE clause "
"at %L", n->sym->name, &code->loc);
- if (n->sym->attr.allocatable)
- gfc_error ("COPYPRIVATE clause object '%s' is ALLOCATABLE "
- "at %L", n->sym->name, &code->loc);
if (n->sym->ts.type == BT_DERIVED && n->sym->ts.derived->attr.alloc_comp)
gfc_error ("COPYPRIVATE clause object '%s' at %L has ALLOCATABLE components",
n->sym->name, &code->loc);
@@ -856,9 +913,6 @@ resolve_omp_clauses (gfc_code *code)
if (n->sym->attr.pointer)
gfc_error ("POINTER object '%s' in %s clause at %L",
n->sym->name, name, &code->loc);
- if (n->sym->attr.allocatable)
- gfc_error ("%s clause object '%s' is ALLOCATABLE at %L",
- name, n->sym->name, &code->loc);
/* Variables in REDUCTION-clauses must be of intrinsic type (flagged below). */
if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST) &&
n->sym->ts.type == BT_DERIVED && n->sym->ts.derived->attr.alloc_comp)
@@ -1246,15 +1300,34 @@ struct omp_context
struct pointer_set_t *private_iterators;
struct omp_context *previous;
} *omp_current_ctx;
-gfc_code *omp_current_do_code;
-
+static gfc_code *omp_current_do_code;
+static int omp_current_do_collapse;
void
gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
{
if (code->block->next && code->block->next->op == EXEC_DO)
- omp_current_do_code = code->block->next;
+ {
+ int i;
+ gfc_code *c;
+
+ omp_current_do_code = code->block->next;
+ omp_current_do_collapse = code->ext.omp_clauses->collapse;
+ for (i = 1, c = omp_current_do_code; i < omp_current_do_collapse; i++)
+ {
+ c = c->block;
+ if (c->op != EXEC_DO || c->next == NULL)
+ break;
+ c = c->next;
+ if (c->op != EXEC_DO)
+ break;
+ }
+ if (i < omp_current_do_collapse || omp_current_do_collapse <= 0)
+ omp_current_do_collapse = 1;
+ }
gfc_resolve_blocks (code->block, ns);
+ omp_current_do_collapse = 0;
+ omp_current_do_code = NULL;
}
@@ -1294,6 +1367,8 @@ void
gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
{
struct omp_context *ctx;
+ int i = omp_current_do_collapse;
+ gfc_code *c = omp_current_do_code;
if (sym->attr.threadprivate)
return;
@@ -1301,8 +1376,14 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
/* !$omp do and !$omp parallel do iteration variable is predetermined
private just in the !$omp do resp. !$omp parallel do construct,
with no implications for the outer parallel constructs. */
- if (code == omp_current_do_code)
- return;
+
+ while (i-- >= 1)
+ {
+ if (code == c)
+ return;
+
+ c = c->block->next;
+ }
for (ctx = omp_current_ctx; ctx; ctx = ctx->previous)
{
@@ -1326,8 +1407,8 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
static void
resolve_omp_do (gfc_code *code)
{
- gfc_code *do_code;
- int list;
+ gfc_code *do_code, *c;
+ int list, i, collapse;
gfc_namelist *n;
gfc_symbol *dovar;
@@ -1335,11 +1416,17 @@ resolve_omp_do (gfc_code *code)
resolve_omp_clauses (code);
do_code = code->block->next;
- if (do_code->op == EXEC_DO_WHILE)
- gfc_error ("!$OMP DO cannot be a DO WHILE or DO without loop control "
- "at %L", &do_code->loc);
- else
+ collapse = code->ext.omp_clauses->collapse;
+ if (collapse <= 0)
+ collapse = 1;
+ for (i = 1; i <= collapse; i++)
{
+ if (do_code->op == EXEC_DO_WHILE)
+ {
+ gfc_error ("!$OMP DO cannot be a DO WHILE or DO without loop control "
+ "at %L", &do_code->loc);
+ break;
+ }
gcc_assert (do_code->op == EXEC_DO);
if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
gfc_error ("!$OMP DO iteration variable must be of type integer at %L",
@@ -1359,6 +1446,53 @@ resolve_omp_do (gfc_code *code)
&do_code->loc);
break;
}
+ if (i > 1)
+ {
+ gfc_code *do_code2 = code->block->next;
+ int j;
+
+ for (j = 1; j < i; j++)
+ {
+ gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
+ if (dovar == ivar
+ || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
+ || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
+ || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
+ {
+ gfc_error ("!$OMP DO collapsed loops don't form rectangular iteration space at %L",
+ &do_code->loc);
+ break;
+ }
+ if (j < i)
+ break;
+ do_code2 = do_code2->block->next;
+ }
+ }
+ if (i == collapse)
+ break;
+ for (c = do_code->next; c; c = c->next)
+ if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
+ {
+ gfc_error ("collapsed !$OMP DO loops not perfectly nested at %L",
+ &c->loc);
+ break;
+ }
+ if (c)
+ break;
+ do_code = do_code->block;
+ if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE)
+ {
+ gfc_error ("not enough DO loops for collapsed !$OMP DO at %L",
+ &code->loc);
+ break;
+ }
+ do_code = do_code->next;
+ if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE)
+ {
+ gfc_error ("not enough DO loops for collapsed !$OMP DO at %L",
+ &code->loc);
+ break;
+ }
}
}
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 33f13c92200..c35db2d9cf6 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -515,6 +515,7 @@ decode_omp_directive (void)
match ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL);
match ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS);
match ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE);
+ match ("end task", gfc_match_omp_eos, ST_OMP_END_TASK);
match ("end workshare", gfc_match_omp_end_nowait,
ST_OMP_END_WORKSHARE);
break;
@@ -541,6 +542,8 @@ decode_omp_directive (void)
match ("single", gfc_match_omp_single, ST_OMP_SINGLE);
break;
case 't':
+ match ("task", gfc_match_omp_task, ST_OMP_TASK);
+ match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
match ("threadprivate", gfc_match_omp_threadprivate,
ST_OMP_THREADPRIVATE);
case 'w':
@@ -641,7 +644,7 @@ next_free (void)
for (i = 0; i < 5; i++, c = gfc_next_ascii_char ())
gcc_assert (c == "!$omp"[i]);
- gcc_assert (c == ' ');
+ gcc_assert (c == ' ' || c == '\t');
gfc_gobble_whitespace ();
return decode_omp_directive ();
}
@@ -870,7 +873,7 @@ next_statement (void)
case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
- case ST_OMP_BARRIER
+ case ST_OMP_BARRIER: case ST_OMP_TASKWAIT
/* Statements that mark other executable statements. */
@@ -879,7 +882,8 @@ next_statement (void)
case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \
case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
- case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE
+ case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: \
+ case ST_OMP_TASK
/* Declaration statements */
@@ -1351,6 +1355,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_END_SINGLE:
p = "!$OMP END SINGLE";
break;
+ case ST_OMP_END_TASK:
+ p = "!$OMP END TASK";
+ break;
case ST_OMP_END_WORKSHARE:
p = "!$OMP END WORKSHARE";
break;
@@ -1384,6 +1391,12 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_SINGLE:
p = "!$OMP SINGLE";
break;
+ case ST_OMP_TASK:
+ p = "!$OMP TASK";
+ break;
+ case ST_OMP_TASKWAIT:
+ p = "!$OMP TASKWAIT";
+ break;
case ST_OMP_THREADPRIVATE:
p = "!$OMP THREADPRIVATE";
break;
@@ -2857,6 +2870,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
case ST_OMP_SINGLE:
omp_end_st = ST_OMP_END_SINGLE;
break;
+ case ST_OMP_TASK:
+ omp_end_st = ST_OMP_END_TASK;
+ break;
case ST_OMP_WORKSHARE:
omp_end_st = ST_OMP_END_WORKSHARE;
break;
@@ -3067,6 +3083,7 @@ parse_executable (gfc_statement st)
case ST_OMP_CRITICAL:
case ST_OMP_MASTER:
case ST_OMP_SINGLE:
+ case ST_OMP_TASK:
parse_omp_structured_block (st, false);
break;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index b5b76b6f7a0..2787e293021 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -4670,8 +4670,8 @@ sym_in_expr (gfc_expr *e, gfc_symbol *sym, int *f ATTRIBUTE_UNUSED)
return false;
}
-static bool
-find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
+bool
+gfc_find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
{
return gfc_traverse_expr (e, sym, sym_in_expr, 0);
}
@@ -4868,8 +4868,10 @@ check_symbols:
if (sym->ts.type == BT_DERIVED)
continue;
- if ((ar->start[i] != NULL && find_sym_in_expr (sym, ar->start[i]))
- || (ar->end[i] != NULL && find_sym_in_expr (sym, ar->end[i])))
+ if ((ar->start[i] != NULL
+ && gfc_find_sym_in_expr (sym, ar->start[i]))
+ || (ar->end[i] != NULL
+ && gfc_find_sym_in_expr (sym, ar->end[i])))
{
gfc_error ("'%s' must not appear an the array specification at "
"%L in the same ALLOCATE statement where it is "
@@ -5982,6 +5984,8 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKWAIT:
case EXEC_OMP_WORKSHARE:
break;
@@ -6100,8 +6104,8 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
{
for (n = 0; n < ref->u.ar.dimen; n++)
if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR
- && find_sym_in_expr (lhs->symtree->n.sym,
- ref->u.ar.start[n]))
+ && gfc_find_sym_in_expr (lhs->symtree->n.sym,
+ ref->u.ar.start[n]))
ref->u.ar.start[n]
= gfc_get_parentheses (ref->u.ar.start[n]);
}
@@ -6176,6 +6180,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_SECTIONS:
+ case EXEC_OMP_TASK:
omp_workshare_save = omp_workshare_flag;
omp_workshare_flag = 0;
gfc_resolve_omp_parallel_blocks (code, ns);
@@ -6418,6 +6423,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_ORDERED:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASKWAIT:
case EXEC_OMP_WORKSHARE:
gfc_resolve_omp_directive (code, ns);
break;
@@ -6426,6 +6432,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_TASK:
omp_workshare_save = omp_workshare_flag;
omp_workshare_flag = 0;
gfc_resolve_omp_directive (code, ns);
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 02d87b4f4ce..1b0eeca1e65 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -702,7 +702,8 @@ skip_free_comments (void)
if (((c = next_char ()) == 'm' || c == 'M')
&& ((c = next_char ()) == 'p' || c == 'P'))
{
- if ((c = next_char ()) == ' ' || continue_flag)
+ if ((c = next_char ()) == ' ' || c == '\t'
+ || continue_flag)
{
while (gfc_is_whitespace (c))
c = next_char ();
@@ -724,7 +725,7 @@ skip_free_comments (void)
next_char ();
c = next_char ();
}
- if (continue_flag || c == ' ')
+ if (continue_flag || c == ' ' || c == '\t')
{
gfc_current_locus = old_loc;
next_char ();
@@ -820,11 +821,11 @@ skip_fixed_comments (void)
c = next_char ();
if (c != '\n'
&& ((openmp_flag && continue_flag)
- || c == ' ' || c == '0'))
+ || c == ' ' || c == '\t' || c == '0'))
{
- c = next_char ();
- while (gfc_is_whitespace (c))
+ do
c = next_char ();
+ while (gfc_is_whitespace (c));
if (c != '\n' && c != '!')
{
/* Canonicalize to *$omp. */
@@ -843,6 +844,11 @@ skip_fixed_comments (void)
for (col = 3; col < 6; col++, c = next_char ())
if (c == ' ')
continue;
+ else if (c == '\t')
+ {
+ col = 6;
+ break;
+ }
else if (c < '0' || c > '9')
break;
else
@@ -850,7 +856,7 @@ skip_fixed_comments (void)
if (col == 6 && c != '\n'
&& ((continue_flag && !digit_seen)
- || c == ' ' || c == '0'))
+ || c == ' ' || c == '\t' || c == '0'))
{
gfc_current_locus = start;
start.nextc[0] = ' ';
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index 0f0e4813d28..abe7b94865c 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -171,6 +171,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASK:
case EXEC_OMP_WORKSHARE:
case EXEC_OMP_PARALLEL_WORKSHARE:
gfc_free_omp_clauses (p->ext.omp_clauses);
@@ -189,6 +190,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_END_NOWAIT:
+ case EXEC_OMP_TASKWAIT:
break;
default:
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index c6c4baeca63..6f99800a014 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -84,6 +84,17 @@ gfc_omp_predetermined_sharing (tree decl)
if (GFC_DECL_CRAY_POINTEE (decl))
return OMP_CLAUSE_DEFAULT_PRIVATE;
+ /* Assumed-size arrays are predetermined to inherit sharing
+ attributes of the associated actual argument, which is shared
+ for all we care. */
+ if (TREE_CODE (decl) == PARM_DECL
+ && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
+ && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
+ && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
+ GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
+ == NULL)
+ return OMP_CLAUSE_DEFAULT_SHARED;
+
/* COMMON and EQUIVALENCE decls are shared. They
are only referenced through DECL_VALUE_EXPR of the variables
contained in them. If those are privatized, they will not be
@@ -98,27 +109,179 @@ gfc_omp_predetermined_sharing (tree decl)
}
+/* Return true if DECL in private clause needs
+ OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
+bool
+gfc_omp_private_outer_ref (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+
+ if (GFC_DESCRIPTOR_TYPE_P (type)
+ && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
+ return true;
+
+ return false;
+}
+
/* 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)
+gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
{
- tree type = TREE_TYPE (decl);
- stmtblock_t block;
+ tree type = TREE_TYPE (decl), rank, size, esize, ptr, cond, then_b, else_b;
+ stmtblock_t block, cond_block;
- if (! GFC_DESCRIPTOR_TYPE_P (type))
+ if (! GFC_DESCRIPTOR_TYPE_P (type)
+ || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
return NULL;
+ gcc_assert (outer != NULL);
+ gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
+ || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE);
+
/* Allocatable arrays in PRIVATE clauses need to be set to
- "not currently allocated" allocation status. */
- gfc_init_block (&block);
+ "not currently allocated" allocation status if outer
+ array is "not currently allocated", otherwise should be allocated. */
+ gfc_start_block (&block);
+
+ gfc_init_block (&cond_block);
+
+ gfc_add_modify_expr (&cond_block, decl, outer);
+ rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
+ size = gfc_conv_descriptor_ubound (decl, rank);
+ size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_lbound (decl, rank));
+ size = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
+ gfc_index_one_node);
+ if (GFC_TYPE_ARRAY_RANK (type) > 1)
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_stride (decl, rank));
+ esize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, esize);
+ size = gfc_evaluate_now (fold_convert (size_type_node, size), &cond_block);
+ ptr = gfc_allocate_array_with_status (&cond_block,
+ build_int_cst (pvoid_type_node, 0),
+ size, NULL);
+ gfc_conv_descriptor_data_set_tuples (&cond_block, decl, ptr);
+ then_b = gfc_finish_block (&cond_block);
+
+ gfc_init_block (&cond_block);
+ gfc_conv_descriptor_data_set_tuples (&cond_block, decl, null_pointer_node);
+ else_b = gfc_finish_block (&cond_block);
+
+ cond = fold_build2 (NE_EXPR, boolean_type_node,
+ fold_convert (pvoid_type_node,
+ gfc_conv_descriptor_data_get (outer)),
+ null_pointer_node);
+ gfc_add_expr_to_block (&block, build3 (COND_EXPR, void_type_node,
+ cond, then_b, else_b));
- gfc_conv_descriptor_data_set_tuples (&block, decl, null_pointer_node);
+ return gfc_finish_block (&block);
+}
+
+/* Build and return code for a copy constructor from SRC to DEST. */
+
+tree
+gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
+{
+ tree type = TREE_TYPE (dest), ptr, size, esize, rank, call;
+ stmtblock_t block;
+
+ if (! GFC_DESCRIPTOR_TYPE_P (type)
+ || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
+ return build_gimple_modify_stmt (dest, src);
+
+ gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE);
+
+ /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
+ and copied from SRC. */
+ gfc_start_block (&block);
+
+ gfc_add_modify_expr (&block, dest, src);
+ rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
+ size = gfc_conv_descriptor_ubound (dest, rank);
+ size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_lbound (dest, rank));
+ size = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
+ gfc_index_one_node);
+ if (GFC_TYPE_ARRAY_RANK (type) > 1)
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_stride (dest, rank));
+ esize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, esize);
+ size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
+ ptr = gfc_allocate_array_with_status (&block,
+ build_int_cst (pvoid_type_node, 0),
+ size, NULL);
+ gfc_conv_descriptor_data_set_tuples (&block, dest, ptr);
+ call = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
+ fold_convert (pvoid_type_node,
+ gfc_conv_descriptor_data_get (src)),
+ size);
+ gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
return gfc_finish_block (&block);
}
+/* Similarly, except use an assignment operator instead. */
+
+tree
+gfc_omp_clause_assign_op (tree clause ATTRIBUTE_UNUSED, tree dest, tree src)
+{
+ tree type = TREE_TYPE (dest), rank, size, esize, call;
+ stmtblock_t block;
+
+ if (! GFC_DESCRIPTOR_TYPE_P (type)
+ || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
+ return build_gimple_modify_stmt (dest, src);
+
+ /* Handle copying allocatable arrays. */
+ gfc_start_block (&block);
+
+ rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
+ size = gfc_conv_descriptor_ubound (dest, rank);
+ size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_lbound (dest, rank));
+ size = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
+ gfc_index_one_node);
+ if (GFC_TYPE_ARRAY_RANK (type) > 1)
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_stride (dest, rank));
+ esize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, esize);
+ size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
+ call = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
+ fold_convert (pvoid_type_node,
+ gfc_conv_descriptor_data_get (dest)),
+ fold_convert (pvoid_type_node,
+ gfc_conv_descriptor_data_get (src)),
+ size);
+ gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
+
+ return gfc_finish_block (&block);
+}
+
+/* Build and return code destructing DECL. Return NULL if nothing
+ to be done. */
+
+tree
+gfc_omp_clause_dtor (tree clause ATTRIBUTE_UNUSED, tree decl)
+{
+ tree type = TREE_TYPE (decl);
+
+ if (! GFC_DESCRIPTOR_TYPE_P (type)
+ || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
+ return NULL;
+
+ /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
+ to be deallocated if they were allocated. */
+ return gfc_trans_dealloc_allocated (decl);
+}
+
/* Return true if DECL's DECL_VALUE_EXPR (if any) should be
disregarded in OpenMP construct, because it is going to be
@@ -429,7 +592,39 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
/* Create the init statement list. */
pushlevel (0);
- stmt = gfc_trans_assignment (e1, e2, false);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
+ && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+ {
+ /* If decl is an allocatable array, it needs to be allocated
+ with the same bounds as the outer var. */
+ tree type = TREE_TYPE (decl), rank, size, esize, ptr;
+ stmtblock_t block;
+
+ gfc_start_block (&block);
+
+ gfc_add_modify_expr (&block, decl, outer_sym.backend_decl);
+ rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
+ size = gfc_conv_descriptor_ubound (decl, rank);
+ size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_lbound (decl, rank));
+ size = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
+ gfc_index_one_node);
+ if (GFC_TYPE_ARRAY_RANK (type) > 1)
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
+ gfc_conv_descriptor_stride (decl, rank));
+ esize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, esize);
+ size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
+ ptr = gfc_allocate_array_with_status (&block,
+ build_int_cst (pvoid_type_node, 0),
+ size, NULL);
+ gfc_conv_descriptor_data_set_tuples (&block, decl, ptr);
+ gfc_add_expr_to_block (&block, gfc_trans_assignment (e1, e2, false));
+ stmt = gfc_finish_block (&block);
+ }
+ else
+ 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
@@ -438,7 +633,20 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
/* Create the merge statement list. */
pushlevel (0);
- stmt = gfc_trans_assignment (e3, e4, false);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
+ && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+ {
+ /* If decl is an allocatable array, it needs to be deallocated
+ afterwards. */
+ stmtblock_t block;
+
+ gfc_start_block (&block);
+ gfc_add_expr_to_block (&block, gfc_trans_assignment (e3, e4, false));
+ gfc_add_expr_to_block (&block, gfc_trans_dealloc_allocated (decl));
+ stmt = gfc_finish_block (&block);
+ }
+ else
+ 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
@@ -639,6 +847,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_SCHED_RUNTIME:
OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
break;
+ case OMP_SCHED_AUTO:
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
+ break;
default:
gcc_unreachable ();
}
@@ -659,6 +870,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_DEFAULT_PRIVATE:
OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
break;
+ case OMP_DEFAULT_FIRSTPRIVATE:
+ OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
+ break;
default:
gcc_unreachable ();
}
@@ -677,6 +891,19 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->untied)
+ {
+ c = build_omp_clause (OMP_CLAUSE_UNTIED);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->collapse)
+ {
+ c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c) = build_int_cst (NULL, clauses->collapse);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
return omp_clauses;
}
@@ -893,20 +1120,28 @@ gfc_trans_omp_critical (gfc_code *code)
static tree
gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
- gfc_omp_clauses *do_clauses)
+ gfc_omp_clauses *do_clauses, tree par_clauses)
{
gfc_se se;
tree dovar, stmt, from, to, step, type, init, cond, incr;
tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
stmtblock_t block;
stmtblock_t body;
- int simple = 0;
- bool dovar_found = false;
gfc_omp_clauses *clauses = code->ext.omp_clauses;
+ gfc_code *outermost;
+ int i, collapse = clauses->collapse;
+ tree dovar_init = NULL_TREE;
- code = code->block->next;
+ if (collapse <= 0)
+ collapse = 1;
+
+ outermost = code = code->block->next;
gcc_assert (code->op == EXEC_DO);
+ init = make_tree_vec (collapse);
+ cond = make_tree_vec (collapse);
+ incr = make_tree_vec (collapse);
+
if (pblock == NULL)
{
gfc_start_block (&block);
@@ -914,107 +1149,168 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
}
omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
- if (clauses)
- {
- gfc_namelist *n;
- for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL; n = n->next)
- if (code->ext.iterator->var->symtree->n.sym == n->sym)
- break;
- if (n == NULL)
- for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
- if (code->ext.iterator->var->symtree->n.sym == n->sym)
- break;
- if (n != NULL)
- dovar_found = true;
- }
- /* Evaluate all the expressions in the iterator. */
- gfc_init_se (&se, NULL);
- gfc_conv_expr_lhs (&se, code->ext.iterator->var);
- gfc_add_block_to_block (pblock, &se.pre);
- dovar = se.expr;
- type = TREE_TYPE (dovar);
- gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
-
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->start);
- gfc_add_block_to_block (pblock, &se.pre);
- from = gfc_evaluate_now (se.expr, pblock);
-
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->end);
- gfc_add_block_to_block (pblock, &se.pre);
- to = gfc_evaluate_now (se.expr, pblock);
-
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->step);
- gfc_add_block_to_block (pblock, &se.pre);
- step = gfc_evaluate_now (se.expr, pblock);
-
- /* Special case simple loops. */
- if (integer_onep (step))
- simple = 1;
- else if (tree_int_cst_equal (step, integer_minus_one_node))
- simple = -1;
-
- /* Loop body. */
- if (simple)
+ for (i = 0; i < collapse; i++)
{
- init = build2_v (GIMPLE_MODIFY_STMT, dovar, from);
- cond = fold_build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node,
- dovar, to);
- incr = fold_build2 (PLUS_EXPR, type, dovar, step);
- incr = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar, incr);
- if (pblock != &block)
+ int simple = 0;
+ int dovar_found = 0;
+
+ if (clauses)
{
- pushlevel (0);
- gfc_start_block (&block);
+ gfc_namelist *n;
+ for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL;
+ n = n->next)
+ if (code->ext.iterator->var->symtree->n.sym == n->sym)
+ break;
+ if (n != NULL)
+ dovar_found = 1;
+ else if (n == NULL)
+ for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
+ if (code->ext.iterator->var->symtree->n.sym == n->sym)
+ break;
+ if (n != NULL)
+ dovar_found++;
}
- gfc_start_block (&body);
- }
- else
- {
- /* STEP is not 1 or -1. Use:
- for (count = 0; count < (to + step - from) / step; count++)
- {
- dovar = from + count * step;
- body;
- cycle_label:;
- } */
- tmp = fold_build2 (MINUS_EXPR, type, step, from);
- tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
- tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
- tmp = gfc_evaluate_now (tmp, pblock);
- count = gfc_create_var (type, "count");
- init = build2_v (GIMPLE_MODIFY_STMT, count, build_int_cst (type, 0));
- cond = fold_build2 (LT_EXPR, boolean_type_node, count, tmp);
- incr = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1));
- incr = fold_build2 (GIMPLE_MODIFY_STMT, type, count, incr);
-
- if (pblock != &block)
+
+ /* Evaluate all the expressions in the iterator. */
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr_lhs (&se, code->ext.iterator->var);
+ gfc_add_block_to_block (pblock, &se.pre);
+ dovar = se.expr;
+ type = TREE_TYPE (dovar);
+ gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr_val (&se, code->ext.iterator->start);
+ gfc_add_block_to_block (pblock, &se.pre);
+ from = gfc_evaluate_now (se.expr, pblock);
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr_val (&se, code->ext.iterator->end);
+ gfc_add_block_to_block (pblock, &se.pre);
+ to = gfc_evaluate_now (se.expr, pblock);
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr_val (&se, code->ext.iterator->step);
+ gfc_add_block_to_block (pblock, &se.pre);
+ step = gfc_evaluate_now (se.expr, pblock);
+
+ /* Special case simple loops. */
+ if (integer_onep (step))
+ simple = 1;
+ else if (tree_int_cst_equal (step, integer_minus_one_node))
+ simple = -1;
+
+ /* Loop body. */
+ if (simple)
{
- pushlevel (0);
- gfc_start_block (&block);
+ TREE_VEC_ELT (init, i) = build2_v (GIMPLE_MODIFY_STMT, dovar, from);
+ TREE_VEC_ELT (cond, i) = fold_build2 (simple > 0 ? LE_EXPR : GE_EXPR,
+ boolean_type_node, dovar, to);
+ TREE_VEC_ELT (incr, i) = fold_build2 (PLUS_EXPR, type, dovar, step);
+ TREE_VEC_ELT (incr, i) = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar,
+ TREE_VEC_ELT (incr, i));
+ }
+ else
+ {
+ /* STEP is not 1 or -1. Use:
+ for (count = 0; count < (to + step - from) / step; count++)
+ {
+ dovar = from + count * step;
+ body;
+ cycle_label:;
+ } */
+ tmp = fold_build2 (MINUS_EXPR, type, step, from);
+ tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
+ tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
+ tmp = gfc_evaluate_now (tmp, pblock);
+ count = gfc_create_var (type, "count");
+ TREE_VEC_ELT (init, i) = build2_v (GIMPLE_MODIFY_STMT, count,
+ build_int_cst (type, 0));
+ TREE_VEC_ELT (cond, i) = fold_build2 (LT_EXPR, boolean_type_node,
+ count, tmp);
+ TREE_VEC_ELT (incr, i) = fold_build2 (PLUS_EXPR, type, count,
+ build_int_cst (type, 1));
+ TREE_VEC_ELT (incr, i) = fold_build2 (GIMPLE_MODIFY_STMT, type,
+ count, TREE_VEC_ELT (incr, i));
+
+ /* Initialize DOVAR. */
+ tmp = fold_build2 (MULT_EXPR, type, count, step);
+ tmp = fold_build2 (PLUS_EXPR, type, from, tmp);
+ dovar_init = tree_cons (dovar, tmp, dovar_init);
}
- gfc_start_block (&body);
- /* Initialize DOVAR. */
- tmp = fold_build2 (MULT_EXPR, type, count, step);
- tmp = fold_build2 (PLUS_EXPR, type, from, tmp);
- gfc_add_modify_stmt (&body, dovar, tmp);
+ if (!dovar_found)
+ {
+ tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (tmp) = dovar;
+ omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
+ }
+ else if (dovar_found == 2)
+ {
+ tree c = NULL;
+
+ tmp = NULL;
+ if (!simple)
+ {
+ /* If dovar is lastprivate, but different counter is used,
+ dovar += step needs to be added to
+ OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
+ will have the value on entry of the last loop, rather
+ than value after iterator increment. */
+ tmp = gfc_evaluate_now (step, pblock);
+ tmp = fold_build2 (PLUS_EXPR, type, dovar, tmp);
+ tmp = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar, tmp);
+ for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_DECL (c) == dovar)
+ {
+ OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
+ break;
+ }
+ }
+ if (c == NULL && par_clauses != NULL)
+ {
+ for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_DECL (c) == dovar)
+ {
+ tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+ OMP_CLAUSE_DECL (l) = dovar;
+ OMP_CLAUSE_CHAIN (l) = omp_clauses;
+ OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
+ omp_clauses = l;
+ OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
+ break;
+ }
+ }
+ gcc_assert (simple || c != NULL);
+ }
+ if (!simple)
+ {
+ tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (tmp) = count;
+ omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
+ }
+
+ if (i + 1 < collapse)
+ code = code->block->next;
}
- if (!dovar_found)
+ if (pblock != &block)
{
- tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
- OMP_CLAUSE_DECL (tmp) = dovar;
- omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
+ pushlevel (0);
+ gfc_start_block (&block);
}
- if (!simple)
+
+ gfc_start_block (&body);
+
+ dovar_init = nreverse (dovar_init);
+ while (dovar_init)
{
- tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
- OMP_CLAUSE_DECL (tmp) = count;
- omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
+ gfc_add_modify_stmt (&body, TREE_PURPOSE (dovar_init),
+ TREE_VALUE (dovar_init));
+ dovar_init = TREE_CHAIN (dovar_init);
}
/* Cycle statement is implemented with a goto. Exit statement must not be
@@ -1107,9 +1403,11 @@ gfc_trans_omp_parallel_do (gfc_code *code)
do_clauses.sched_kind = parallel_clauses.sched_kind;
do_clauses.chunk_size = parallel_clauses.chunk_size;
do_clauses.ordered = parallel_clauses.ordered;
+ do_clauses.collapse = parallel_clauses.collapse;
parallel_clauses.sched_kind = OMP_SCHED_NONE;
parallel_clauses.chunk_size = NULL;
parallel_clauses.ordered = false;
+ parallel_clauses.collapse = 0;
omp_clauses = gfc_trans_omp_clauses (&block, &parallel_clauses,
code->loc);
}
@@ -1118,7 +1416,7 @@ gfc_trans_omp_parallel_do (gfc_code *code)
pblock = &block;
else
pushlevel (0);
- stmt = gfc_trans_omp_do (code, pblock, &do_clauses);
+ stmt = gfc_trans_omp_do (code, pblock, &do_clauses, omp_clauses);
if (TREE_CODE (stmt) != BIND_EXPR)
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
else
@@ -1221,6 +1519,31 @@ gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
}
static tree
+gfc_trans_omp_task (gfc_code *code)
+{
+ stmtblock_t block;
+ tree stmt, body_stmt, omp_clauses;
+
+ gfc_start_block (&block);
+ omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
+ code->loc);
+ body_stmt = gfc_trans_omp_code (code->block->next, true);
+ stmt = make_node (OMP_TASK);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TASK_CLAUSES (stmt) = omp_clauses;
+ OMP_TASK_BODY (stmt) = body_stmt;
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_taskwait (void)
+{
+ tree decl = built_in_decls [BUILT_IN_GOMP_TASKWAIT];
+ return build_call_expr (decl, 0);
+}
+
+static tree
gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
{
/* XXX */
@@ -1239,7 +1562,7 @@ gfc_trans_omp_directive (gfc_code *code)
case EXEC_OMP_CRITICAL:
return gfc_trans_omp_critical (code);
case EXEC_OMP_DO:
- return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses);
+ return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses, NULL);
case EXEC_OMP_FLUSH:
return gfc_trans_omp_flush ();
case EXEC_OMP_MASTER:
@@ -1258,6 +1581,10 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_sections (code, code->ext.omp_clauses);
case EXEC_OMP_SINGLE:
return gfc_trans_omp_single (code, code->ext.omp_clauses);
+ case EXEC_OMP_TASK:
+ return gfc_trans_omp_task (code);
+ case EXEC_OMP_TASKWAIT:
+ return gfc_trans_omp_taskwait ();
case EXEC_OMP_WORKSHARE:
return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
default:
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index f303128a28d..51e0cdd6aad 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -1135,6 +1135,8 @@ gfc_trans_code (gfc_code * code)
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKWAIT:
case EXEC_OMP_WORKSHARE:
res = gfc_trans_omp_directive (code);
break;
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index d0ce2354120..3a07d712791 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -493,9 +493,13 @@ bool gfc_get_array_descr_info (const_tree, struct array_descr_info *);
/* In trans-openmp.c */
bool gfc_omp_privatize_by_reference (const_tree);
enum omp_clause_default_kind gfc_omp_predetermined_sharing (tree);
-tree gfc_omp_clause_default_ctor (tree, tree);
+tree gfc_omp_clause_default_ctor (tree, tree, tree);
+tree gfc_omp_clause_copy_ctor (tree, tree, tree);
+tree gfc_omp_clause_assign_op (tree, tree, tree);
+tree gfc_omp_clause_dtor (tree, tree);
bool gfc_omp_disregard_value_expr (tree, bool);
bool gfc_omp_private_debug_clause (tree, bool);
+bool gfc_omp_private_outer_ref (tree);
struct gimplify_omp_ctx;
void gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, tree);
diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def
index 22dcafd2397..5bcdb5261d9 100644
--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def
@@ -50,10 +50,12 @@ along with GCC; see the file COPYING3. If not see
the type pointed to. */
DEF_PRIMITIVE_TYPE (BT_VOID, void_type_node)
-DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_type_node)
+DEF_PRIMITIVE_TYPE (BT_BOOL,
+ (*lang_hooks.types.type_for_size) (BOOL_TYPE_SIZE, 1))
DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
DEF_PRIMITIVE_TYPE (BT_I1, builtin_type_for_size (BITS_PER_UNIT*1, 1))
@@ -70,6 +72,7 @@ DEF_PRIMITIVE_TYPE (BT_VOLATILE_PTR,
TYPE_QUAL_VOLATILE)))
DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
+DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
DEF_FUNCTION_TYPE_0 (BT_FN_BOOL, BT_BOOL)
DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR)
@@ -87,11 +90,16 @@ DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_LONGPTR,
BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
+ BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_I1, BT_I1, BT_VOLATILE_PTR, BT_I1)
DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_I2, BT_I2, BT_VOLATILE_PTR, BT_I2)
DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, BT_I4, BT_VOLATILE_PTR, BT_I4)
DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_I16, BT_I16, BT_VOLATILE_PTR, BT_I16)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR)
+
+DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I1_I1, BT_BOOL, BT_VOLATILE_PTR,
BT_I1, BT_I1)
@@ -127,9 +135,20 @@ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
BT_LONG, BT_LONG, BT_LONG)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
+ BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
BT_LONG, BT_LONG, BT_LONG, BT_LONG)
+DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
+ BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
+ BT_BOOL, BT_UINT)
+DEF_FUNCTION_TYPE_7 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
+ BT_ULONGLONG, BT_ULONGLONG,
+ BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)