case OMP_CLAUSE_LASTPRIVATE:
if (is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
+ else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
+ sctx.max_vf = 1;
+ }
break;
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
|| is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
+ else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
+ sctx.max_vf = 1;
+ }
break;
case OMP_CLAUSE_IF:
if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
/* For reduction in SIMD loop, defer adding the
initialization of the reference, because if we decide
to use SIMD array for it, the initilization could cause
- expansion ICE. */
- if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
+ expansion ICE. Ditto for other privatization clauses. */
+ if (is_simd)
x = NULL_TREE;
else
{
tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
if ((TREE_ADDRESSABLE (new_var) || nx || y
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
+ || omp_is_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
+
if (nx)
x = lang_hooks.decls.omp_clause_default_ctor
(c, unshare_expr (ivar), x);
}
break;
}
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ x = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (x))
+ {
+ x = create_tmp_var_raw (type, get_name (var));
+ gimple_add_tmp_var (x);
+ TREE_ADDRESSABLE (x) = 1;
+ x = build_fold_addr_expr_loc (clause_loc, x);
+ x = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard), x);
+ gimplify_assign (new_vard, x, ilist);
+ }
+ }
}
if (nx)
gimplify_and_add (nx, ilist);
if (OMP_CLAUSE_LINEAR_ARRAY (c))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ nx = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (nx))
+ {
+ nx = create_tmp_var_raw (type,
+ get_name (var));
+ gimple_add_tmp_var (nx);
+ TREE_ADDRESSABLE (nx) = 1;
+ nx = build_fold_addr_expr_loc (clause_loc,
+ nx);
+ nx = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard),
+ nx);
+ gimplify_assign (new_vard, nx, ilist);
+ }
+ }
+
x = lang_hooks.decls.omp_clause_linear_ctor
(c, new_var, x, t);
gimplify_and_add (x, ilist);
}
if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
- || TREE_ADDRESSABLE (new_var))
+ || TREE_ADDRESSABLE (new_var)
+ || omp_is_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
{
tree iv = create_tmp_var (TREE_TYPE (new_var));
}
break;
}
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ nx = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (nx))
+ {
+ nx = create_tmp_var_raw (type, get_name (var));
+ gimple_add_tmp_var (nx);
+ TREE_ADDRESSABLE (nx) = 1;
+ nx = build_fold_addr_expr_loc (clause_loc, nx);
+ nx = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard), nx);
+ gimplify_assign (new_vard, nx, ilist);
+ }
+ }
}
x = lang_hooks.decls.omp_clause_copy_ctor
(c, unshare_expr (new_var), x);
--- /dev/null
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int w;
+struct S {
+ int s, &t;
+ int *p;
+ S (int *x) : s (0), t (w), p (x) {};
+ void foo (short &, int &);
+ void bar (short &, int &);
+ void baz (short &, int &);
+ void qux (short &, int &);
+};
+
+__attribute__((noipa)) void
+S::foo (short &x, int &y)
+{
+ int *q = this->p;
+ #pragma omp simd lastprivate (x, s, t) private (y)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = q[i];
+ x = y;
+ q[i] = y * 2;
+ s = q[i] + 3;
+ t = q[i] + 6;
+ }
+}
+
+__attribute__((noipa)) void
+S::bar (short &x, int &y)
+{
+ #pragma omp simd linear (x) linear (s, t: 2) private (y)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = p[i];
+ x += y - 2 * i + 1;
+ p[i] = y * 2;
+ s += 2 * y - 4 * i + 2;
+ t += 2 * y - 4 * i + 2;
+ }
+}
+
+__attribute__((noipa)) void
+S::baz (short &x, int &y)
+{
+ int *q = this->p;
+ #pragma omp simd lastprivate (x, s, t) private (y) if (simd: 0)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = q[i];
+ x = y;
+ q[i] = y * 2;
+ s = q[i] + 3;
+ t = q[i] + 6;
+ }
+}
+
+__attribute__((noipa)) void
+S::qux (short &x, int &y)
+{
+ #pragma omp simd linear (x) linear (s, t: 2) private (y) simdlen (1)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = p[i];
+ x += y - 2 * i + 1;
+ p[i] = y * 2;
+ s += 2 * y - 4 * i + 2;
+ t += 2 * y - 4 * i + 2;
+ }
+}
+
+int
+main ()
+{
+ short x;
+ int a[1025], y;
+ check_vect ();
+ S s = a;
+ for (int i = 0; i < 1025; ++i)
+ {
+ a[i] = i;
+ asm volatile ("" : "+g" (i));
+ }
+ s.foo (x, y);
+ if (x != 1024 || s.s != 2051 || s.t != 2054)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 2 * i)
+ abort ();
+ s.bar (x, y);
+ if (x != 2049 || s.s != 4101 || s.t != 4104)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 4 * i)
+ abort ();
+ else
+ a[i] = i;
+ s.baz (x, y);
+ if (x != 1024 || s.s != 2051 || s.t != 2054)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 2 * i)
+ abort ();
+ s.qux (x, y);
+ if (x != 2049 || s.s != 4101 || s.t != 4104)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 4 * i)
+ abort ();
+}