diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2017-12-22 10:22:15 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2017-12-22 10:22:15 +0000 |
commit | 170a8bd604a4c960b8a378d50f7cc6c66cbdaf5c (patch) | |
tree | 51107593d97f5e01e7b9dfa212cf1ab21d1998f4 /gcc/fortran | |
parent | fa546f0f16fd6678616eaea1c620b1abe5b6f8b5 (diff) | |
download | gcc-170a8bd604a4c960b8a378d50f7cc6c66cbdaf5c.zip gcc-170a8bd604a4c960b8a378d50f7cc6c66cbdaf5c.tar.gz gcc-170a8bd604a4c960b8a378d50f7cc6c66cbdaf5c.tar.bz2 |
extend.texi (Loop-Specific Pragmas): Document pragma GCC unroll.
* doc/extend.texi (Loop-Specific Pragmas): Document pragma GCC unroll.
c-family/
* c-pragma.c (init_pragma): Register pragma GCC unroll.
* c-pragma.h (enum pragma_kind): Add PRAGMA_UNROLL.
c/
* c-parser.c (c_parser_while_statement): Add unroll parameter and
build ANNOTATE_EXPR if present. Add 3rd operand to ANNOTATE_EXPR.
(c_parser_do_statement): Likewise.
(c_parser_for_statement): Likewise.
(c_parser_statement_after_labels): Adjust calls to above.
(c_parse_pragma_ivdep): New static function.
(c_parser_pragma_unroll): Likewise.
(c_parser_pragma) <PRAGMA_IVDEP>: Add support for pragma Unroll.
<PRAGMA_UNROLL>: New case.
cp/
* constexpr.c (cxx_eval_constant_expression) <ANNOTATE_EXPR>: Remove
assertion on 2nd operand.
(potential_constant_expression_1): Likewise.
* cp-tree.def (RANGE_FOR_STMT): Take a 5th operand.
* cp-tree.h (RANGE_FOR_UNROLL): New macro.
(cp_convert_range_for): Adjust prototype.
(finish_while_stmt_cond): Likewise.
(finish_do_stmt): Likewise.
(finish_for_cond): Likewise.
* init.c (build_vec_init): Adjut call to finish_for_cond.
* parser.c (cp_parser_statement): Adjust call to
cp_parser_iteration_statement.
(cp_parser_for): Add unroll parameter and pass it in calls to
cp_parser_range_for and cp_parser_c_for.
(cp_parser_c_for): Add unroll parameter and pass it in call to
finish_for_cond.
(cp_parser_range_for): Add unroll parameter, set in on RANGE_FOR_STMT
and pass it in call to cp_convert_range_for.
(cp_convert_range_for): Add unroll parameter and pass it in call to
finish_for_cond.
(cp_parser_iteration_statement): Add unroll parameter and pass it in
calls to finish_while_stmt_cond, finish_do_stmt and cp_parser_for.
(cp_parser_pragma_ivdep): New static function.
(cp_parser_pragma_unroll): Likewise.
(cp_parser_pragma) <PRAGMA_IVDEP>: Add support for pragma Unroll.
<PRAGMA_UNROLL>: New case.
* pt.c (tsubst_expr) <FOR_STMT>: Adjust call to finish_for_cond.
<RANGE_FOR_STMT>: Pass unrolling factor to cp_convert_range_for.
<WHILE_STMT>: Adjust call to finish_while_stmt_cond.
<DO_STMT>: Adjust call to finish_do_stmt.
* semantics.c (finish_while_stmt_cond): Add unroll parameter and
build ANNOTATE_EXPR if present.
(finish_do_stmt): Likewise.
(finish_for_cond): Likewise.
(begin_range_for_stmt): Build RANGE_FOR_STMT with 5th operand.
fortran/
* array.c (gfc_copy_iterator): Copy unroll field.
* decl.c (directive_unroll): New global variable.
(gfc_match_gcc_unroll): New function.
* gfortran.h (gfc_iterator]): Add unroll field.
(directive_unroll): Declare:
* match.c (gfc_match_do): Use memset to initialize the iterator.
* match.h (gfc_match_gcc_unroll): New prototype.
* parse.c (decode_gcc_attribute): Match "unroll".
(parse_do_block): Set iterator's unroll.
(parse_executable): Diagnose misplaced unroll directive.
* trans-stmt.c (gfc_trans_simple_do) Annotate loop condition with
annot_expr_unroll_kind.
(gfc_trans_do): Likewise.
* gfortran.texi (GNU Fortran Compiler Directives): Split section into
subections 'ATTRIBUTES directive' and 'UNROLL directive'.
From-SVN: r255973
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/fortran/array.c | 1 | ||||
-rw-r--r-- | gcc/fortran/decl.c | 38 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/gfortran.texi | 21 | ||||
-rw-r--r-- | gcc/fortran/match.c | 2 | ||||
-rw-r--r-- | gcc/fortran/match.h | 1 | ||||
-rw-r--r-- | gcc/fortran/parse.c | 13 | ||||
-rw-r--r-- | gcc/fortran/trans-stmt.c | 10 |
9 files changed, 104 insertions, 3 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a601cfa..d0cbc37 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,22 @@ +2017-12-22 Bernhard Reutner-Fischer <aldot@gcc.gnu.org> + Eric Botcazou <ebotcazou@adacore.com> + + * array.c (gfc_copy_iterator): Copy unroll field. + * decl.c (directive_unroll): New global variable. + (gfc_match_gcc_unroll): New function. + * gfortran.h (gfc_iterator]): Add unroll field. + (directive_unroll): Declare: + * match.c (gfc_match_do): Use memset to initialize the iterator. + * match.h (gfc_match_gcc_unroll): New prototype. + * parse.c (decode_gcc_attribute): Match "unroll". + (parse_do_block): Set iterator's unroll. + (parse_executable): Diagnose misplaced unroll directive. + * trans-stmt.c (gfc_trans_simple_do) Annotate loop condition with + annot_expr_unroll_kind. + (gfc_trans_do): Likewise. + * gfortran.texi (GNU Fortran Compiler Directives): Split section into + subections 'ATTRIBUTES directive' and 'UNROLL directive'. + 2017-12-19 Jakub Jelinek <jakub@redhat.com> * scanner.c (preprocessor_line): Replace Yoda conditions with typical diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 46642bb..81476b2 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -2123,6 +2123,7 @@ gfc_copy_iterator (gfc_iterator *src) dest->start = gfc_copy_expr (src->start); dest->end = gfc_copy_expr (src->end); dest->step = gfc_copy_expr (src->step); + dest->unroll = src->unroll; return dest; } diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 53a87b6..d2c794fc 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -95,6 +95,9 @@ gfc_symbol *gfc_new_block; bool gfc_matching_function; +/* Set upon parsing a !GCC$ unroll n directive for use in the next loop. */ +int directive_unroll = -1; + /* If a kind expression of a component of a parameterized derived type is parameterized, temporarily store the expression here. */ static gfc_expr *saved_kind_expr = NULL; @@ -104,7 +107,6 @@ static gfc_expr *saved_kind_expr = NULL; static gfc_actual_arglist *decl_type_param_list; static gfc_actual_arglist *type_param_spec_list; - /********************* DATA statement subroutines *********************/ static bool in_match_data = false; @@ -10958,3 +10960,37 @@ syntax: gfc_error ("Syntax error in !GCC$ ATTRIBUTES statement at %C"); return MATCH_ERROR; } + + +/* Match a !GCC$ UNROLL statement of the form: + !GCC$ UNROLL n + + The parameter n is the number of times we are supposed to unroll. + + When we come here, we have already matched the !GCC$ UNROLL string. */ +match +gfc_match_gcc_unroll (void) +{ + int value; + + if (gfc_match_small_int (&value) == MATCH_YES) + { + if (value < 0 || value > USHRT_MAX) + { + gfc_error ("%<GCC unroll%> directive requires a" + " non-negative integral constant" + " less than or equal to %u at %C", + USHRT_MAX + ); + return MATCH_ERROR; + } + if (gfc_match_eos () == MATCH_YES) + { + directive_unroll = value == 0 ? 1 : value; + return MATCH_YES; + } + } + + gfc_error ("Syntax error in !GCC$ UNROLL directive at %C"); + return MATCH_ERROR; +} diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c5e62d7..7b837c9 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2350,6 +2350,7 @@ gfc_case; typedef struct { gfc_expr *var, *start, *end, *step; + unsigned short unroll; } gfc_iterator; @@ -2724,6 +2725,7 @@ gfc_finalizer; /* decl.c */ bool gfc_in_match_data (void); match gfc_match_char_spec (gfc_typespec *); +extern int directive_unroll; /* Handling Parameterized Derived Types */ bool gfc_insert_kind_parameter_exprs (gfc_expr *); diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index aabf268..fc95ec0 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3447,6 +3447,14 @@ as this requires the new array descriptor. @node GNU Fortran Compiler Directives @section GNU Fortran Compiler Directives +@menu +* ATTRIBUTES directive:: +* UNROLL directive:: +@end menu + +@node ATTRIBUTES directive +@subsection ATTRIBUTES directive + The Fortran standard describes how a conforming program shall behave; however, the exact implementation is not standardized. In order to allow the user to choose specific implementation details, compiler @@ -3520,6 +3528,19 @@ of the procedure; for variables and procedure pointers, they shall be in the same declaration part as the variable or procedure pointer. +@node UNROLL directive +@subsection UNROLL directive + +The syntax of the directive is + +@code{!GCC$ unroll N} + +You can use this directive to control how many times a loop should be unrolled. +It must be placed immediately before a @code{DO} loop and applies only to the +loop that follows. N is an integer constant specifying the unrolling factor. +The values of 0 and 1 block any unrolling of the loop. + + @node Non-Fortran Main Program @section Non-Fortran Main Program diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index d63b11c..f7de5d5 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -2540,8 +2540,8 @@ gfc_match_do (void) old_loc = gfc_current_locus; + memset (&iter, '\0', sizeof (gfc_iterator)); label = NULL; - iter.var = iter.start = iter.end = iter.step = NULL; m = gfc_match_label (); if (m == MATCH_ERROR) diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index d6df349..a5f6291 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -241,6 +241,7 @@ match gfc_match_contiguous (void); match gfc_match_dimension (void); match gfc_match_external (void); match gfc_match_gcc_attributes (void); +match gfc_match_gcc_unroll (void); match gfc_match_import (void); match gfc_match_intent (void); match gfc_match_intrinsic (void); diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 08bff3f..91be6da 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -1063,6 +1063,7 @@ decode_gcc_attribute (void) old_locus = gfc_current_locus; match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL); + match ("unroll", gfc_match_gcc_unroll, ST_NONE); /* All else has failed, so give up. See if any of the matchers has stored an error message of some sort. */ @@ -4635,7 +4636,14 @@ parse_do_block (void) s.ext.end_do_label = new_st.label1; if (new_st.ext.iterator != NULL) - stree = new_st.ext.iterator->var->symtree; + { + stree = new_st.ext.iterator->var->symtree; + if (directive_unroll != -1) + { + new_st.ext.iterator->unroll = directive_unroll; + directive_unroll = -1; + } + } else stree = NULL; @@ -5393,6 +5401,9 @@ parse_executable (gfc_statement st) return st; } + if (directive_unroll != -1) + gfc_error ("%<GCC unroll%> directive does not commence a loop at %C"); + st = next_statement (); } } diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index df29b78..e6569e0 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1979,6 +1979,11 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar, fold_convert (type, to)); cond = gfc_evaluate_now_loc (loc, cond, &body); + if (code->ext.iterator->unroll && cond != error_mark_node) + cond + = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_unroll_kind), + build_int_cst (integer_type_node, code->ext.iterator->unroll)); /* The loop exit. */ tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); @@ -2305,6 +2310,11 @@ gfc_trans_do (gfc_code * code, tree exit_cond) /* End with the loop condition. Loop until countm1t == 0. */ cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t, build_int_cst (utype, 0)); + if (code->ext.iterator->unroll && cond != error_mark_node) + cond + = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_unroll_kind), + build_int_cst (integer_type_node, code->ext.iterator->unroll)); tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp, build_empty_stmt (loc)); |