aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-typeck.c10
-rw-r--r--gcc/cp/semantics.c8
-rw-r--r--gcc/omp-low.c87
-rw-r--r--gcc/testsuite/gcc.dg/gomp/clause-1.c2
4 files changed, 86 insertions, 21 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 3b45cfd..fdc7bb6 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -14097,6 +14097,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
break;
case MIN_EXPR:
if (TREE_CODE (type) == COMPLEX_TYPE)
@@ -14115,14 +14117,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case BIT_IOR_EXPR:
r_name = "|";
break;
- case TRUTH_ANDIF_EXPR:
- if (FLOAT_TYPE_P (type))
- r_name = "&&";
- break;
- case TRUTH_ORIF_EXPR:
- if (FLOAT_TYPE_P (type))
- r_name = "||";
- break;
default:
gcc_unreachable ();
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6224f49..0d590c3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6032,6 +6032,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
predefined = true;
break;
case MIN_EXPR:
@@ -6047,12 +6049,6 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
break;
predefined = true;
break;
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- if (FLOAT_TYPE_P (type))
- break;
- predefined = true;
- break;
default:
break;
}
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);
}
diff --git a/gcc/testsuite/gcc.dg/gomp/clause-1.c b/gcc/testsuite/gcc.dg/gomp/clause-1.c
index 9d34b041..8e7cc95 100644
--- a/gcc/testsuite/gcc.dg/gomp/clause-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/clause-1.c
@@ -56,7 +56,7 @@ foo (int x)
;
#pragma omp p reduction (|:d) /* { dg-error "has invalid type for" } */
;
-#pragma omp p reduction (&&:d) /* { dg-error "has invalid type for" } */
+#pragma omp p reduction (&:d) /* { dg-error "has invalid type for" } */
;
#pragma omp p copyin (d) /* { dg-error "must be 'threadprivate'" } */
;