aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2017-12-22 10:22:15 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2017-12-22 10:22:15 +0000
commit170a8bd604a4c960b8a378d50f7cc6c66cbdaf5c (patch)
tree51107593d97f5e01e7b9dfa212cf1ab21d1998f4 /gcc/fortran
parentfa546f0f16fd6678616eaea1c620b1abe5b6f8b5 (diff)
downloadgcc-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/ChangeLog19
-rw-r--r--gcc/fortran/array.c1
-rw-r--r--gcc/fortran/decl.c38
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/gfortran.texi21
-rw-r--r--gcc/fortran/match.c2
-rw-r--r--gcc/fortran/match.h1
-rw-r--r--gcc/fortran/parse.c13
-rw-r--r--gcc/fortran/trans-stmt.c10
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));