Hi! Here is the first part of LTO fixes for #pragma omp declare simd, in partuclar support for streaming OMP_CLAUSEs.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-11-28 Jakub Jelinek <ja...@redhat.com> PR lto/59326 * tree-core.h (enum omp_clause_schedule_kind): Add OMP_CLAUSE_SCHEDULE_LAST. (enum omp_clause_default_kind): Add OMP_CLAUSE_DEFAULT_LAST. (enum omp_clause_depend_kind): Add OMP_CLAUSE_DEPEND_LAST. (enum omp_clause_map_kind): Add OMP_CLAUSE_MAP_LAST. (enum omp_clause_proc_bind_kind): Add OMP_CLAUSE_PROC_BIND_LAST. * lto-streamer-out.c (lto_is_streamable): Allow streaming OMP_CLAUSE. (DFS_write_tree_body): Handle OMP_CLAUSE. * tree-streamer-out.c (pack_ts_omp_clause_value_fields): New function. (streamer_pack_tree_bitfields): Call it for OMP_CLAUSE. (write_ts_omp_clause_tree_pointers): New function. (streamer_write_tree_body): Call it for OMP_CLAUSE. (streamer_write_tree_header): For OMP_CLAUSE stream OMP_CLAUSE_CODE. * tree-streamer-in.c (unpack_ts_omp_clause_value_fields): New function. (unpack_value_fields): Call it for OMP_CLAUSE. (streamer_alloc_tree): Handle OMP_CLAUSE. (lto_input_ts_omp_clause_tree_pointers): New function. (streamer_read_tree_body): Call it for OMP_CLAUSE. lto/ * lto.c (mentions_vars_p_omp_clause): New function. (mentions_vars_p): Call it for OMP_CLAUSE. Remove break; after return stmts. --- gcc/tree-core.h.jj 2013-11-27 12:15:14.000000000 +0100 +++ gcc/tree-core.h 2013-11-28 10:55:46.691490627 +0100 @@ -350,7 +350,8 @@ enum omp_clause_schedule_kind { OMP_CLAUSE_SCHEDULE_DYNAMIC, OMP_CLAUSE_SCHEDULE_GUIDED, OMP_CLAUSE_SCHEDULE_AUTO, - OMP_CLAUSE_SCHEDULE_RUNTIME + OMP_CLAUSE_SCHEDULE_RUNTIME, + OMP_CLAUSE_SCHEDULE_LAST }; enum omp_clause_default_kind { @@ -358,7 +359,8 @@ enum omp_clause_default_kind { OMP_CLAUSE_DEFAULT_SHARED, OMP_CLAUSE_DEFAULT_NONE, OMP_CLAUSE_DEFAULT_PRIVATE, - OMP_CLAUSE_DEFAULT_FIRSTPRIVATE + OMP_CLAUSE_DEFAULT_FIRSTPRIVATE, + OMP_CLAUSE_DEFAULT_LAST }; /* There is a TYPE_QUAL value for each type qualifier. They can be @@ -1107,7 +1109,8 @@ enum omp_clause_depend_kind { OMP_CLAUSE_DEPEND_IN, OMP_CLAUSE_DEPEND_OUT, - OMP_CLAUSE_DEPEND_INOUT + OMP_CLAUSE_DEPEND_INOUT, + OMP_CLAUSE_DEPEND_LAST }; enum omp_clause_map_kind @@ -1119,7 +1122,8 @@ enum omp_clause_map_kind /* The following kind is an internal only map kind, used for pointer based array sections. OMP_CLAUSE_SIZE for these is not the pointer size, which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias. */ - OMP_CLAUSE_MAP_POINTER + OMP_CLAUSE_MAP_POINTER, + OMP_CLAUSE_MAP_LAST }; enum omp_clause_proc_bind_kind @@ -1129,7 +1133,8 @@ enum omp_clause_proc_bind_kind OMP_CLAUSE_PROC_BIND_TRUE = 1, OMP_CLAUSE_PROC_BIND_MASTER = 2, OMP_CLAUSE_PROC_BIND_CLOSE = 3, - OMP_CLAUSE_PROC_BIND_SPREAD = 4 + OMP_CLAUSE_PROC_BIND_SPREAD = 4, + OMP_CLAUSE_PROC_BIND_LAST }; struct GTY(()) tree_exp { --- gcc/lto-streamer-out.c.jj 2013-11-27 18:02:46.000000000 +0100 +++ gcc/lto-streamer-out.c 2013-11-28 11:51:03.085288356 +0100 @@ -297,7 +297,6 @@ lto_is_streamable (tree expr) && code != BIND_EXPR && code != WITH_CLEANUP_EXPR && code != STATEMENT_LIST - && code != OMP_CLAUSE && (code == CASE_LABEL_EXPR || code == DECL_EXPR || TREE_CODE_CLASS (code) != tcc_statement); @@ -667,6 +666,14 @@ DFS_write_tree_body (struct output_block } } + if (code == OMP_CLAUSE) + { + int i; + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + DFS_follow_tree_edge (OMP_CLAUSE_OPERAND (expr, i)); + DFS_follow_tree_edge (OMP_CLAUSE_CHAIN (expr)); + } + #undef DFS_follow_tree_edge } --- gcc/tree-streamer-out.c.jj 2013-11-22 21:03:16.000000000 +0100 +++ gcc/tree-streamer-out.c 2013-11-28 11:49:49.327672855 +0100 @@ -390,6 +390,46 @@ pack_ts_optimization (struct bitpack_d * } +/* Pack all the non-pointer fields of the TS_OMP_CLAUSE structure + of expression EXPR into bitpack BP. */ + +static void +pack_ts_omp_clause_value_fields (struct output_block *ob, + struct bitpack_d *bp, tree expr) +{ + stream_output_location (ob, bp, OMP_CLAUSE_LOCATION (expr)); + switch (OMP_CLAUSE_CODE (expr)) + { + case OMP_CLAUSE_DEFAULT: + bp_pack_enum (bp, omp_clause_default_kind, OMP_CLAUSE_DEFAULT_LAST, + OMP_CLAUSE_DEFAULT_KIND (expr)); + break; + case OMP_CLAUSE_SCHEDULE: + bp_pack_enum (bp, omp_clause_schedule_kind, OMP_CLAUSE_SCHEDULE_LAST, + OMP_CLAUSE_SCHEDULE_KIND (expr)); + break; + case OMP_CLAUSE_DEPEND: + bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST, + OMP_CLAUSE_DEPEND_KIND (expr)); + break; + case OMP_CLAUSE_MAP: + bp_pack_enum (bp, omp_clause_map_kind, OMP_CLAUSE_MAP_LAST, + OMP_CLAUSE_MAP_KIND (expr)); + break; + case OMP_CLAUSE_PROC_BIND: + bp_pack_enum (bp, omp_clause_proc_bind_kind, OMP_CLAUSE_PROC_BIND_LAST, + OMP_CLAUSE_PROC_BIND_KIND (expr)); + break; + case OMP_CLAUSE_REDUCTION: + bp_pack_enum (bp, tree_code, MAX_TREE_CODES, + OMP_CLAUSE_REDUCTION_CODE (expr)); + break; + default: + break; + } +} + + /* Pack all the bitfields in EXPR into a bit pack. */ void @@ -451,6 +491,9 @@ streamer_pack_tree_bitfields (struct out if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) bp_pack_var_len_unsigned (bp, CONSTRUCTOR_NELTS (expr)); + + if (code == OMP_CLAUSE) + pack_ts_omp_clause_value_fields (ob, bp, expr); } @@ -853,6 +896,29 @@ write_ts_constructor_tree_pointers (stru } } + +/* Write all pointer fields in the TS_OMP_CLAUSE structure of EXPR + to output block OB. If REF_P is true, write a reference to EXPR's + pointer fields. */ + +static void +write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr, + bool ref_p) +{ + int i; + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p); + if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_REDUCTION) + { + /* We don't stream these right now, handle it if streaming + of them is needed. */ + gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr) == NULL); + gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr) == NULL); + } + stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p); +} + + /* Write all pointer fields in EXPR to output block OB. If REF_P is true, the leaves of EXPR are emitted as references. */ @@ -915,6 +981,9 @@ streamer_write_tree_body (struct output_ if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) write_ts_constructor_tree_pointers (ob, expr, ref_p); + + if (code == OMP_CLAUSE) + write_ts_omp_clause_tree_pointers (ob, expr, ref_p); } @@ -963,6 +1032,8 @@ streamer_write_tree_header (struct outpu streamer_write_uhwi (ob, BINFO_N_BASE_BINFOS (expr)); else if (TREE_CODE (expr) == CALL_EXPR) streamer_write_uhwi (ob, call_expr_nargs (expr)); + else if (TREE_CODE (expr) == OMP_CLAUSE) + streamer_write_uhwi (ob, OMP_CLAUSE_CODE (expr)); } --- gcc/tree-streamer-in.c.jj 2013-11-22 21:03:16.000000000 +0100 +++ gcc/tree-streamer-in.c 2013-11-28 11:49:42.437709308 +0100 @@ -425,6 +425,48 @@ unpack_ts_optimization (struct bitpack_d } +/* Unpack all the non-pointer fields of the TS_OMP_CLAUSE + structure of expression EXPR from bitpack BP. */ + +static void +unpack_ts_omp_clause_value_fields (struct data_in *data_in, + struct bitpack_d *bp, tree expr) +{ + OMP_CLAUSE_LOCATION (expr) = stream_input_location (bp, data_in); + switch (OMP_CLAUSE_CODE (expr)) + { + case OMP_CLAUSE_DEFAULT: + OMP_CLAUSE_DEFAULT_KIND (expr) + = bp_unpack_enum (bp, omp_clause_default_kind, + OMP_CLAUSE_DEFAULT_LAST); + break; + case OMP_CLAUSE_SCHEDULE: + OMP_CLAUSE_SCHEDULE_KIND (expr) + = bp_unpack_enum (bp, omp_clause_schedule_kind, + OMP_CLAUSE_SCHEDULE_LAST); + break; + case OMP_CLAUSE_DEPEND: + OMP_CLAUSE_DEPEND_KIND (expr) + = bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST); + break; + case OMP_CLAUSE_MAP: + OMP_CLAUSE_MAP_KIND (expr) + = bp_unpack_enum (bp, omp_clause_map_kind, OMP_CLAUSE_MAP_LAST); + break; + case OMP_CLAUSE_PROC_BIND: + OMP_CLAUSE_PROC_BIND_KIND (expr) + = bp_unpack_enum (bp, omp_clause_proc_bind_kind, + OMP_CLAUSE_PROC_BIND_LAST); + break; + case OMP_CLAUSE_REDUCTION: + OMP_CLAUSE_REDUCTION_CODE (expr) + = bp_unpack_enum (bp, tree_code, MAX_TREE_CODES); + break; + default: + break; + } +} + /* Unpack all the non-pointer fields in EXPR into a bit pack. */ static void @@ -493,6 +535,9 @@ unpack_value_fields (struct data_in *dat if (length > 0) vec_safe_grow (CONSTRUCTOR_ELTS (expr), length); } + + if (code == OMP_CLAUSE) + unpack_ts_omp_clause_value_fields (data_in, bp, expr); } @@ -578,6 +623,12 @@ streamer_alloc_tree (struct lto_input_bl unsigned HOST_WIDE_INT nargs = streamer_read_uhwi (ib); return build_vl_exp (CALL_EXPR, nargs + 3); } + else if (code == OMP_CLAUSE) + { + enum omp_clause_code subcode + = (enum omp_clause_code) streamer_read_uhwi (ib); + return build_omp_clause (UNKNOWN_LOCATION, subcode); + } else { /* For all other nodes, materialize the tree with a raw @@ -960,6 +1011,22 @@ lto_input_ts_constructor_tree_pointers ( } +/* Read all pointer fields in the TS_OMP_CLAUSE structure of EXPR from + input block IB. DATA_IN contains tables and descriptors for the + file being read. */ + +static void +lto_input_ts_omp_clause_tree_pointers (struct lto_input_block *ib, + struct data_in *data_in, tree expr) +{ + int i; + + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree (ib, data_in); + OMP_CLAUSE_CHAIN (expr) = stream_read_tree (ib, data_in); +} + + /* Read all pointer fields in EXPR from input block IB. DATA_IN contains tables and descriptors for the file being read. */ @@ -1021,6 +1088,9 @@ streamer_read_tree_body (struct lto_inpu if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) lto_input_ts_constructor_tree_pointers (ib, data_in, expr); + + if (code == OMP_CLAUSE) + lto_input_ts_omp_clause_tree_pointers (ib, data_in, expr); } --- gcc/lto/lto.c.jj 2013-11-22 21:03:14.000000000 +0100 +++ gcc/lto/lto.c 2013-11-28 11:58:15.597048439 +0100 @@ -904,6 +904,19 @@ mentions_vars_p_expr (tree t) return false; } +/* Check presence of pointers to decls in fields of an OMP_CLAUSE T. */ + +static bool +mentions_vars_p_omp_clause (tree t) +{ + int i; + if (mentions_vars_p_common (t)) + return true; + for (i = omp_clause_num_ops[OMP_CLAUSE_CODE (t)] - 1; i >= 0; --i) + CHECK_VAR (OMP_CLAUSE_OPERAND (t, i)); + return false; +} + /* Check presence of pointers to decls that needs later fixup in T. */ static bool @@ -922,7 +935,6 @@ mentions_vars_p (tree t) case FIELD_DECL: return mentions_vars_p_field_decl (t); - break; case LABEL_DECL: case CONST_DECL: @@ -931,27 +943,21 @@ mentions_vars_p (tree t) case IMPORTED_DECL: case NAMESPACE_DECL: return mentions_vars_p_decl_common (t); - break; case VAR_DECL: return mentions_vars_p_decl_with_vis (t); - break; case TYPE_DECL: return mentions_vars_p_decl_non_common (t); - break; case FUNCTION_DECL: return mentions_vars_p_function (t); - break; case TREE_BINFO: return mentions_vars_p_binfo (t); - break; case PLACEHOLDER_EXPR: return mentions_vars_p_common (t); - break; case BLOCK: case TRANSLATION_UNIT_DECL: @@ -961,7 +967,9 @@ mentions_vars_p (tree t) case CONSTRUCTOR: return mentions_vars_p_constructor (t); - break; + + case OMP_CLAUSE: + return mentions_vars_p_omp_clause (t); default: if (TYPE_P (t)) Jakub