aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-06-25 11:16:12 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2014-06-25 11:16:12 +0200
commitda6f124d8a567e410a2926f1cb4416ca620d271d (patch)
tree553a56ba818b9c31b883fbfc783c1b85ead87337 /gcc/fortran
parentd49f446ecd2dbe68081d25da06a528c7f2198efe (diff)
downloadgcc-da6f124d8a567e410a2926f1cb4416ca620d271d.zip
gcc-da6f124d8a567e410a2926f1cb4416ca620d271d.tar.gz
gcc-da6f124d8a567e410a2926f1cb4416ca620d271d.tar.bz2
langhooks-def.h (LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR): Define.
* langhooks-def.h (LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR): Define. (LANG_HOOKS_DECLS): Add it. * gimplify.c (gimplify_omp_for): Make sure OMP_CLAUSE_LINEAR_STEP has correct type. * tree.h (OMP_CLAUSE_LINEAR_ARRAY): Define. * langhooks.h (struct lang_hooks_for_decls): Add omp_clause_linear_ctor hook. * omp-low.c (lower_rec_input_clauses): Set max_vf even if OMP_CLAUSE_LINEAR_ARRAY is set. Don't fold_convert OMP_CLAUSE_LINEAR_STEP. For OMP_CLAUSE_LINEAR_ARRAY in combined simd loop use omp_clause_linear_ctor hook. gcc/c/ * c-typeck.c (c_finish_omp_clauses): Make sure OMP_CLAUSE_LINEAR_STEP has correct type. gcc/cp/ * semantics.c (finish_omp_clauses): Make sure OMP_CLAUSE_LINEAR_STEP has correct type. gcc/fortran/ * trans.h (gfc_omp_clause_linear_ctor): New prototype. * trans-openmp.c (gfc_omp_linear_clause_add_loop, gfc_omp_clause_linear_ctor): New functions. (gfc_trans_omp_clauses): Make sure OMP_CLAUSE_LINEAR_STEP has correct type. Set OMP_CLAUSE_LINEAR_ARRAY flag if needed. * f95-lang.c (LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR): Redefine. libgomp/ * testsuite/libgomp.fortran/simd5.f90: New test. * testsuite/libgomp.fortran/simd6.f90: New test. * testsuite/libgomp.fortran/simd7.f90: New test. From-SVN: r211971
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog9
-rw-r--r--gcc/fortran/f95-lang.c2
-rw-r--r--gcc/fortran/trans-openmp.c137
-rw-r--r--gcc/fortran/trans.h1
4 files changed, 148 insertions, 1 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 57c5f8f..b4bbb0a8 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,12 @@
+2014-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ * trans.h (gfc_omp_clause_linear_ctor): New prototype.
+ * trans-openmp.c (gfc_omp_linear_clause_add_loop,
+ gfc_omp_clause_linear_ctor): New functions.
+ (gfc_trans_omp_clauses): Make sure OMP_CLAUSE_LINEAR_STEP has
+ correct type. Set OMP_CLAUSE_LINEAR_ARRAY flag if needed.
+ * f95-lang.c (LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR): Redefine.
+
2014-06-24 Jakub Jelinek <jakub@redhat.com>
* dump-parse-tree.c (show_omp_namelist): Use n->udr->udr instead
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 40f7f18..83f7eb2 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -126,6 +126,7 @@ static const struct attribute_spec gfc_attribute_table[] =
#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_LINEAR_CTOR
#undef LANG_HOOKS_OMP_CLAUSE_DTOR
#undef LANG_HOOKS_OMP_FINISH_CLAUSE
#undef LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR
@@ -158,6 +159,7 @@ static const struct attribute_spec gfc_attribute_table[] =
#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_LINEAR_CTOR gfc_omp_clause_linear_ctor
#define LANG_HOOKS_OMP_CLAUSE_DTOR gfc_omp_clause_dtor
#define LANG_HOOKS_OMP_FINISH_CLAUSE gfc_omp_finish_clause
#define LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR gfc_omp_disregard_value_expr
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 458cfff..da01a90 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -822,6 +822,137 @@ gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
return gfc_finish_block (&block);
}
+static void
+gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
+ tree add, tree nelems)
+{
+ stmtblock_t tmpblock;
+ tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
+ nelems = gfc_evaluate_now (nelems, block);
+
+ gfc_init_block (&tmpblock);
+ if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
+ {
+ desta = gfc_build_array_ref (dest, index, NULL);
+ srca = gfc_build_array_ref (src, index, NULL);
+ }
+ else
+ {
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
+ tree idx = fold_build2 (MULT_EXPR, sizetype,
+ fold_convert (sizetype, index),
+ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
+ desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (dest), dest,
+ idx));
+ srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (src), src,
+ idx));
+ }
+ gfc_add_modify (&tmpblock, desta,
+ fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
+ srca, add));
+
+ gfc_loopinfo loop;
+ gfc_init_loopinfo (&loop);
+ loop.dimen = 1;
+ loop.from[0] = gfc_index_zero_node;
+ loop.loopvar[0] = index;
+ loop.to[0] = nelems;
+ gfc_trans_scalarizing_loops (&loop, &tmpblock);
+ gfc_add_block_to_block (block, &loop.pre);
+}
+
+/* Build and return code for a constructor of DEST that initializes
+ it to SRC plus ADD (ADD is scalar integer). */
+
+tree
+gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
+{
+ tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
+ stmtblock_t block;
+
+ gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
+
+ gfc_start_block (&block);
+ add = gfc_evaluate_now (add, &block);
+
+ if ((! GFC_DESCRIPTOR_TYPE_P (type)
+ || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
+ && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
+ {
+ gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+ if (!TYPE_DOMAIN (type)
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
+ || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
+ {
+ nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
+ TYPE_SIZE_UNIT (type),
+ TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
+ }
+ else
+ nelems = array_type_nelts (type);
+ nelems = fold_convert (gfc_array_index_type, nelems);
+
+ gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
+ return gfc_finish_block (&block);
+ }
+
+ /* Allocatable arrays in LINEAR clauses need to be allocated
+ and copied from SRC. */
+ gfc_add_modify (&block, dest, src);
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ {
+ tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
+ size = gfc_conv_descriptor_ubound_get (dest, rank);
+ size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ size,
+ gfc_conv_descriptor_lbound_get (dest, rank));
+ size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ size, gfc_index_one_node);
+ if (GFC_TYPE_ARRAY_RANK (type) > 1)
+ size = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, size,
+ gfc_conv_descriptor_stride_get (dest, rank));
+ tree esize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ nelems = gfc_evaluate_now (unshare_expr (size), &block);
+ size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ nelems, unshare_expr (esize));
+ size = gfc_evaluate_now (fold_convert (size_type_node, size),
+ &block);
+ nelems = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, nelems,
+ gfc_index_one_node);
+ }
+ else
+ size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ ptr = gfc_create_var (pvoid_type_node, NULL);
+ gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ {
+ gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
+ tree etype = gfc_get_element_type (type);
+ ptr = fold_convert (build_pointer_type (etype), ptr);
+ tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
+ srcptr = fold_convert (build_pointer_type (etype), srcptr);
+ gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
+ }
+ else
+ {
+ gfc_add_modify (&block, unshare_expr (dest),
+ fold_convert (TREE_TYPE (dest), ptr));
+ ptr = fold_convert (TREE_TYPE (dest), ptr);
+ tree dstm = build_fold_indirect_ref (ptr);
+ tree srcm = build_fold_indirect_ref (unshare_expr (src));
+ gfc_add_modify (&block, dstm,
+ fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
+ }
+ return gfc_finish_block (&block);
+}
+
/* Build and return code destructing DECL. Return NULL if nothing
to be done. */
@@ -1667,7 +1798,11 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
gfc_add_block_to_block (block, &se.post);
}
}
- OMP_CLAUSE_LINEAR_STEP (node) = last_step;
+ OMP_CLAUSE_LINEAR_STEP (node)
+ = fold_convert (gfc_typenode_for_spec (&n->sym->ts),
+ last_step);
+ if (n->sym->attr.dimension || n->sym->attr.allocatable)
+ OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
omp_clauses = gfc_trans_add_clause (node, omp_clauses);
}
}
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index c272c0d..472b841 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -670,6 +670,7 @@ tree gfc_omp_report_decl (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_linear_ctor (tree, tree, tree, tree);
tree gfc_omp_clause_dtor (tree, tree);
void gfc_omp_finish_clause (tree, gimple_seq *);
bool gfc_omp_disregard_value_expr (tree, bool);