mirror of git://gcc.gnu.org/git/gcc.git
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.
This commit is contained in:
parent
9174343256
commit
1580fc7644
|
@ -14097,6 +14097,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||||
case PLUS_EXPR:
|
case PLUS_EXPR:
|
||||||
case MULT_EXPR:
|
case MULT_EXPR:
|
||||||
case MINUS_EXPR:
|
case MINUS_EXPR:
|
||||||
|
case TRUTH_ANDIF_EXPR:
|
||||||
|
case TRUTH_ORIF_EXPR:
|
||||||
break;
|
break;
|
||||||
case MIN_EXPR:
|
case MIN_EXPR:
|
||||||
if (TREE_CODE (type) == COMPLEX_TYPE)
|
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:
|
case BIT_IOR_EXPR:
|
||||||
r_name = "|";
|
r_name = "|";
|
||||||
break;
|
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:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6032,6 +6032,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
|
||||||
case PLUS_EXPR:
|
case PLUS_EXPR:
|
||||||
case MULT_EXPR:
|
case MULT_EXPR:
|
||||||
case MINUS_EXPR:
|
case MINUS_EXPR:
|
||||||
|
case TRUTH_ANDIF_EXPR:
|
||||||
|
case TRUTH_ORIF_EXPR:
|
||||||
predefined = true;
|
predefined = true;
|
||||||
break;
|
break;
|
||||||
case MIN_EXPR:
|
case MIN_EXPR:
|
||||||
|
@ -6047,12 +6049,6 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
|
||||||
break;
|
break;
|
||||||
predefined = true;
|
predefined = true;
|
||||||
break;
|
break;
|
||||||
case TRUTH_ANDIF_EXPR:
|
|
||||||
case TRUTH_ORIF_EXPR:
|
|
||||||
if (FLOAT_TYPE_P (type))
|
|
||||||
break;
|
|
||||||
predefined = true;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6389,6 +6389,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||||
if (code == MINUS_EXPR)
|
if (code == MINUS_EXPR)
|
||||||
code = PLUS_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;
|
tree new_vard = new_var;
|
||||||
if (is_simd && omp_is_reference (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);
|
x = build2 (code, TREE_TYPE (ivar), ivar, x);
|
||||||
gimplify_assign (ivar, x, &llist[2]);
|
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);
|
ref = build_outer_var_ref (var, ctx);
|
||||||
gimplify_assign (ref, x, &llist[1]);
|
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)
|
if (is_simd)
|
||||||
{
|
{
|
||||||
tree ref = build_outer_var_ref (var, ctx);
|
tree ref = build_outer_var_ref (var, ctx);
|
||||||
|
tree new_var2 = new_var;
|
||||||
x = build2 (code, TREE_TYPE (ref), ref, 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);
|
ref = build_outer_var_ref (var, ctx);
|
||||||
gimplify_assign (ref, x, dlist);
|
gimplify_assign (ref, x, dlist);
|
||||||
}
|
}
|
||||||
|
@ -7397,13 +7429,32 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
|
||||||
if (code == MINUS_EXPR)
|
if (code == MINUS_EXPR)
|
||||||
code = PLUS_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)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
tree addr = build_fold_addr_expr_loc (clause_loc, ref);
|
tree addr = build_fold_addr_expr_loc (clause_loc, ref);
|
||||||
|
|
||||||
addr = save_expr (addr);
|
addr = save_expr (addr);
|
||||||
ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), 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);
|
x = build2 (OMP_ATOMIC, void_type_node, addr, x);
|
||||||
OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
|
OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
|
||||||
gimplify_and_add (x, stmt_seqp);
|
gimplify_and_add (x, stmt_seqp);
|
||||||
|
@ -7508,7 +7559,19 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
|
||||||
}
|
}
|
||||||
else
|
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);
|
out = unshare_expr (out);
|
||||||
gimplify_assign (out, x, &sub_seq);
|
gimplify_assign (out, x, &sub_seq);
|
||||||
}
|
}
|
||||||
|
@ -7542,7 +7605,19 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
|
||||||
}
|
}
|
||||||
else
|
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);
|
ref = build_outer_var_ref (var, ctx);
|
||||||
gimplify_assign (ref, x, &sub_seq);
|
gimplify_assign (ref, x, &sub_seq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 reduction (&:d) /* { dg-error "has invalid type for" } */
|
||||||
;
|
;
|
||||||
#pragma omp p copyin (d) /* { dg-error "must be 'threadprivate'" } */
|
#pragma omp p copyin (d) /* { dg-error "must be 'threadprivate'" } */
|
||||||
;
|
;
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* C / C++'s logical AND and OR operators take any scalar argument
|
||||||
|
which compares (un)equal to 0 - the result 1 or 0 and of type int.
|
||||||
|
|
||||||
|
In this testcase, the int result is again converted to a floating-poing
|
||||||
|
or complex type.
|
||||||
|
|
||||||
|
While having a floating-point/complex array element with || and && can make
|
||||||
|
sense, having a non-integer/non-bool reduction variable is odd but valid.
|
||||||
|
|
||||||
|
Test: FP reduction variable + FP array. */
|
||||||
|
|
||||||
|
#define N 1024
|
||||||
|
_Complex float rcf[N];
|
||||||
|
_Complex double rcd[N];
|
||||||
|
float rf[N];
|
||||||
|
double rd[N];
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or ()
|
||||||
|
{
|
||||||
|
float orf = 0;
|
||||||
|
double ord = 0;
|
||||||
|
_Complex float orfc = 0;
|
||||||
|
_Complex double ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or_teams ()
|
||||||
|
{
|
||||||
|
float orf = 0;
|
||||||
|
double ord = 0;
|
||||||
|
_Complex float orfc = 0;
|
||||||
|
_Complex double ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and ()
|
||||||
|
{
|
||||||
|
float andf = 1;
|
||||||
|
double andd = 1;
|
||||||
|
_Complex float andfc = 1;
|
||||||
|
_Complex double anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and_teams ()
|
||||||
|
{
|
||||||
|
float andf = 1;
|
||||||
|
double andd = 1;
|
||||||
|
_Complex float andfc = 1;
|
||||||
|
_Complex double anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 0;
|
||||||
|
rd[i] = 0;
|
||||||
|
rcf[i] = 0;
|
||||||
|
rcd[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 1.0;
|
||||||
|
rd[15] = 1.0;
|
||||||
|
rcf[10] = 1.0;
|
||||||
|
rcd[15] = 1.0i;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 1;
|
||||||
|
rd[i] = 1;
|
||||||
|
rcf[i] = 1;
|
||||||
|
rcd[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 0.0;
|
||||||
|
rd[15] = 0.0;
|
||||||
|
rcf[10] = 0.0;
|
||||||
|
rcd[15] = 0.0;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* C / C++'s logical AND and OR operators take any scalar argument
|
||||||
|
which compares (un)equal to 0 - the result 1 or 0 and of type int.
|
||||||
|
|
||||||
|
In this testcase, the int result is again converted to a floating-poing
|
||||||
|
or complex type.
|
||||||
|
|
||||||
|
While having a floating-point/complex array element with || and && can make
|
||||||
|
sense, having a non-integer/non-bool reduction variable is odd but valid.
|
||||||
|
|
||||||
|
Test: FP reduction variable + integer array. */
|
||||||
|
|
||||||
|
#define N 1024
|
||||||
|
char rcf[N];
|
||||||
|
short rcd[N];
|
||||||
|
int rf[N];
|
||||||
|
long rd[N];
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or ()
|
||||||
|
{
|
||||||
|
float orf = 0;
|
||||||
|
double ord = 0;
|
||||||
|
_Complex float orfc = 0;
|
||||||
|
_Complex double ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or_teams ()
|
||||||
|
{
|
||||||
|
float orf = 0;
|
||||||
|
double ord = 0;
|
||||||
|
_Complex float orfc = 0;
|
||||||
|
_Complex double ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and ()
|
||||||
|
{
|
||||||
|
float andf = 1;
|
||||||
|
double andd = 1;
|
||||||
|
_Complex float andfc = 1;
|
||||||
|
_Complex double anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and_teams ()
|
||||||
|
{
|
||||||
|
float andf = 1;
|
||||||
|
double andd = 1;
|
||||||
|
_Complex float andfc = 1;
|
||||||
|
_Complex double anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 0;
|
||||||
|
rd[i] = 0;
|
||||||
|
rcf[i] = 0;
|
||||||
|
rcd[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 1;
|
||||||
|
rd[15] = 1;
|
||||||
|
rcf[10] = 1;
|
||||||
|
rcd[15] = 1;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 1;
|
||||||
|
rd[i] = 1;
|
||||||
|
rcf[i] = 1;
|
||||||
|
rcd[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 0;
|
||||||
|
rd[15] = 0;
|
||||||
|
rcf[10] = 0;
|
||||||
|
rcd[15] = 0;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* C / C++'s logical AND and OR operators take any scalar argument
|
||||||
|
which compares (un)equal to 0 - the result 1 or 0 and of type int.
|
||||||
|
|
||||||
|
In this testcase, the int result is again converted to a floating-poing
|
||||||
|
or complex type.
|
||||||
|
|
||||||
|
While having a floating-point/complex array element with || and && can make
|
||||||
|
sense, having a non-integer/non-bool reduction variable is odd but valid.
|
||||||
|
|
||||||
|
Test: integer reduction variable + FP array. */
|
||||||
|
|
||||||
|
#define N 1024
|
||||||
|
_Complex float rcf[N];
|
||||||
|
_Complex double rcd[N];
|
||||||
|
float rf[N];
|
||||||
|
double rd[N];
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or ()
|
||||||
|
{
|
||||||
|
char orf = 0;
|
||||||
|
short ord = 0;
|
||||||
|
int orfc = 0;
|
||||||
|
long ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or_teams ()
|
||||||
|
{
|
||||||
|
char orf = 0;
|
||||||
|
short ord = 0;
|
||||||
|
int orfc = 0;
|
||||||
|
long ordc = 0;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orf = orf || rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ord)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ord = ord || rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orfc = orfc || rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ordc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ordc = ordc || rcd[i];
|
||||||
|
|
||||||
|
return orf + ord + __real__ orfc + __real__ ordc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and ()
|
||||||
|
{
|
||||||
|
unsigned char andf = 1;
|
||||||
|
unsigned short andd = 1;
|
||||||
|
unsigned int andfc = 1;
|
||||||
|
unsigned long anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and_teams ()
|
||||||
|
{
|
||||||
|
unsigned char andf = 1;
|
||||||
|
unsigned short andd = 1;
|
||||||
|
unsigned int andfc = 1;
|
||||||
|
unsigned long anddc = 1;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andf)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andf = andf && rf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: andd)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andd = andd && rcd[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andfc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andfc = andfc && rcf[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: anddc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
anddc = anddc && rcd[i];
|
||||||
|
|
||||||
|
return andf + andd + __real__ andfc + __real__ anddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 0;
|
||||||
|
rd[i] = 0;
|
||||||
|
rcf[i] = 0;
|
||||||
|
rcd[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 1.0;
|
||||||
|
rd[15] = 1.0;
|
||||||
|
rcf[10] = 1.0;
|
||||||
|
rcd[15] = 1.0i;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rf[i] = 1;
|
||||||
|
rd[i] = 1;
|
||||||
|
rcf[i] = 1;
|
||||||
|
rcd[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rf[10] = 0.0;
|
||||||
|
rd[15] = 0.0;
|
||||||
|
rcf[10] = 0.0;
|
||||||
|
rcd[15] = 0.0;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
/* C / C++'s logical AND and OR operators take any scalar argument
|
||||||
|
which compares (un)equal to 0 - the result 1 or 0 and of type int.
|
||||||
|
|
||||||
|
In this testcase, the int result is again converted to an integer complex
|
||||||
|
type.
|
||||||
|
|
||||||
|
While having a floating-point/complex array element with || and && can make
|
||||||
|
sense, having a complex reduction variable is odd but valid.
|
||||||
|
|
||||||
|
Test: int complex reduction variable + int complex array. */
|
||||||
|
|
||||||
|
#define N 1024
|
||||||
|
_Complex char rcc[N];
|
||||||
|
_Complex short rcs[N];
|
||||||
|
_Complex int rci[N];
|
||||||
|
_Complex long long rcl[N];
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or ()
|
||||||
|
{
|
||||||
|
_Complex char orc = 0;
|
||||||
|
_Complex short ors = 0;
|
||||||
|
_Complex int ori = 0;
|
||||||
|
_Complex long orl = 0;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(||: orc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orc = orc || rcl[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(||: ors)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ors = ors || rci[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(||: ori)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ori = ori || rcs[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(||: orl)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orl = orl || rcc[i];
|
||||||
|
|
||||||
|
return __real__ (orc + ors + ori + orl) + __imag__ (orc + ors + ori + orl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_or_teams ()
|
||||||
|
{
|
||||||
|
_Complex char orc = 0;
|
||||||
|
_Complex short ors = 0;
|
||||||
|
_Complex int ori = 0;
|
||||||
|
_Complex long orl = 0;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: orc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orc = orc || rcc[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: ors)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ors = ors || rcs[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(||: ori)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ori = ori || rci[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(||: orl)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
orl = orl || rcl[i];
|
||||||
|
|
||||||
|
return __real__ (orc + ors + ori + orl) + __imag__ (orc + ors + ori + orl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and ()
|
||||||
|
{
|
||||||
|
_Complex char andc = 1;
|
||||||
|
_Complex short ands = 1;
|
||||||
|
_Complex int andi = 1;
|
||||||
|
_Complex long andl = 1;
|
||||||
|
|
||||||
|
#pragma omp parallel reduction(&&: andc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andc = andc && rcc[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(&&: ands)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ands = ands && rcs[i];
|
||||||
|
|
||||||
|
#pragma omp parallel for simd reduction(&&: andi)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andi = andi && rci[i];
|
||||||
|
|
||||||
|
#pragma omp parallel loop reduction(&&: andl)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andl = andl && rcl[i];
|
||||||
|
|
||||||
|
return __real__ (andc + ands + andi + andl)
|
||||||
|
+ __imag__ (andc + ands + andi + andl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
reduction_and_teams ()
|
||||||
|
{
|
||||||
|
_Complex char andc = 1;
|
||||||
|
_Complex short ands = 1;
|
||||||
|
_Complex int andi = 1;
|
||||||
|
_Complex long andl = 1;
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andc)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andc = andc && rcl[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: ands)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
ands = ands && rci[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for reduction(&&: andi)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andi = andi && rcs[i];
|
||||||
|
|
||||||
|
#pragma omp teams distribute parallel for simd reduction(&&: andl)
|
||||||
|
for (int i=0; i < N; ++i)
|
||||||
|
andl = andl && rcc[i];
|
||||||
|
|
||||||
|
return __real__ (andc + ands + andi + andl)
|
||||||
|
+ __imag__ (andc + ands + andi + andl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rcc[i] = 0;
|
||||||
|
rcs[i] = 0;
|
||||||
|
rci[i] = 0;
|
||||||
|
rcl[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rcc[10] = 1.0;
|
||||||
|
rcs[15] = 1.0i;
|
||||||
|
rci[10] = 1.0;
|
||||||
|
rcl[15] = 1.0i;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
rcc[i] = 1;
|
||||||
|
rcs[i] = 1i;
|
||||||
|
rci[i] = 1;
|
||||||
|
rcl[i] = 1 + 1i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
rcc[10] = 0.0;
|
||||||
|
rcs[15] = 0.0;
|
||||||
|
rci[10] = 0.0;
|
||||||
|
rcl[15] = 0.0;
|
||||||
|
|
||||||
|
if (reduction_or () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_or_teams () != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (reduction_and_teams () != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue