aboutsummaryrefslogtreecommitdiff
path: root/gcc
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
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')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c/ChangeLog5
-rw-r--r--gcc/c/c-typeck.c3
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/semantics.c2
-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
-rw-r--r--gcc/gimplify.c19
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h4
-rw-r--r--gcc/omp-low.c33
-rw-r--r--gcc/tree.h5
14 files changed, 221 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7651e6e..dcbb23b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2014-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2014-06-24 Cong Hou <congh@google.com>
* tree-vect-patterns.c (vect_recog_sad_pattern): New function for SAD
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 4ab7160..955828c 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Make sure
+ OMP_CLAUSE_LINEAR_STEP has correct type.
+
2014-06-24 Trevor Saunders <tsaunders@mozilla.com>
* c-decl.c: Adjust.
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 0764630..4deeae7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -12005,6 +12005,9 @@ c_finish_omp_clauses (tree clauses)
s = size_one_node;
OMP_CLAUSE_LINEAR_STEP (c) = s;
}
+ else
+ OMP_CLAUSE_LINEAR_STEP (c)
+ = fold_convert (TREE_TYPE (t), OMP_CLAUSE_LINEAR_STEP (c));
goto check_dup_generic;
check_dup_generic:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d3d2835..99bca49 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses): Make sure
+ OMP_CLAUSE_LINEAR_STEP has correct type.
+
2014-06-24 Jan Hubicka <hubicka@ucw.cz>
* class.c (check_methods, create_vtable_ptr, determine_key_method,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index aad6e2f..241884c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5287,6 +5287,8 @@ finish_omp_clauses (tree clauses)
break;
}
}
+ else
+ t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)), t);
}
OMP_CLAUSE_LINEAR_STEP (c) = t;
}
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);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 6bea3c6..f3c7d61 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6913,8 +6913,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
case POSTINCREMENT_EXPR:
{
tree decl = TREE_OPERAND (t, 0);
- // c_omp_for_incr_canonicalize_ptr() should have been
- // called to massage things appropriately.
+ /* c_omp_for_incr_canonicalize_ptr() should have been
+ called to massage things appropriately. */
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
if (orig_for_stmt != for_stmt)
@@ -6930,6 +6930,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ /* c_omp_for_incr_canonicalize_ptr() should have been
+ called to massage things appropriately. */
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
if (orig_for_stmt != for_stmt)
break;
t = build_int_cst (TREE_TYPE (decl), -1);
@@ -6970,12 +6973,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
ret = MIN (ret, tret);
if (c)
{
- OMP_CLAUSE_LINEAR_STEP (c) = TREE_OPERAND (t, 1);
+ tree step = TREE_OPERAND (t, 1);
+ tree stept = TREE_TYPE (decl);
+ if (POINTER_TYPE_P (stept))
+ stept = sizetype;
+ step = fold_convert (stept, step);
if (TREE_CODE (t) == MINUS_EXPR)
+ step = fold_build1 (NEGATE_EXPR, stept, step);
+ OMP_CLAUSE_LINEAR_STEP (c) = step;
+ if (step != TREE_OPERAND (t, 1))
{
- t = TREE_OPERAND (t, 1);
- OMP_CLAUSE_LINEAR_STEP (c)
- = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
&for_pre_body, NULL,
is_gimple_val, fb_rvalue);
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 76bb907..e77d2d9 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -215,6 +215,7 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR hook_tree_tree_tree_tree_null
#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR lhd_omp_assignment
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP lhd_omp_assignment
+#define LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR NULL
#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
#define LANG_HOOKS_OMP_FINISH_CLAUSE lhd_omp_finish_clause
@@ -238,6 +239,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR, \
LANG_HOOKS_OMP_CLAUSE_COPY_CTOR, \
LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP, \
+ LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
LANG_HOOKS_OMP_CLAUSE_DTOR, \
LANG_HOOKS_OMP_FINISH_CLAUSE \
}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 33aa558..72fa85e 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -225,6 +225,10 @@ struct lang_hooks_for_decls
/* Similarly, except use an assignment operator instead. */
tree (*omp_clause_assign_op) (tree clause, tree dst, tree src);
+ /* Build and return code for a constructor of DST that sets it to
+ SRC + ADD. */
+ tree (*omp_clause_linear_ctor) (tree clause, tree dst, tree src, tree add);
+
/* Build and return code destructing DECL. Return NULL if nothing
to be done. */
tree (*omp_clause_dtor) (tree clause, tree decl);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index e70970e..e1bf34d 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3083,11 +3083,14 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
switch (OMP_CLAUSE_CODE (c))
{
+ case OMP_CLAUSE_LINEAR:
+ if (OMP_CLAUSE_LINEAR_ARRAY (c))
+ max_vf = 1;
+ /* FALLTHRU */
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
- case OMP_CLAUSE_LINEAR:
if (is_variable_sized (OMP_CLAUSE_DECL (c)))
max_vf = 1;
break;
@@ -3413,14 +3416,12 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
&& gimple_omp_for_combined_into_p (ctx->stmt))
{
- tree stept = POINTER_TYPE_P (TREE_TYPE (x))
- ? sizetype : TREE_TYPE (x);
- tree t = fold_convert (stept,
- OMP_CLAUSE_LINEAR_STEP (c));
- tree c = find_omp_clause (clauses,
- OMP_CLAUSE__LOOPTEMP_);
- gcc_assert (c);
- tree l = OMP_CLAUSE_DECL (c);
+ tree t = OMP_CLAUSE_LINEAR_STEP (c);
+ tree stept = TREE_TYPE (t);
+ tree ct = find_omp_clause (clauses,
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (ct);
+ tree l = OMP_CLAUSE_DECL (ct);
tree n1 = fd->loop.n1;
tree step = fd->loop.step;
tree itype = TREE_TYPE (l);
@@ -3437,6 +3438,15 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
t = fold_build2 (MULT_EXPR, stept,
fold_convert (stept, l), t);
+
+ if (OMP_CLAUSE_LINEAR_ARRAY (c))
+ {
+ x = lang_hooks.decls.omp_clause_linear_ctor
+ (c, new_var, x, t);
+ gimplify_and_add (x, ilist);
+ goto do_dtor;
+ }
+
if (POINTER_TYPE_P (TREE_TYPE (x)))
x = fold_build2 (POINTER_PLUS_EXPR,
TREE_TYPE (x), x, t);
@@ -3460,10 +3470,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
= gimple_build_assign (unshare_expr (lvar), iv);
gsi_insert_before_without_update (&gsi, g,
GSI_SAME_STMT);
- tree stept = POINTER_TYPE_P (TREE_TYPE (iv))
- ? sizetype : TREE_TYPE (iv);
- tree t = fold_convert (stept,
- OMP_CLAUSE_LINEAR_STEP (c));
+ tree t = OMP_CLAUSE_LINEAR_STEP (c);
enum tree_code code = PLUS_EXPR;
if (POINTER_TYPE_P (TREE_TYPE (new_var)))
code = POINTER_PLUS_EXPR;
diff --git a/gcc/tree.h b/gcc/tree.h
index a435c3a..a80fa38 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1330,6 +1330,11 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_LINEAR_VARIABLE_STRIDE(NODE) \
TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR))
+/* True if a LINEAR clause is for an array or allocatable variable that
+ needs special handling by the frontend. */
+#define OMP_CLAUSE_LINEAR_ARRAY(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)->base.deprecated_flag)
+
#define OMP_CLAUSE_LINEAR_STEP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)