diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe3e7ec8feb..f167e76e140 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-05-21 Jakub Jelinek + + PR middle-end/61252 + * omp-low.c (handle_simd_reference): New function. + (lower_rec_input_clauses): Use it. Defer adding reference + initialization even for reduction without placeholder if in simd, + handle it properly later on. + 2014-05-20 Jan Hubicka PR tree-optimization/60899 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a2a64ad1dcd..95b0e5273d2 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -2998,6 +2998,27 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf, return true; } +/* Helper function of lower_rec_input_clauses. For a reference + in simd reduction, add an underlying variable it will reference. */ + +static void +handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist) +{ + tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard))); + if (TREE_CONSTANT (z)) + { + const char *name = NULL; + if (DECL_NAME (new_vard)) + name = IDENTIFIER_POINTER (DECL_NAME (new_vard)); + + z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name); + gimple_add_tmp_var (z); + TREE_ADDRESSABLE (z) = 1; + z = build_fold_addr_expr_loc (loc, z); + gimplify_assign (new_vard, z, ilist); + } +} + /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN, from the receiver (aka child) side and initializers for REFERENCE_TYPE private variables. Initialization statements go in ILIST, while calls @@ -3189,13 +3210,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, } else if (TREE_CONSTANT (x)) { - /* For reduction with placeholder 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 - && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) - && is_simd) + /* 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) x = NULL_TREE; else { @@ -3524,23 +3543,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, But if they aren't used, we need to emit the deferred initialization now. */ else if (is_reference (var) && is_simd) - { - tree z - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard))); - if (TREE_CONSTANT (z)) - { - const char *name = NULL; - if (DECL_NAME (var)) - name = IDENTIFIER_POINTER (DECL_NAME (new_vard)); - - z = create_tmp_var_raw - (TREE_TYPE (TREE_TYPE (new_vard)), name); - gimple_add_tmp_var (z); - TREE_ADDRESSABLE (z) = 1; - z = build_fold_addr_expr_loc (clause_loc, z); - gimplify_assign (new_vard, z, ilist); - } - } + handle_simd_reference (clause_loc, new_vard, ilist); x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, unshare_expr (x)); if (x) @@ -3573,6 +3576,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (code == MINUS_EXPR) code = PLUS_EXPR; + tree new_vard = new_var; + if (is_simd && is_reference (var)) + { + gcc_assert (TREE_CODE (new_var) == MEM_REF); + new_vard = TREE_OPERAND (new_var, 0); + gcc_assert (DECL_P (new_vard)); + } if (is_simd && lower_rec_simd_input_clauses (new_var, ctx, max_vf, idx, lane, ivar, lvar)) @@ -3584,9 +3594,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, x = build2 (code, TREE_TYPE (ref), ref, ivar); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, &llist[1]); + + if (new_vard != new_var) + { + SET_DECL_VALUE_EXPR (new_vard, + build_fold_addr_expr (lvar)); + DECL_HAS_VALUE_EXPR_P (new_vard) = 1; + } } else { + if (is_reference (var) && is_simd) + handle_simd_reference (clause_loc, new_vard, ilist); gimplify_assign (new_var, x, ilist); if (is_simd) { diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 9e02f5426e5..45daf0e6597 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2014-05-21 Jakub Jelinek + + PR middle-end/61252 + * testsuite/libgomp.c++/simd-9.C: New test. + 2014-05-18 Uros Bizjak * libgomp.texi (Runitme Library Routines): Remove multiple @menu. diff --git a/libgomp/testsuite/libgomp.c++/simd-9.C b/libgomp/testsuite/libgomp.c++/simd-9.C new file mode 100644 index 00000000000..3c567b31c3e --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/simd-9.C @@ -0,0 +1,52 @@ +// { dg-do run } +// { dg-options "-O2" } +// { dg-additional-options "-msse2" { target sse2_runtime } } +// { dg-additional-options "-mavx" { target avx_runtime } } + +extern "C" void abort (); +int a[1024] __attribute__((aligned (32))) = { 1 }; +#pragma omp declare reduction (foo:int:omp_out += omp_in) \ + initializer (omp_priv = 0) + +__attribute__((noinline, noclone)) void +foo (int &u, int &v) +{ + int i; + #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v) + for (i = 0; i < 1024; i++) + { + int x = a[i]; + u += x; + v += x; + } +} + +__attribute__((noinline, noclone)) void +bar (int &u, int &v) +{ + int i; + #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v) \ + safelen(1) + for (i = 0; i < 1024; i++) + { + int x = a[i]; + u += x; + v += x; + } +} + +int +main () +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (i & 31) + (i / 128); + int u = 0, v = 0; + foo (u, v); + if (u != 19456 || v != 19456) + abort (); + u = 0; v = 0; + bar (u, v); + if (u != 19456 || v != 19456) + abort (); +}