From 1580fc764423bf89e9b853aaa8c65999e37ccb8b Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Tue, 4 May 2021 13:38:03 +0200 Subject: OpenMP: Support complex/float in && and || reduction C/C++ permit logical AND and logical OR also with floating-point or complex arguments by doing an unequal zero comparison; the result is an 'int' with value one or zero. Hence, those are also permitted as reduction variable, even though it is not the most sensible thing to do. gcc/c/ChangeLog: * c-typeck.c (c_finish_omp_clauses): Accept float + complex for || and && reductions. gcc/cp/ChangeLog: * semantics.c (finish_omp_reduction_clause): Accept float + complex for || and && reductions. gcc/ChangeLog: * omp-low.c (lower_rec_input_clauses, lower_reduction_clauses): Handle && and || with floating-point and complex arguments. gcc/testsuite/ChangeLog: * gcc.dg/gomp/clause-1.c: Use 'reduction(&:..)' instead of '...(&&:..)'. libgomp/ChangeLog: * testsuite/libgomp.c-c++-common/reduction-1.c: New test. * testsuite/libgomp.c-c++-common/reduction-2.c: New test. * testsuite/libgomp.c-c++-common/reduction-3.c: New test. --- gcc/omp-low.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 6 deletions(-) (limited to 'gcc/omp-low.c') diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 1f14c4b..26ceaf7 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -6389,6 +6389,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (code == MINUS_EXPR) code = PLUS_EXPR; + /* C/C++ permits FP/complex with || and &&. */ + bool is_fp_and_or + = ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) + && (FLOAT_TYPE_P (TREE_TYPE (new_var)) + || TREE_CODE (TREE_TYPE (new_var)) == COMPLEX_TYPE)); tree new_vard = new_var; if (is_simd && omp_is_reference (var)) { @@ -6437,7 +6442,20 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, x = build2 (code, TREE_TYPE (ivar), ivar, x); gimplify_assign (ivar, x, &llist[2]); } - x = build2 (code, TREE_TYPE (ref), ref, ivar); + tree ivar2 = ivar; + tree ref2 = ref; + if (is_fp_and_or) + { + tree zero = build_zero_cst (TREE_TYPE (ivar)); + ivar2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, ivar, + zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, ref, zero); + } + x = build2 (code, TREE_TYPE (ref), ref2, ivar2); + if (is_fp_and_or) + x = fold_convert (TREE_TYPE (ref), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, &llist[1]); @@ -6456,8 +6474,22 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (is_simd) { tree ref = build_outer_var_ref (var, ctx); - - x = build2 (code, TREE_TYPE (ref), ref, new_var); + tree new_var2 = new_var; + tree ref2 = ref; + if (is_fp_and_or) + { + tree zero = build_zero_cst (TREE_TYPE (new_var)); + new_var2 + = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, new_var, + zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, ref, + zero); + } + x = build2 (code, TREE_TYPE (ref2), ref2, new_var2); + if (is_fp_and_or) + x = fold_convert (TREE_TYPE (new_var), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, dlist); } @@ -7397,13 +7429,32 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, if (code == MINUS_EXPR) code = PLUS_EXPR; + /* C/C++ permits FP/complex with || and &&. */ + bool is_fp_and_or = ((code == TRUTH_ANDIF_EXPR + || code == TRUTH_ORIF_EXPR) + && (FLOAT_TYPE_P (TREE_TYPE (new_var)) + || (TREE_CODE (TREE_TYPE (new_var)) + == COMPLEX_TYPE))); if (count == 1) { tree addr = build_fold_addr_expr_loc (clause_loc, ref); addr = save_expr (addr); ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr); - x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var); + tree new_var2 = new_var; + tree ref2 = ref; + if (is_fp_and_or) + { + tree zero = build_zero_cst (TREE_TYPE (new_var)); + new_var2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, new_var, zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, integer_type_node, + ref, zero); + } + x = fold_build2_loc (clause_loc, code, TREE_TYPE (new_var2), ref2, + new_var2); + if (is_fp_and_or) + x = fold_convert (TREE_TYPE (new_var), x); x = build2 (OMP_ATOMIC, void_type_node, addr, x); OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED; gimplify_and_add (x, stmt_seqp); @@ -7508,7 +7559,19 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, } else { - x = build2 (code, TREE_TYPE (out), out, priv); + tree out2 = out; + tree priv2 = priv; + if (is_fp_and_or) + { + tree zero = build_zero_cst (TREE_TYPE (out)); + out2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, out, zero); + priv2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, priv, zero); + } + x = build2 (code, TREE_TYPE (out2), out2, priv2); + if (is_fp_and_or) + x = fold_convert (TREE_TYPE (out), x); out = unshare_expr (out); gimplify_assign (out, x, &sub_seq); } @@ -7542,7 +7605,19 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, } else { - x = build2 (code, TREE_TYPE (ref), ref, new_var); + tree new_var2 = new_var; + tree ref2 = ref; + if (is_fp_and_or) + { + tree zero = build_zero_cst (TREE_TYPE (new_var)); + new_var2 = fold_build2_loc (clause_loc, NE_EXPR, + integer_type_node, new_var, zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, integer_type_node, + ref, zero); + } + x = build2 (code, TREE_TYPE (ref), ref2, new_var2); + if (is_fp_and_or) + x = fold_convert (TREE_TYPE (new_var), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, &sub_seq); } -- cgit v1.1