diff --git a/Tests/acc_if_condition.F90 b/Tests/acc_if_condition.F90 new file mode 100644 index 0000000..f7b8199 --- /dev/null +++ b/Tests/acc_if_condition.F90 @@ -0,0 +1,282 @@ +! acc_if_condition.F90 +! +! Feature under test (OpenACC 3.4, Section 1.6, Feb 2026): +! - Clarified definition of "condition" when used as an argument to the if clause. +! - In Fortran, the if clause argument must be a LOGICAL expression. +! - The if clause must correctly gate execution of data and compute directives. +! +! Notes: +! - T1–T4 verify runtime gating behavior for enter data / exit data. +! - T5–T6 verify valid Fortran LOGICAL variable and expression forms. + +! Fortran conditions must be LOGICAL. + +#ifndef T1 +!T1:syntax,if-clause,runtime,enter-data,V:3.4- + LOGICAL FUNCTION test1() + USE OPENACC + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a + LOGICAL :: present + + errors = 0 + DO i=1, LOOPCOUNT + a(i) = DBLE(i) + END DO + + !$acc enter data copyin(a(1:LOOPCOUNT)) if(.FALSE.) + present = acc_is_present(a) + IF (present) THEN + errors = errors + 1 + END IF + + IF (present) THEN + !$acc exit data delete(a(1:LOOPCOUNT)) if(.TRUE.) + END IF + test1 = (errors .NE. 0) + END FUNCTION +#endif + +#ifndef T2 +!T2:syntax,if-clause,runtime,enter-data,V:3.4- + LOGICAL FUNCTION test2() + USE OPENACC + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a + LOGICAL :: present + + errors = 0 + DO i=1, LOOPCOUNT + a(i) = DBLE(i) + END DO + + !$acc enter data copyin(a(1:LOOPCOUNT)) if(.TRUE.) + present = acc_is_present(a) + IF (.NOT. present) THEN + errors = errors + 1 + END IF + + !$acc exit data delete(a(1:LOOPCOUNT)) if(.TRUE.) + test2 = (errors .NE. 0) + END FUNCTION +#endif + +#ifndef T3 +!T3:syntax,if-clause,runtime,exit-data,V:3.4- + LOGICAL FUNCTION test3() + USE OPENACC + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a + LOGICAL :: present + + errors = 0 + DO i=1, LOOPCOUNT + a(i) = DBLE(i) + END DO + + !$acc enter data copyin(a(1:LOOPCOUNT)) if(.TRUE.) + present = acc_is_present(a) + IF (.NOT. present) THEN + errors = errors + 1 + END IF + + !$acc exit data delete(a(1:LOOPCOUNT)) if(.FALSE.) + present = acc_is_present(a) + IF (.NOT. present) THEN + errors = errors + 1 + END IF + + !$acc exit data delete(a(1:LOOPCOUNT)) if(.TRUE.) + test3 = (errors .NE. 0) + END FUNCTION +#endif + +#ifndef T4 +!T4:syntax,if-clause,runtime,exit-data,V:3.4- + LOGICAL FUNCTION test4() + USE OPENACC + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a + LOGICAL :: present + + errors = 0 + DO i=1, LOOPCOUNT + a(i) = DBLE(i) + END DO + + !$acc enter data copyin(a(1:LOOPCOUNT)) if(.TRUE.) + present = acc_is_present(a) + IF (.NOT. present) THEN + errors = errors + 1 + END IF + + !$acc exit data delete(a(1:LOOPCOUNT)) if(.TRUE.) + present = acc_is_present(a) + IF (present) THEN + errors = errors + 1 + END IF + + test4 = (errors .NE. 0) + END FUNCTION +#endif + +#ifndef T5 +!T5:syntax,if-clause,runtime,compute,V:3.4- +! logical variable condition + LOGICAL FUNCTION test5() + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a, c + LOGICAL :: cond + + errors = 0 + cond = .TRUE. + + CALL RANDOM_NUMBER(a) + c = 0.0D0 + + !$acc data copyin(a(1:LOOPCOUNT)) copy(c(1:LOOPCOUNT)) + !$acc parallel loop present(a(1:LOOPCOUNT), c(1:LOOPCOUNT)) if(cond) + DO i=1, LOOPCOUNT + c(i) = 2.0D0 * a(i) + END DO + !$acc end parallel loop + !$acc end data + + DO i=1, LOOPCOUNT + IF (ABS(c(i) - 2.0D0*a(i)) .GT. PRECISION) THEN + errors = errors + 1 + END IF + END DO + + test5 = (errors .NE. 0) + END FUNCTION +#endif + +#ifndef T6 +!T6:syntax,if-clause,runtime,compute,V:3.4- +! logical expression condition + LOGICAL FUNCTION test6() + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: i, errors + REAL(8), DIMENSION(LOOPCOUNT) :: a, c + LOGICAL :: cond + + errors = 0 + cond = .TRUE. + + CALL RANDOM_NUMBER(a) + c = 0.0D0 + + !$acc data copyin(a(1:LOOPCOUNT)) copy(c(1:LOOPCOUNT)) + !$acc parallel loop present(a(1:LOOPCOUNT), c(1:LOOPCOUNT)) & + !$acc& if( (LOOPCOUNT .GT. 0) .AND. cond ) + DO i=1, LOOPCOUNT + c(i) = a(i) + 1.0D0 + END DO + !$acc end parallel loop + !$acc end data + + DO i=1, LOOPCOUNT + IF (ABS(c(i) - (a(i)+1.0D0)) .GT. PRECISION) THEN + errors = errors + 1 + END IF + END DO + + test6 = (errors .NE. 0) + END FUNCTION +#endif + + PROGRAM main + IMPLICIT NONE + INCLUDE "acc_testsuite.Fh" + INTEGER :: failcode, testrun + LOGICAL :: failed +#ifndef T1 + LOGICAL :: test1 +#endif +#ifndef T2 + LOGICAL :: test2 +#endif +#ifndef T3 + LOGICAL :: test3 +#endif +#ifndef T4 + LOGICAL :: test4 +#endif +#ifndef T5 + LOGICAL :: test5 +#endif +#ifndef T6 + LOGICAL :: test6 +#endif + + failcode = 0 + +#ifndef T1 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test1() + END DO + IF (failed) THEN + failcode = failcode + 2**0 + END IF +#endif +#ifndef T2 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test2() + END DO + IF (failed) THEN + failcode = failcode + 2**1 + END IF +#endif +#ifndef T3 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test3() + END DO + IF (failed) THEN + failcode = failcode + 2**2 + END IF +#endif +#ifndef T4 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test4() + END DO + IF (failed) THEN + failcode = failcode + 2**3 + END IF +#endif +#ifndef T5 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test5() + END DO + IF (failed) THEN + failcode = failcode + 2**4 + END IF +#endif +#ifndef T6 + failed = .FALSE. + DO testrun=1, NUM_TEST_CALLS + failed = failed .OR. test6() + END DO + IF (failed) THEN + failcode = failcode + 2**5 + END IF +#endif + + CALL EXIT(failcode) + END PROGRAM diff --git a/Tests/acc_if_condition.c b/Tests/acc_if_condition.c new file mode 100644 index 0000000..09dd178 --- /dev/null +++ b/Tests/acc_if_condition.c @@ -0,0 +1,314 @@ +// acc_if_condition.c +// +// Feature under test (OpenACC 3.4, Section 1.6, Feb 2026): +// - Clarified definition of "condition" when used as an argument to the if clause. +// - The if(condition) clause must accept any valid C scalar condition expression. +// - The if clause must correctly gate execution of data and compute directives. +// +// Notes: +// - T1–T4 verify runtime gating behavior for enter data / exit data. +// - T5–T7 verify valid C condition forms (integer, floating-point, pointer). + + +#include "acc_testsuite.h" +#include +#include +#include +#include + +#ifndef T1 +int test1(void){ + int err = 0; + real_t *a = (real_t*)malloc(n * sizeof(real_t)); + + if (!a){ + return 1; + } + + for (int i = 0; i < n; ++i){ + a[i] = (real_t)i; + } + + #pragma acc enter data copyin(a[0:n]) if(0) + + if (acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + #pragma acc exit data delete(a[0:n]) if(1) + free(a); + return err; +} +#endif + +#ifndef T2 +int test2(void){ + int err = 0; + real_t *a = (real_t*)malloc(n * sizeof(real_t)); + + if (!a){ + return 1; + } + + for (int i = 0; i < n; ++i){ + a[i] = (real_t)i; + } + + #pragma acc enter data copyin(a[0:n]) if(1) + + if (!acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + #pragma acc exit data delete(a[0:n]) if(1) + free(a); + return err; +} +#endif + +#ifndef T3 +int test3(void){ + int err = 0; + real_t *a = (real_t*)malloc(n * sizeof(real_t)); + + if (!a){ + return 1; + } + + for (int i = 0; i < n; ++i){ + a[i] = (real_t)i; + } + + #pragma acc enter data copyin(a[0:n]) if(1) + if (!acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + #pragma acc exit data delete(a[0:n]) if(0) + if (!acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + #pragma acc exit data delete(a[0:n]) if(1) + free(a); + return err; +} +#endif + +#ifndef T4 +int test4(void){ + int err = 0; + real_t *a = (real_t*)malloc(n * sizeof(real_t)); + + if (!a){ + return 1; + } + + for (int i = 0; i < n; ++i){ + a[i] = (real_t)i; + } + + #pragma acc enter data copyin(a[0:n]) if(1) + if (!acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + #pragma acc exit data delete(a[0:n]) if(1) + if (acc_is_present(a, (size_t)n * sizeof(real_t))){ + err++; + } + + free(a); + return err; +} +#endif + + +#ifndef T5 +int test5(void){ + int err = 0; + srand(SEED); + real_t *a = (real_t*)malloc(n*sizeof(real_t)); + real_t *b = (real_t*)malloc(n*sizeof(real_t)); + real_t *c = (real_t*)malloc(n*sizeof(real_t)); + + if (!a || !b || !c){ + free(a); + free(b); + free(c); + return 1; + } + + for (int i=0;i 0); + + #pragma acc data copyin(a[0:n],b[0:n]) copyout(c[0:n]) + { + #pragma acc parallel loop present(a[0:n],b[0:n],c[0:n]) if(cond_int) + for (int i=0;iPRECISION){ + err++; + } + } + free(a); + free(b); + free(c); + return err; +} +#endif + +#ifndef T6 +int test6(void){ + int err = 0; + srand(SEED); + real_t *a = (real_t*)malloc(n*sizeof(real_t)); + real_t *c = (real_t*)malloc(n*sizeof(real_t)); + if (!a || !c){ + free(a); + free(c); + return 1; + } + + for (int i=0;iPRECISION){ + err++; + } + } + free(a); + free(c); + return err; +} +#endif + +#ifndef T7 +int test7(void){ + int err = 0; + srand(SEED); + real_t *a = (real_t*)malloc(n*sizeof(real_t)); + real_t *c = (real_t*)malloc(n*sizeof(real_t)); + if (!a || !c){ + free(a); + free(c); + return 1; + } + + for (int i=0;iPRECISION){ + err++; + } + } + free(a); + free(c); + return err; +} +#endif + +int main(void){ + int failcode = 0, failed; + +#ifndef T1 + failed=0; + for(int i=0;i +#include +#include +#include + +struct BoolLike { + int v; + explicit operator bool() const { return v != 0; } +}; + +#ifndef T1 +int test1(){ + int err=0; + real_t* a=(real_t*)std::malloc(n*sizeof(real_t)); + + if(!a){ + return 1; + } + + for(int i=0;i 0); + + #pragma acc data copyin(a[0:n],b[0:n]) copyout(c[0:n]) + { + #pragma acc parallel loop present(a[0:n],b[0:n],c[0:n]) if(cond_int) + for(int i=0;iPRECISION){ + err++; + } + } + + std::free(a); + std::free(b); + std::free(c); + return err; +} +#endif + +#ifndef T6 +int test6(){ + int err=0; + std::srand(SEED); + real_t* a=(real_t*)std::malloc(n*sizeof(real_t)); + real_t* c=(real_t*)std::malloc(n*sizeof(real_t)); + if(!a||!c){ + std::free(a); + std::free(c); + return 1; + } + + for(int i=0;iPRECISION){ + err++; + } + } + + std::free(a); + std::free(c); + return err; +} +#endif + +int main(){ + int failcode=0, failed; +#ifndef T1 + failed=0; + for(int i=0;i