From: Jakub Jelinek Date: Sat, 6 Jul 2019 07:53:48 +0000 (+0200) Subject: omp-low.c (struct omp_context): Add for_simd_scan_phase member. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1f52d1a8b52ace2922eb9b97e2c49d2ee7d27410;p=gcc.git omp-low.c (struct omp_context): Add for_simd_scan_phase member. * omp-low.c (struct omp_context): Add for_simd_scan_phase member. (maybe_lookup_ctx): Add forward declaration. (omp_find_scan): Likewise. Walk into body of simd if composited with worksharing loop. (scan_omp_simd_scan): New function. (scan_omp_1_stmt): Call it. (lower_rec_simd_input_clauses): Don't create rvar nor rvar2 if ctx->for_simd_scan_phase. (lower_rec_input_clauses): Do much less work for inscan reductions in ctx->for_simd_scan_phase is_simd regions. (lower_omp_scan): Set is_simd also on simd constructs composited with worksharing loop, unless ctx->for_simd_scan_phase. Never emit a sorry message. Don't change GIMPLE_OMP_SCAN stmts into nops and emit their body after in simd constructs composited with worksharing loop. (lower_omp_for_scan): Handle worksharing loop composited with simd. * c-c++-common/gomp/scan-4.c: Don't expect sorry message. * testsuite/libgomp.c/scan-11.c: New test. * testsuite/libgomp.c/scan-12.c: New test. * testsuite/libgomp.c/scan-13.c: New test. * testsuite/libgomp.c/scan-14.c: New test. * testsuite/libgomp.c/scan-15.c: New test. * testsuite/libgomp.c/scan-16.c: New test. * testsuite/libgomp.c/scan-17.c: New test. * testsuite/libgomp.c/scan-18.c: New test. * testsuite/libgomp.c++/scan-9.C: New test. * testsuite/libgomp.c++/scan-10.C: New test. * testsuite/libgomp.c++/scan-11.C: New test. * testsuite/libgomp.c++/scan-12.C: New test. * testsuite/libgomp.c++/scan-13.C: New test. * testsuite/libgomp.c++/scan-14.C: New test. * testsuite/libgomp.c++/scan-15.C: New test. * testsuite/libgomp.c++/scan-16.C: New test. From-SVN: r273157 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc75cbbe7b1..3ce8b90a5d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2019-07-06 Jakub Jelinek + * omp-low.c (struct omp_context): Add for_simd_scan_phase member. + (maybe_lookup_ctx): Add forward declaration. + (omp_find_scan): Likewise. Walk into body of simd if composited + with worksharing loop. + (scan_omp_simd_scan): New function. + (scan_omp_1_stmt): Call it. + (lower_rec_simd_input_clauses): Don't create rvar nor rvar2 if + ctx->for_simd_scan_phase. + (lower_rec_input_clauses): Do much less work for inscan reductions + in ctx->for_simd_scan_phase is_simd regions. + (lower_omp_scan): Set is_simd also on simd constructs composited + with worksharing loop, unless ctx->for_simd_scan_phase. Never emit + a sorry message. Don't change GIMPLE_OMP_SCAN stmts into nops and + emit their body after in simd constructs composited with worksharing + loop. + (lower_omp_for_scan): Handle worksharing loop composited with simd. + * omp-low.c (omp_find_scan): Make static. (lower_omp_for_scan): Fix order of merge arguments in input phase of the second loop, var2 represents the first partial sum and so needs diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 52834c97f76..5d5fb6a8eb2 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -147,6 +147,9 @@ struct omp_context /* True if there is nested scan context with exclusive clause. */ bool scan_exclusive; + + /* True in the second simd loop of for simd with inscan reductions. */ + bool for_simd_scan_phase; }; static splay_tree all_contexts; @@ -2421,6 +2424,85 @@ scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt, scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt; } +static tree omp_find_scan (gimple_stmt_iterator *, bool *, + struct walk_stmt_info *); +static omp_context *maybe_lookup_ctx (gimple *); + +/* Duplicate #pragma omp simd, one for the scan input phase loop and one + for scan phase loop. */ + +static void +scan_omp_simd_scan (gimple_stmt_iterator *gsi, gomp_for *stmt, + omp_context *outer_ctx) +{ + /* The only change between inclusive and exclusive scan will be + within the first simd loop, so just use inclusive in the + worksharing loop. */ + outer_ctx->scan_inclusive = true; + tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_INCLUSIVE); + OMP_CLAUSE_DECL (c) = integer_zero_node; + + gomp_scan *input_stmt = gimple_build_omp_scan (NULL, NULL_TREE); + gomp_scan *scan_stmt = gimple_build_omp_scan (NULL, c); + gsi_replace (gsi, input_stmt, false); + gimple_seq input_body = NULL; + gimple_seq_add_stmt (&input_body, stmt); + gsi_insert_after (gsi, scan_stmt, GSI_NEW_STMT); + + gimple_stmt_iterator input1_gsi = gsi_none (); + struct walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input1_gsi; + walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input1_gsi)); + + gimple *input_stmt1 = gsi_stmt (input1_gsi); + gsi_next (&input1_gsi); + gimple *scan_stmt1 = gsi_stmt (input1_gsi); + gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN); + c = gimple_omp_scan_clauses (as_a (scan_stmt1)); + if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE) + std::swap (input_stmt1, scan_stmt1); + + gimple_seq input_body1 = gimple_omp_body (input_stmt1); + gimple_omp_set_body (input_stmt1, NULL); + + gimple_seq scan_body = copy_gimple_seq_and_replace_locals (stmt); + gomp_for *new_stmt = as_a (scan_body); + + gimple_omp_set_body (input_stmt1, input_body1); + gimple_omp_set_body (scan_stmt1, NULL); + + gimple_stmt_iterator input2_gsi = gsi_none (); + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input2_gsi; + walk_gimple_seq_mod (gimple_omp_body_ptr (new_stmt), omp_find_scan, + NULL, &wi); + gcc_assert (!gsi_end_p (input2_gsi)); + + gimple *input_stmt2 = gsi_stmt (input2_gsi); + gsi_next (&input2_gsi); + gimple *scan_stmt2 = gsi_stmt (input2_gsi); + gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN); + if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE) + std::swap (input_stmt2, scan_stmt2); + + gimple_omp_set_body (input_stmt2, NULL); + + gimple_omp_set_body (input_stmt, input_body); + gimple_omp_set_body (scan_stmt, scan_body); + + omp_context *ctx = new_omp_context (input_stmt, outer_ctx); + scan_omp (gimple_omp_body_ptr (input_stmt), ctx); + + ctx = new_omp_context (scan_stmt, outer_ctx); + scan_omp (gimple_omp_body_ptr (scan_stmt), ctx); + + maybe_lookup_ctx (new_stmt)->for_simd_scan_phase = true; +} + /* Scan an OpenMP sections directive. */ static void @@ -3319,6 +3401,19 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, break; case GIMPLE_OMP_FOR: + if ((gimple_omp_for_kind (as_a (stmt)) + == GF_OMP_FOR_KIND_SIMD) + && gimple_omp_for_combined_into_p (stmt) + && gimple_code (ctx->stmt) != GIMPLE_OMP_SCAN) + { + tree clauses = gimple_omp_for_clauses (as_a (stmt)); + tree c = omp_find_clause (clauses, OMP_CLAUSE_REDUCTION); + if (c && OMP_CLAUSE_REDUCTION_INSCAN (c) && !seen_error ()) + { + scan_omp_simd_scan (gsi, as_a (stmt), ctx); + break; + } + } if ((gimple_omp_for_kind (as_a (stmt)) == GF_OMP_FOR_KIND_SIMD) && omp_maybe_offloaded_ctx (ctx) @@ -3757,7 +3852,7 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, DECL_ATTRIBUTES (avar)); gimple_add_tmp_var (avar); tree iavar = avar; - if (rvar) + if (rvar && !ctx->for_simd_scan_phase) { /* For inscan reductions, create another array temporary, which will hold the reduced value. */ @@ -5213,7 +5308,16 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, x = lang_hooks.decls.omp_clause_default_ctor (c, unshare_expr (ivar), build_outer_var_ref (var, ctx)); - if (rvarp) + if (rvarp && ctx->for_simd_scan_phase) + { + if (x) + gimplify_and_add (x, &llist[0]); + x = lang_hooks.decls.omp_clause_dtor (c, ivar); + if (x) + gimplify_and_add (x, &llist[1]); + break; + } + else if (rvarp) { if (x) { @@ -5371,6 +5475,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION && OMP_CLAUSE_REDUCTION_INSCAN (c)) { + if (ctx->for_simd_scan_phase) + goto do_dtor; if (x || (!is_simd && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))) { @@ -5532,6 +5638,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (rvarp) { + if (ctx->for_simd_scan_phase) + break; gimplify_assign (ivar, ref, &llist[0]); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, rvar, &llist[3]); @@ -8629,11 +8737,13 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) bool input_phase = has_clauses ^ octx->scan_inclusive; bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD) - && !gimple_omp_for_combined_into_p (octx->stmt)); + && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD)); bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR && !gimple_omp_for_combined_p (octx->stmt)); + bool is_for_simd = is_simd && gimple_omp_for_combined_into_p (octx->stmt); + if (is_for_simd && octx->for_simd_scan_phase) + is_simd = false; if (is_simd) if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt), OMP_CLAUSE__SIMDUID_)) @@ -8866,10 +8976,7 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) } } } - else if (has_clauses) - sorry_at (gimple_location (stmt), - "%<#pragma omp scan%> not supported yet"); - if (!is_for) + if (is_simd && !is_for_simd) { gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT); gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT); @@ -9115,6 +9222,12 @@ omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, { WALK_SUBSTMTS; + case GIMPLE_OMP_FOR: + if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_combined_into_p (stmt)) + *handled_ops_p = false; + break; + case GIMPLE_OMP_SCAN: *(gimple_stmt_iterator *) (wi->info) = *gsi_p; return integer_zero_node; @@ -9255,6 +9368,7 @@ static void lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, struct omp_for_data *fd, omp_context *ctx) { + bool is_for_simd = gimple_omp_for_combined_p (stmt); gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive); gimple_seq body = gimple_omp_body (stmt); @@ -9299,6 +9413,45 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN); gimple_omp_set_body (scan_stmt2, scan_body); + gimple_stmt_iterator input3_gsi = gsi_none (); + gimple_stmt_iterator scan3_gsi = gsi_none (); + gimple_stmt_iterator input4_gsi = gsi_none (); + gimple_stmt_iterator scan4_gsi = gsi_none (); + gimple *input_stmt3 = NULL, *scan_stmt3 = NULL; + gimple *input_stmt4 = NULL, *scan_stmt4 = NULL; + omp_context *input_simd_ctx = NULL, *scan_simd_ctx = NULL; + if (is_for_simd) + { + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input3_gsi; + walk_gimple_seq_mod (&input_body, omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input3_gsi)); + + input_stmt3 = gsi_stmt (input3_gsi); + gsi = input3_gsi; + gsi_next (&gsi); + scan3_gsi = gsi; + scan_stmt3 = gsi_stmt (gsi); + gcc_assert (scan_stmt3 && gimple_code (scan_stmt3) == GIMPLE_OMP_SCAN); + + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input4_gsi; + walk_gimple_seq_mod (&scan_body, omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input4_gsi)); + + input_stmt4 = gsi_stmt (input4_gsi); + gsi = input4_gsi; + gsi_next (&gsi); + scan4_gsi = gsi; + scan_stmt4 = gsi_stmt (gsi); + gcc_assert (scan_stmt4 && gimple_code (scan_stmt4) == GIMPLE_OMP_SCAN); + + input_simd_ctx = maybe_lookup_ctx (input_stmt3)->outer; + scan_simd_ctx = maybe_lookup_ctx (input_stmt4)->outer; + } + tree num_threads = create_tmp_var (integer_type_node); tree thread_num = create_tmp_var (integer_type_node); tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS); @@ -9390,6 +9543,18 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x); tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x); + tree var4 = is_for_simd ? new_var : var2; + tree var5 = NULL_TREE, var6 = NULL_TREE; + if (is_for_simd) + { + var5 = lookup_decl (var, input_simd_ctx); + var6 = lookup_decl (var, scan_simd_ctx); + if (new_vard != new_var) + { + var5 = build_simple_mem_ref_loc (clause_loc, var5); + var6 = build_simple_mem_ref_loc (clause_loc, var6); + } + } if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) { tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); @@ -9401,16 +9566,19 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gimplify_and_add (x, &clist); x = build_outer_var_ref (var, ctx); - x = lang_hooks.decls.omp_clause_assign_op (c, var2, x); + x = lang_hooks.decls.omp_clause_assign_op (c, unshare_expr (var4), + x); gimplify_and_add (x, &thr01_list); tree y = (DECL_HAS_VALUE_EXPR_P (new_vard) ? DECL_VALUE_EXPR (new_vard) : NULL_TREE); if (var3) { - x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var3); gimplify_and_add (x, &thrn1_list); - x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var3); gimplify_and_add (x, &thr02_list); } else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)) @@ -9418,11 +9586,13 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, /* Otherwise, assign to it the identity element. */ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c); tseq = copy_gimple_seq_and_replace_locals (tseq); - - if (new_vard != new_var) - val = build_fold_addr_expr_loc (clause_loc, val); - SET_DECL_VALUE_EXPR (new_vard, val); - DECL_HAS_VALUE_EXPR_P (new_vard) = 1; + if (!is_for_simd) + { + if (new_vard != new_var) + val = build_fold_addr_expr_loc (clause_loc, val); + SET_DECL_VALUE_EXPR (new_vard, val); + DECL_HAS_VALUE_EXPR_P (new_vard) = 1; + } SET_DECL_VALUE_EXPR (placeholder, error_mark_node); DECL_HAS_VALUE_EXPR_P (placeholder) = 1; lower_omp (&tseq, ctx); @@ -9442,47 +9612,64 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, } } - x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivam1_ref); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivam1_ref); gimplify_and_add (x, &thrn2_list); - if (ctx->scan_exclusive) + if (is_for_simd) { x = unshare_expr (rprivb_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var5); gimplify_and_add (x, &scan1_list); } + else + { + if (ctx->scan_exclusive) + { + x = unshare_expr (rprivb_ref); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + gimplify_and_add (x, &scan1_list); + } - gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); - tseq = copy_gimple_seq_and_replace_locals (tseq); - SET_DECL_VALUE_EXPR (placeholder, var2); - DECL_HAS_VALUE_EXPR_P (placeholder) = 1; - lower_omp (&tseq, ctx); - gimple_seq_add_seq (&scan1_list, tseq); + gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); + tseq = copy_gimple_seq_and_replace_locals (tseq); + SET_DECL_VALUE_EXPR (placeholder, var2); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + lower_omp (&tseq, ctx); + gimple_seq_add_seq (&scan1_list, tseq); - if (ctx->scan_inclusive) - { - x = unshare_expr (rprivb_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); - gimplify_and_add (x, &scan1_list); + if (ctx->scan_inclusive) + { + x = unshare_expr (rprivb_ref); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + gimplify_and_add (x, &scan1_list); + } } x = unshare_expr (rpriva_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = lang_hooks.decls.omp_clause_assign_op (c, x, + unshare_expr (var4)); gimplify_and_add (x, &mdlist); - x = unshare_expr (new_var); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = unshare_expr (is_for_simd ? var6 : new_var); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var4); gimplify_and_add (x, &input2_list); val = rprivb_ref; if (new_vard != new_var) val = build_fold_addr_expr_loc (clause_loc, val); - tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); + gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); tseq = copy_gimple_seq_and_replace_locals (tseq); SET_DECL_VALUE_EXPR (new_vard, val); DECL_HAS_VALUE_EXPR_P (new_vard) = 1; - DECL_HAS_VALUE_EXPR_P (placeholder) = 0; + if (is_for_simd) + { + SET_DECL_VALUE_EXPR (placeholder, var6); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + } + else + DECL_HAS_VALUE_EXPR_P (placeholder) = 0; lower_omp (&tseq, ctx); if (y) SET_DECL_VALUE_EXPR (new_vard, y); @@ -9491,9 +9678,12 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, DECL_HAS_VALUE_EXPR_P (new_vard) = 0; SET_DECL_VALUE_EXPR (new_vard, NULL_TREE); } - SET_DECL_VALUE_EXPR (placeholder, new_var); - DECL_HAS_VALUE_EXPR_P (placeholder) = 1; - lower_omp (&tseq, ctx); + if (!is_for_simd) + { + SET_DECL_VALUE_EXPR (placeholder, new_var); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + lower_omp (&tseq, ctx); + } gimple_seq_add_seq (&input2_list, tseq); x = build_outer_var_ref (var, ctx); @@ -9532,29 +9722,38 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, else { x = build_outer_var_ref (var, ctx); - gimplify_assign (var2, x, &thr01_list); + gimplify_assign (unshare_expr (var4), x, &thr01_list); x = omp_reduction_init (c, TREE_TYPE (new_var)); - gimplify_assign (var2, unshare_expr (x), &thrn1_list); - gimplify_assign (var2, x, &thr02_list); + gimplify_assign (unshare_expr (var4), unshare_expr (x), + &thrn1_list); + gimplify_assign (unshare_expr (var4), x, &thr02_list); - gimplify_assign (var2, rprivam1_ref, &thrn2_list); + gimplify_assign (unshare_expr (var4), rprivam1_ref, &thrn2_list); enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c); if (code == MINUS_EXPR) code = PLUS_EXPR; - if (ctx->scan_exclusive) - gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list); - x = build2 (code, TREE_TYPE (new_var), var2, new_var); - gimplify_assign (var2, x, &scan1_list); - if (ctx->scan_inclusive) - gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list); + if (is_for_simd) + gimplify_assign (unshare_expr (rprivb_ref), var5, &scan1_list); + else + { + if (ctx->scan_exclusive) + gimplify_assign (unshare_expr (rprivb_ref), var2, + &scan1_list); + x = build2 (code, TREE_TYPE (new_var), var2, new_var); + gimplify_assign (var2, x, &scan1_list); + if (ctx->scan_inclusive) + gimplify_assign (unshare_expr (rprivb_ref), var2, + &scan1_list); + } - gimplify_assign (unshare_expr (rpriva_ref), var2, &mdlist); + gimplify_assign (unshare_expr (rpriva_ref), unshare_expr (var4), + &mdlist); - x = build2 (code, TREE_TYPE (new_var), var2, rprivb_ref); - gimplify_assign (new_var, x, &input2_list); + x = build2 (code, TREE_TYPE (new_var), var4, rprivb_ref); + gimplify_assign (is_for_simd ? var6 : new_var, x, &input2_list); gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref, &last_list); @@ -9568,7 +9767,8 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node); gimple_seq_add_stmt (&scan1_list, g); g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node); - gimple_seq_add_stmt (gimple_omp_body_ptr (scan_stmt2), g); + gimple_seq_add_stmt (gimple_omp_body_ptr (is_for_simd + ? scan_stmt4 : scan_stmt2), g); tree controlb = create_tmp_var (boolean_type_node); tree controlp = create_tmp_var (ptr_type_node); @@ -9598,8 +9798,29 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, *cp2 = gimple_omp_for_clauses (new_stmt); gimple_omp_for_set_clauses (new_stmt, new_clauses2); - gimple_omp_set_body (scan_stmt1, scan1_list); - gimple_omp_set_body (input_stmt2, input2_list); + if (is_for_simd) + { + gimple_seq_add_seq (gimple_omp_body_ptr (scan_stmt3), scan1_list); + gimple_seq_add_seq (gimple_omp_body_ptr (input_stmt4), input2_list); + + gsi_insert_seq_after (&input3_gsi, gimple_omp_body (input_stmt3), + GSI_SAME_STMT); + gsi_remove (&input3_gsi, true); + gsi_insert_seq_after (&scan3_gsi, gimple_omp_body (scan_stmt3), + GSI_SAME_STMT); + gsi_remove (&scan3_gsi, true); + gsi_insert_seq_after (&input4_gsi, gimple_omp_body (input_stmt4), + GSI_SAME_STMT); + gsi_remove (&input4_gsi, true); + gsi_insert_seq_after (&scan4_gsi, gimple_omp_body (scan_stmt4), + GSI_SAME_STMT); + gsi_remove (&scan4_gsi, true); + } + else + { + gimple_omp_set_body (scan_stmt1, scan1_list); + gimple_omp_set_body (input_stmt2, input2_list); + } gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1), GSI_SAME_STMT); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5a848eb77ec..cc0661a947e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2019-07-06 Jakub Jelinek + * c-c++-common/gomp/scan-4.c: Don't expect sorry message. + PR tree-optimization/91096 * gcc.dg/vect/vect-simd-10.c (FLT_MIN_VALUE): Define. (bar, main): Use it instead of -__builtin_inff (). diff --git a/gcc/testsuite/c-c++-common/gomp/scan-4.c b/gcc/testsuite/c-c++-common/gomp/scan-4.c index 32d40065786..b2e22e81cd1 100644 --- a/gcc/testsuite/c-c++-common/gomp/scan-4.c +++ b/gcc/testsuite/c-c++-common/gomp/scan-4.c @@ -8,7 +8,7 @@ f1 (int *c, int *d) for (i = 0; i < 64; i++) { d[i] = a; - #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */ + #pragma omp scan exclusive (a) a += c[i]; } } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 01a8714ef74..8ffe379f74c 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,22 @@ +2019-07-06 Jakub Jelinek + + * testsuite/libgomp.c/scan-11.c: New test. + * testsuite/libgomp.c/scan-12.c: New test. + * testsuite/libgomp.c/scan-13.c: New test. + * testsuite/libgomp.c/scan-14.c: New test. + * testsuite/libgomp.c/scan-15.c: New test. + * testsuite/libgomp.c/scan-16.c: New test. + * testsuite/libgomp.c/scan-17.c: New test. + * testsuite/libgomp.c/scan-18.c: New test. + * testsuite/libgomp.c++/scan-9.C: New test. + * testsuite/libgomp.c++/scan-10.C: New test. + * testsuite/libgomp.c++/scan-11.C: New test. + * testsuite/libgomp.c++/scan-12.C: New test. + * testsuite/libgomp.c++/scan-13.C: New test. + * testsuite/libgomp.c++/scan-14.C: New test. + * testsuite/libgomp.c++/scan-15.C: New test. + * testsuite/libgomp.c++/scan-16.C: New test. + 2019-07-04 Jakub Jelinek * testsuite/libgomp.c/scan-9.c: New test. diff --git a/libgomp/testsuite/libgomp.c++/scan-10.C b/libgomp/testsuite/libgomp.c++/scan-10.C new file mode 100644 index 00000000000..c72ba6ee5d9 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-10.C @@ -0,0 +1,119 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); +int r, a[1024], b[1024], q; + +__attribute__((noipa)) void +foo (int *a, int *b, int &r) +{ + #pragma omp for simd if (0) reduction (inscan, +:r) nowait + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int &s = q; + q = 0; + #pragma omp parallel + #pragma omp for simd simdlen(1) reduction (inscan, +:s) nowait + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b, int &r) +{ + #pragma omp parallel for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int &s = q; + q = 0; + #pragma omp parallel for simd reduction (inscan, +:s) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = 25; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + else + b[i] = -1; + } + r = 0; + baz (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = -25; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-11.C b/libgomp/testsuite/libgomp.c++/scan-11.C new file mode 100644 index 00000000000..d618f125617 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-11.C @@ -0,0 +1,122 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); +int r, a[1024], b[1024], q; + +#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0) + +__attribute__((noipa)) void +foo (int *a, int *b, int &r) +{ + #pragma omp for simd reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int &s = q; + q = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, foo:s) if (0) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b, int &r) +{ + #pragma omp parallel for simd simdlen (1) reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int &s = q; + q = 0; + #pragma omp parallel for simd reduction (inscan, foo:s) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = 25; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + else + b[i] = -1; + } + r = 0; + baz (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = -25; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/scan-12.C b/libgomp/testsuite/libgomp.c++/scan-12.C new file mode 100644 index 00000000000..6f9bfc3723f --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-12.C @@ -0,0 +1,153 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); + +struct S { + inline S (); + inline ~S (); + inline S (const S &); + inline S & operator= (const S &); + int s; +}; + +S::S () : s (0) +{ +} + +S::~S () +{ +} + +S::S (const S &x) +{ + s = x.s; +} + +S & +S::operator= (const S &x) +{ + s = x.s; + return *this; +} + +static inline void +ini (S &x) +{ + x.s = 0; +} + +S r, a[1024], b[1024]; + +#pragma omp declare reduction (+: S: omp_out.s += omp_in.s) +#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv)) + +__attribute__((noipa)) void +foo (S *a, S *b, S &r) +{ + #pragma omp for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r.s += a[i].s; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) S +bar () +{ + S s; + #pragma omp parallel + #pragma omp for simd reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + s.s += 2 * a[i].s; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +__attribute__((noipa)) void +baz (S *a, S *b, S &r) +{ + #pragma omp parallel for simd if (simd: 0) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r.s += a[i].s; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) S +qux () +{ + S s; + #pragma omp parallel for simd reduction (inscan, plus:s) simdlen(1) + for (int i = 0; i < 1024; i++) + { + s.s += 2 * a[i].s; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + S s; + for (int i = 0; i < 1024; ++i) + { + a[i].s = i; + b[i].s = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r.s != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s.s += i; + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + } + if (bar ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += 2 * i; + if (b[i].s != s.s) + abort (); + } + r.s = 0; + baz (a, b, r); + if (r.s != 1024 * 1023 / 2) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += i; + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + } + if (qux ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += 2 * i; + if (b[i].s != s.s) + abort (); + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-13.C b/libgomp/testsuite/libgomp.c++/scan-13.C new file mode 100644 index 00000000000..eb91297a827 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-13.C @@ -0,0 +1,161 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { xfail *-*-* } } } + +extern "C" void abort (); + +template +struct S { + inline S (); + inline ~S (); + inline S (const S &); + inline S & operator= (const S &); + T s; +}; + +template +S::S () : s (0) +{ +} + +template +S::~S () +{ +} + +template +S::S (const S &x) +{ + s = x.s; +} + +template +S & +S::operator= (const S &x) +{ + s = x.s; + return *this; +} + +template +static inline void +ini (S &x) +{ + x.s = 0; +} + +S r, a[1024], b[1024]; + +#pragma omp declare reduction (+: S: omp_out.s += omp_in.s) +#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv)) + +template +__attribute__((noipa)) void +foo (S *a, S *b) +{ + #pragma omp for simd if (0) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r.s += a[i].s; + } +} + +template +__attribute__((noipa)) S +bar (void) +{ + S s; + #pragma omp parallel + #pragma omp for simd reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s.s += 2 * a[i].s; + } + return S (s); +} + +__attribute__((noipa)) void +baz (S *a, S *b) +{ + #pragma omp parallel for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r.s += a[i].s; + } +} + +__attribute__((noipa)) S +qux (void) +{ + S s; + #pragma omp parallel for simd simdlen(1) reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s.s += 2 * a[i].s; + } + return S (s); +} + +int +main () +{ + S s; + for (int i = 0; i < 1024; ++i) + { + a[i].s = i; + b[i].s = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r.s != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + s.s += i; + } + if (bar ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + s.s += 2 * i; + } + r.s = 0; + baz (a, b); + if (r.s != 1024 * 1023 / 2) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + s.s += i; + } + if (qux ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + s.s += 2 * i; + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-14.C b/libgomp/testsuite/libgomp.c++/scan-14.C new file mode 100644 index 00000000000..197ec6e8b19 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-14.C @@ -0,0 +1,123 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); +int r, a[1024], b[1024], q; + +template +__attribute__((noipa)) void +foo (T a, T b, U r) +{ + #pragma omp for simd if (0) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +template +__attribute__((noipa)) T +bar () +{ + T &s = q; + q = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, +:s) simdlen(1) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +template +__attribute__((noipa)) void +baz (T *a, T *b, T &r) +{ + #pragma omp parallel for simd reduction (inscan, +:r) + for (T i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +template +__attribute__((noipa)) int +qux () +{ + T s = q; + q = 0; + #pragma omp parallel for simd reduction (inscan, +:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = 25; + s += i; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -1; + s += 2 * i; + } + r = 0; + baz (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -25; + s += i; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + s += 2 * i; + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-15.C b/libgomp/testsuite/libgomp.c++/scan-15.C new file mode 100644 index 00000000000..b6a8787aa44 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-15.C @@ -0,0 +1,121 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); +int r, a[1024], b[1024], q; + +#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0) + +__attribute__((noipa)) void +foo (int *a, int *b, int &r) +{ + #pragma omp for simd reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int &s = q; + q = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, foo:s) nowait + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b, int &r) +{ + #pragma omp parallel for simd reduction (inscan, foo:r) if (simd: 0) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int &s = q; + q = 0; + #pragma omp parallel for simd reduction (inscan, foo:s)simdlen(1) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = 25; + s += i; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -1; + s += 2 * i; + } + r = 0; + baz (a, b, r); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -25; + s += i; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + s += 2 * i; + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-16.C b/libgomp/testsuite/libgomp.c++/scan-16.C new file mode 100644 index 00000000000..025860e8c7a --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-16.C @@ -0,0 +1,153 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { xfail *-*-* } } } + +extern "C" void abort (); + +struct S { + inline S (); + inline ~S (); + inline S (const S &); + inline S & operator= (const S &); + int s; +}; + +S::S () : s (0) +{ +} + +S::~S () +{ +} + +S::S (const S &x) +{ + s = x.s; +} + +S & +S::operator= (const S &x) +{ + s = x.s; + return *this; +} + +static inline void +ini (S &x) +{ + x.s = 0; +} + +S r, a[1024], b[1024]; + +#pragma omp declare reduction (+: S: omp_out.s += omp_in.s) +#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv)) + +__attribute__((noipa)) void +foo (S *a, S *b, S &r) +{ + #pragma omp for simd simdlen (1) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r.s += a[i].s; + } +} + +__attribute__((noipa)) S +bar (void) +{ + S s; + #pragma omp parallel + #pragma omp for simd if (0) reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s.s += 2 * a[i].s; + } + return s; +} + +__attribute__((noipa)) void +baz (S *a, S *b, S &r) +{ + #pragma omp parallel for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r.s += a[i].s; + } +} + +__attribute__((noipa)) S +qux (void) +{ + S s; + #pragma omp parallel for simd reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s.s += 2 * a[i].s; + } + return s; +} + +int +main () +{ + S s; + for (int i = 0; i < 1024; ++i) + { + a[i].s = i; + b[i].s = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, r); + if (r.s != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + s.s += i; + } + if (bar ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + s.s += 2 * i; + } + r.s = 0; + baz (a, b, r); + if (r.s != 1024 * 1023 / 2) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + s.s += i; + } + if (qux ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i].s != s.s) + abort (); + s.s += 2 * i; + } +} diff --git a/libgomp/testsuite/libgomp.c++/scan-9.C b/libgomp/testsuite/libgomp.c++/scan-9.C new file mode 100644 index 00000000000..340004e3b41 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/scan-9.C @@ -0,0 +1,154 @@ +// { dg-require-effective-target size32plus } +// { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } + +extern "C" void abort (); + +struct S { + inline S (); + inline ~S (); + inline S (const S &); + inline S & operator= (const S &); + int s; +}; + +S::S () : s (0) +{ +} + +S::~S () +{ +} + +S::S (const S &x) +{ + s = x.s; +} + +S & +S::operator= (const S &x) +{ + s = x.s; + return *this; +} + +static inline void +ini (S &x) +{ + x.s = 0; +} + +S r, a[1024], b[1024]; + +#pragma omp declare reduction (+: S: omp_out.s += omp_in.s) +#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv)) + +__attribute__((noipa)) void +foo (S *a, S *b) +{ + #pragma omp for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r.s += a[i].s; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) S +bar (void) +{ + S s; + #pragma omp parallel + #pragma omp for simd reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + s.s += 2 * a[i].s; + #pragma omp scan inclusive(s) + b[i] = s; + } + return S (s); +} + +__attribute__((noipa)) void +baz (S *a, S *b) +{ + #pragma omp parallel for simd simdlen (1) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r.s += a[i].s; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) S +qux (void) +{ + S s; + #pragma omp parallel for simd if (simd: 0) reduction (inscan, plus:s) + for (int i = 0; i < 1024; i++) + { + s.s += 2 * a[i].s; + #pragma omp scan inclusive(s) + b[i] = s; + } + return S (s); +} + +int +main () +{ + S s; + for (int i = 0; i < 1024; ++i) + { + a[i].s = i; + b[i].s = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r.s != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s.s += i; + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + } + if (bar ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += 2 * i; + if (b[i].s != s.s) + abort (); + } + r.s = 0; + baz (a, b); + if (r.s != 1024 * 1023 / 2) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += i; + if (b[i].s != s.s) + abort (); + else + b[i].s = 25; + } + if (qux ().s != 1024 * 1023) + abort (); + s.s = 0; + for (int i = 0; i < 1024; ++i) + { + s.s += 2 * i; + if (b[i].s != s.s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-11.c b/libgomp/testsuite/libgomp.c/scan-11.c new file mode 100644 index 00000000000..7443a504440 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-11.c @@ -0,0 +1,118 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; + +__attribute__((noipa)) void +foo (int *a, int *b) +{ + #pragma omp for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int s = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, +:s) if (0) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b) +{ + #pragma omp parallel for simd reduction (inscan, +:r) simdlen(1) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int s = 0; + #pragma omp parallel for simd reduction (inscan, +:s) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = 25; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + else + b[i] = -1; + } + r = 0; + baz (a, b); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = -25; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-12.c b/libgomp/testsuite/libgomp.c/scan-12.c new file mode 100644 index 00000000000..6e320468742 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-12.c @@ -0,0 +1,120 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; + +#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0) + +__attribute__((noipa)) void +foo (int *a, int *b) +{ + #pragma omp for simd reduction (inscan, foo:r) simdlen (1) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int s = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, foo:s) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b) +{ + #pragma omp parallel for simd reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + r += a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int s = 0; + #pragma omp parallel for simd if (simd: 0) reduction (inscan, foo:s) + for (int i = 0; i < 1024; i++) + { + s += 2 * a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = 25; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + else + b[i] = -1; + } + r = 0; + baz (a, b); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s) + abort (); + else + b[i] = -25; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-13.c b/libgomp/testsuite/libgomp.c/scan-13.c new file mode 100644 index 00000000000..3c8ce2da04d --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-13.c @@ -0,0 +1,91 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +float r = 1.0f, a[1024], b[1024]; + +__attribute__((noipa)) void +foo (float *a, float *b) +{ + #pragma omp for simd reduction (inscan, *:r) + for (int i = 0; i < 1024; i++) + { + r *= a[i]; + #pragma omp scan inclusive(r) + b[i] = r; + } +} + +__attribute__((noipa)) float +bar (void) +{ + float s = -__builtin_inff (); + #pragma omp parallel for simd reduction (inscan, max:s) + for (int i = 0; i < 1024; i++) + { + s = s > a[i] ? s : a[i]; + #pragma omp scan inclusive(s) + b[i] = s; + } + return s; +} + +int +main () +{ + float s = 1.0f; + for (int i = 0; i < 1024; ++i) + { + if (i < 80) + a[i] = (i & 1) ? 0.25f : 0.5f; + else if (i < 200) + a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f; + else if (i < 280) + a[i] = (i & 1) ? 0.25f : 0.5f; + else if (i < 380) + a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f; + else + switch (i % 6) + { + case 0: a[i] = 0.25f; break; + case 1: a[i] = 2.0f; break; + case 2: a[i] = -1.0f; break; + case 3: a[i] = -4.0f; break; + case 4: a[i] = 0.5f; break; + case 5: a[i] = 1.0f; break; + default: a[i] = 0.0f; break; + } + b[i] = -19.0f; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r * 16384.0f != 0.125f) + abort (); + float m = -175.25f; + for (int i = 0; i < 1024; ++i) + { + s *= a[i]; + if (b[i] != s) + abort (); + else + { + a[i] = m - ((i % 3) == 1 ? 2.0f : (i % 3) == 2 ? 4.0f : 0.0f); + b[i] = -231.75f; + m += 0.75f; + } + } + if (bar () != 592.0f) + abort (); + s = -__builtin_inff (); + for (int i = 0; i < 1024; ++i) + { + if (s < a[i]) + s = a[i]; + if (b[i] != s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-14.c b/libgomp/testsuite/libgomp.c/scan-14.c new file mode 100644 index 00000000000..53bd11e5157 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-14.c @@ -0,0 +1,182 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; +unsigned short r2, b2[1024]; +unsigned char r3, b3[1024]; + +__attribute__((noipa)) void +foo (int *a, int *b, unsigned short *b2, unsigned char *b3) +{ + #pragma omp for simd reduction (inscan, +:r, r2, r3) if (simd:0) + for (int i = 0; i < 1024; i++) + { + { r += a[i]; r2 += a[i]; r3 += a[i]; } + #pragma omp scan inclusive(r, r2, r3) + { + b[i] = r; + b2[i] = r2; + b3[i] = r3; + } + } +} + +__attribute__((noipa)) int +bar (unsigned short *s2p, unsigned char *s3p) +{ + int s = 0; + unsigned short s2 = 0; + unsigned char s3 = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, +:s, s2, s3) simdlen (1) + for (int i = 0; i < 1024; i++) + { + { + s += 2 * a[i]; + s2 += 2 * a[i]; + s3 += 2 * a[i]; + } + #pragma omp scan inclusive(s, s2, s3) + { b[i] = s; b2[i] = s2; b3[i] = s3; } + } + *s2p = s2; + *s3p = s3; + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b, unsigned short *b2, unsigned char *b3) +{ + #pragma omp parallel for simd reduction (inscan, +:r, r2, r3) + for (int i = 0; i < 1024; i++) + { + { + r += a[i]; + r2 += a[i]; + r3 += a[i]; + } + #pragma omp scan inclusive(r, r2, r3) + { + b[i] = r; + b2[i] = r2; + b3[i] = r3; + } + } +} + +__attribute__((noipa)) int +qux (unsigned short *s2p, unsigned char *s3p) +{ + int s = 0; + unsigned short s2 = 0; + unsigned char s3 = 0; + #pragma omp parallel for simd reduction (inscan, +:s, s2, s3) + for (int i = 0; i < 1024; i++) + { + { s += 2 * a[i]; s2 += 2 * a[i]; s3 += 2 * a[i]; } + #pragma omp scan inclusive(s, s2, s3) + { b[i] = s; b2[i] = s2; b3[i] = s3; } + } + *s2p = s2; + *s3p = s3; + return s; +} + +int +main () +{ + int s = 0; + unsigned short s2; + unsigned char s3; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + b2[i] = -1; + b3[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, b2, b3); + if (r != 1024 * 1023 / 2 + || r2 != (unsigned short) r + || r3 != (unsigned char) r) + abort (); + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = 25; + b2[i] = 24; + b3[i] = 26; + } + } + if (bar (&s2, &s3) != 1024 * 1023) + abort (); + if (s2 != (unsigned short) (1024 * 1023) + || s3 != (unsigned char) (1024 * 1023)) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = -1; + b2[i] = -1; + b3[i] = -1; + } + } + r = 0; + r2 = 0; + r3 = 0; + baz (a, b, b2, b3); + if (r != 1024 * 1023 / 2 + || r2 != (unsigned short) r + || r3 != (unsigned char) r) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += i; + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = 25; + b2[i] = 24; + b3[i] = 26; + } + } + s2 = 0; + s3 = 0; + if (qux (&s2, &s3) != 1024 * 1023) + abort (); + if (s2 != (unsigned short) (1024 * 1023) + || s3 != (unsigned char) (1024 * 1023)) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + s += 2 * i; + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-15.c b/libgomp/testsuite/libgomp.c/scan-15.c new file mode 100644 index 00000000000..4a02519129b --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-15.c @@ -0,0 +1,118 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; + +__attribute__((noipa)) void +foo (int *a, int *b) +{ + #pragma omp for simd reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int s = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, +:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b) +{ + #pragma omp parallel for simd simdlen (1) reduction (inscan, +:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int s = 0; + #pragma omp parallel for simd if (simd: 0) reduction (inscan, +:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = 25; + s += i; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -1; + s += 2 * i; + } + r = 0; + baz (a, b); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -25; + s += i; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + s += 2 * i; + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-16.c b/libgomp/testsuite/libgomp.c/scan-16.c new file mode 100644 index 00000000000..53705d0f430 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-16.c @@ -0,0 +1,120 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; + +#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0) + +__attribute__((noipa)) void +foo (int *a, int *b) +{ + #pragma omp for simd reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +bar (void) +{ + int s = 0; + #pragma omp parallel + #pragma omp for simd simdlen (1) reduction (inscan, foo:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b) +{ + #pragma omp parallel for simd if (simd: 0) reduction (inscan, foo:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r += a[i]; + } +} + +__attribute__((noipa)) int +qux (void) +{ + int s = 0; + #pragma omp parallel for simd reduction (inscan, foo:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s += 2 * a[i]; + } + return s; +} + +int +main () +{ + int s = 0; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r != 1024 * 1023 / 2) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = 25; + s += i; + } + if (bar () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -1; + s += 2 * i; + } + r = 0; + baz (a, b); + if (r != 1024 * 1023 / 2) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -25; + s += i; + } + if (qux () != 1024 * 1023) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + s += 2 * i; + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-17.c b/libgomp/testsuite/libgomp.c/scan-17.c new file mode 100644 index 00000000000..22b2e62ee98 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-17.c @@ -0,0 +1,89 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +float r = 1.0f, a[1024], b[1024]; + +__attribute__((noipa)) void +foo (float *a, float *b) +{ + #pragma omp for simd reduction (inscan, *:r) + for (int i = 0; i < 1024; i++) + { + b[i] = r; + #pragma omp scan exclusive(r) + r *= a[i]; + } +} + +__attribute__((noipa)) float +bar (void) +{ + float s = -__builtin_inff (); + #pragma omp parallel for simd reduction (inscan, max:s) + for (int i = 0; i < 1024; i++) + { + b[i] = s; + #pragma omp scan exclusive(s) + s = s > a[i] ? s : a[i]; + } + return s; +} + +int +main () +{ + float s = 1.0f; + for (int i = 0; i < 1024; ++i) + { + if (i < 80) + a[i] = (i & 1) ? 0.25f : 0.5f; + else if (i < 200) + a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f; + else if (i < 280) + a[i] = (i & 1) ? 0.25f : 0.5f; + else if (i < 380) + a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f; + else + switch (i % 6) + { + case 0: a[i] = 0.25f; break; + case 1: a[i] = 2.0f; break; + case 2: a[i] = -1.0f; break; + case 3: a[i] = -4.0f; break; + case 4: a[i] = 0.5f; break; + case 5: a[i] = 1.0f; break; + default: a[i] = 0.0f; break; + } + b[i] = -19.0f; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b); + if (r * 16384.0f != 0.125f) + abort (); + float m = -175.25f; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + else + b[i] = -231.75f; + s *= a[i]; + a[i] = m - ((i % 3) == 1 ? 2.0f : (i % 3) == 2 ? 4.0f : 0.0f); + m += 0.75f; + } + if (bar () != 592.0f) + abort (); + s = -__builtin_inff (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s) + abort (); + if (s < a[i]) + s = a[i]; + } + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/scan-18.c b/libgomp/testsuite/libgomp.c/scan-18.c new file mode 100644 index 00000000000..ea13687bb06 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/scan-18.c @@ -0,0 +1,182 @@ +/* { dg-require-effective-target size32plus } */ +/* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */ + +extern void abort (void); +int r, a[1024], b[1024]; +unsigned short r2, b2[1024]; +unsigned char r3, b3[1024]; + +__attribute__((noipa)) void +foo (int *a, int *b, unsigned short *b2, unsigned char *b3) +{ + #pragma omp for simd reduction (inscan, +:r, r2, r3) + for (int i = 0; i < 1024; i++) + { + { + b[i] = r; + b2[i] = r2; + b3[i] = r3; + } + #pragma omp scan exclusive(r, r2, r3) + { r += a[i]; r2 += a[i]; r3 += a[i]; } + } +} + +__attribute__((noipa)) int +bar (unsigned short *s2p, unsigned char *s3p) +{ + int s = 0; + unsigned short s2 = 0; + unsigned char s3 = 0; + #pragma omp parallel + #pragma omp for simd reduction (inscan, +:s, s2, s3) + for (int i = 0; i < 1024; i++) + { + { b[i] = s; b2[i] = s2; b3[i] = s3; } + #pragma omp scan exclusive(s, s2, s3) + { + s += 2 * a[i]; + s2 += 2 * a[i]; + s3 += 2 * a[i]; + } + } + *s2p = s2; + *s3p = s3; + return s; +} + +__attribute__((noipa)) void +baz (int *a, int *b, unsigned short *b2, unsigned char *b3) +{ + #pragma omp parallel for simd reduction (inscan, +:r, r2, r3) if (simd: 0) + for (int i = 0; i < 1024; i++) + { + { + b[i] = r; + b2[i] = r2; + b3[i] = r3; + } + #pragma omp scan exclusive(r, r2, r3) + { + r += a[i]; + r2 += a[i]; + r3 += a[i]; + } + } +} + +__attribute__((noipa)) int +qux (unsigned short *s2p, unsigned char *s3p) +{ + int s = 0; + unsigned short s2 = 0; + unsigned char s3 = 0; + #pragma omp parallel for simd simdlen (1) reduction (inscan, +:s, s2, s3) + for (int i = 0; i < 1024; i++) + { + { b[i] = s; b2[i] = s2; b3[i] = s3; } + #pragma omp scan exclusive(s, s2, s3) + { s += 2 * a[i]; s2 += 2 * a[i]; s3 += 2 * a[i]; } + } + *s2p = s2; + *s3p = s3; + return s; +} + +int +main () +{ + int s = 0; + unsigned short s2; + unsigned char s3; + for (int i = 0; i < 1024; ++i) + { + a[i] = i; + b[i] = -1; + b2[i] = -1; + b3[i] = -1; + asm ("" : "+g" (i)); + } + #pragma omp parallel + foo (a, b, b2, b3); + if (r != 1024 * 1023 / 2 + || r2 != (unsigned short) r + || r3 != (unsigned char) r) + abort (); + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = 25; + b2[i] = 24; + b3[i] = 26; + } + s += i; + } + if (bar (&s2, &s3) != 1024 * 1023) + abort (); + if (s2 != (unsigned short) (1024 * 1023) + || s3 != (unsigned char) (1024 * 1023)) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = -1; + b2[i] = -1; + b3[i] = -1; + } + s += 2 * i; + } + r = 0; + r2 = 0; + r3 = 0; + baz (a, b, b2, b3); + if (r != 1024 * 1023 / 2 + || r2 != (unsigned short) r + || r3 != (unsigned char) r) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + else + { + b[i] = 25; + b2[i] = 24; + b3[i] = 26; + } + s += i; + } + s2 = 0; + s3 = 0; + if (qux (&s2, &s3) != 1024 * 1023) + abort (); + if (s2 != (unsigned short) (1024 * 1023) + || s3 != (unsigned char) (1024 * 1023)) + abort (); + s = 0; + for (int i = 0; i < 1024; ++i) + { + if (b[i] != s + || b2[i] != (unsigned short) s + || b3[i] != (unsigned char) s) + abort (); + s += 2 * i; + } + return 0; +}