Hi! OpenMP 4.1 allows modifiers on the linear clause, like: #ifdef __cplusplus #pragma omp declare simd linear(ref(a):1) linear(val(b)) linear(uval(c)) int foo (int &a, int &b, int &c); #else #pragma omp declare simd linear(a:1) linear(val(b)) linear(uval(c)) int bar (int a, int b, int c); #endif
This patch parses them and checks requirements. Further changes (for elemental function handling and vectorization) will depend on the vector ABI details. 2015-06-11 Jakub Jelinek <ja...@redhat.com> * tree-core.h (enum omp_clause_linear_kind): New. (struct tree_omp_clause): Add subcode.linear_kind. * tree.h (OMP_CLAUSE_LINEAR_KIND): Define. * tree-pretty-print.h (dump_omp_clause): Dump linear clause modifiers. c/ * c-parser.c (c_parser_omp_clause_linear): Handle linear clause modifiers. cp/ * parser.c (cp_parser_omp_clause_linear): Handle linear clause modifiers. * semantics.c (finish_omp_clauses): Diagnose linear(ref(var)) where var isn't a reference. Don't use pointer_sum for ref(var), just multiply by size of pointer. --- gcc/tree-core.h.jj 2015-06-08 11:08:41.000000000 +0200 +++ gcc/tree-core.h 2015-06-11 14:34:43.926623065 +0200 @@ -1264,6 +1264,14 @@ enum omp_clause_proc_bind_kind OMP_CLAUSE_PROC_BIND_LAST }; +enum omp_clause_linear_kind +{ + OMP_CLAUSE_LINEAR_DEFAULT, + OMP_CLAUSE_LINEAR_REF, + OMP_CLAUSE_LINEAR_VAL, + OMP_CLAUSE_LINEAR_UVAL +}; + struct GTY(()) tree_exp { struct tree_typed typed; location_t locus; @@ -1328,6 +1336,7 @@ struct GTY(()) tree_omp_clause { unsigned char map_kind; enum omp_clause_proc_bind_kind proc_bind_kind; enum tree_code reduction_code; + enum omp_clause_linear_kind linear_kind; } GTY ((skip)) subcode; /* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's --- gcc/tree.h.jj 2015-06-08 10:48:20.000000000 +0200 +++ gcc/tree.h 2015-06-11 14:36:37.236879987 +0200 @@ -1494,6 +1494,9 @@ extern void protected_set_expr_location #define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init +#define OMP_CLAUSE_LINEAR_KIND(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)->omp_clause.subcode.linear_kind) + #define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1) --- gcc/tree-pretty-print.c.jj 2015-06-11 11:32:39.000000000 +0200 +++ gcc/tree-pretty-print.c 2015-06-11 14:43:37.367415531 +0200 @@ -495,8 +495,26 @@ dump_omp_clause (pretty_printer *pp, tre case OMP_CLAUSE_LINEAR: pp_string (pp, "linear("); + switch (OMP_CLAUSE_LINEAR_KIND (clause)) + { + case OMP_CLAUSE_LINEAR_DEFAULT: + break; + case OMP_CLAUSE_LINEAR_REF: + pp_string (pp, "ref("); + break; + case OMP_CLAUSE_LINEAR_VAL: + pp_string (pp, "val("); + break; + case OMP_CLAUSE_LINEAR_UVAL: + pp_string (pp, "uval("); + break; + default: + gcc_unreachable (); + } dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); + if (OMP_CLAUSE_LINEAR_KIND (clause) != OMP_CLAUSE_LINEAR_DEFAULT) + pp_right_paren (pp); pp_colon (pp); dump_generic_node (pp, OMP_CLAUSE_LINEAR_STEP (clause), spc, flags, false); --- gcc/c/c-parser.c.jj 2015-06-11 13:02:30.000000000 +0200 +++ gcc/c/c-parser.c 2015-06-11 17:00:21.046632435 +0200 @@ -11461,20 +11461,46 @@ c_parser_omp_clause_aligned (c_parser *p /* OpenMP 4.0: linear ( variable-list ) - linear ( variable-list : expression ) */ + linear ( variable-list : expression ) + + OpenMP 4.1: + linear ( modifier ( variable-list ) ) + linear ( modifier ( variable-list ) : expression ) */ static tree c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; + enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return list; + if (!is_cilk_simd_fn + && c_parser_next_token_is (parser, CPP_NAME)) + { + c_token *tok = c_parser_peek_token (parser); + const char *p = IDENTIFIER_POINTER (tok->value); + if (strcmp ("val", p) == 0) + kind = OMP_CLAUSE_LINEAR_VAL; + else if (strcmp ("uval", p) == 0) + kind = OMP_CLAUSE_LINEAR_UVAL; + if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN) + kind = OMP_CLAUSE_LINEAR_DEFAULT; + if (kind != OMP_CLAUSE_LINEAR_DEFAULT) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + } + } + nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_LINEAR, list); + if (kind != OMP_CLAUSE_LINEAR_DEFAULT) + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); @@ -11500,6 +11526,7 @@ c_parser_omp_clause_linear (c_parser *pa for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { OMP_CLAUSE_LINEAR_STEP (c) = step; + OMP_CLAUSE_LINEAR_KIND (c) = kind; } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); --- gcc/cp/parser.c.jj 2015-06-11 13:03:19.000000000 +0200 +++ gcc/cp/parser.c 2015-06-11 16:59:24.879484663 +0200 @@ -28965,7 +28965,11 @@ cp_parser_omp_clause_aligned (cp_parser /* OpenMP 4.0: linear ( variable-list ) - linear ( variable-list : expression ) */ + linear ( variable-list : expression ) + + OpenMP 4.1: + linear ( modifier ( variable-list ) ) + linear ( modifier ( variable-list ) : expression ) */ static tree cp_parser_omp_clause_linear (cp_parser *parser, tree list, @@ -28973,12 +28977,43 @@ cp_parser_omp_clause_linear (cp_parser * { tree nlist, c, step = integer_one_node; bool colon; + enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list, - &colon); + if (!is_cilk_simd_fn + && cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (strcmp ("ref", p) == 0) + kind = OMP_CLAUSE_LINEAR_REF; + else if (strcmp ("val", p) == 0) + kind = OMP_CLAUSE_LINEAR_VAL; + else if (strcmp ("uval", p) == 0) + kind = OMP_CLAUSE_LINEAR_UVAL; + if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)) + cp_lexer_consume_token (parser->lexer); + else + kind = OMP_CLAUSE_LINEAR_DEFAULT; + } + + if (kind == OMP_CLAUSE_LINEAR_DEFAULT) + nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list, + &colon); + else + { + nlist = cp_parser_omp_var_list (parser, OMP_CLAUSE_LINEAR, list); + colon = cp_lexer_next_token_is (parser->lexer, CPP_COLON); + if (colon) + cp_parser_require (parser, CPP_COLON, RT_COLON); + else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } if (colon) { @@ -28999,7 +29034,10 @@ cp_parser_omp_clause_linear (cp_parser * } for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) - OMP_CLAUSE_LINEAR_STEP (c) = step; + { + OMP_CLAUSE_LINEAR_STEP (c) = step; + OMP_CLAUSE_LINEAR_KIND (c) = kind; + } return nlist; } --- gcc/cp/semantics.c.jj 2015-06-10 16:09:56.000000000 +0200 +++ gcc/cp/semantics.c 2015-06-11 17:12:29.324582468 +0200 @@ -5579,6 +5579,15 @@ finish_omp_clauses (tree clauses, bool a if (!type_dependent_expression_p (t)) { tree type = TREE_TYPE (t); + if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF + && TREE_CODE (type) != REFERENCE_TYPE) + { + error ("linear clause with %<ref%> modifier applied to " + "non-reference variable with %qT type", + TREE_TYPE (t)); + remove = true; + break; + } if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (!INTEGRAL_TYPE_P (type) @@ -5616,7 +5625,16 @@ finish_omp_clauses (tree clauses, bool a tree type = TREE_TYPE (OMP_CLAUSE_DECL (c)); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == POINTER_TYPE) + if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF) + { + type = TREE_TYPE (OMP_CLAUSE_DECL (c)); + t = fold_convert_loc (OMP_CLAUSE_LOCATION (c), + sizetype, t); + t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), + MULT_EXPR, sizetype, t, + TYPE_SIZE_UNIT (type)); + } + else if (TREE_CODE (type) == POINTER_TYPE) { tree d = convert_from_reference (OMP_CLAUSE_DECL (c)); t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, Jakub