--- /dev/null
+/* Check that the nteams ICV is honored. */
+/* PR libgomp/109875 */
+
+/* This base version of testcases is supposed to be run with all
+ OMP_NUM_TEAMS* env vars being unset.
+
+ The variants teams-nteams-icv-{2,3,4}.c test it by setting the
+ various OMP_NUM_TEAMS* env vars and #define MY_... for checking.
+
+ Currently, only <num> 0,1,2 is supported for the envar via #define
+ and with remote execution, dg-set-target-env-var does not work with
+ DejaGNU, hence, gcc/testsuite/lib/gcc-dg.exp marks those tests as
+ UNSUPPORTED. */
+
+#define MY_MAX_DEVICES 3
+
+/* OpenMP currently has:
+ - nteams-var ICV is initialized to 0; one ICV per device
+ - OMP_NUM_TEAMS(_DEV(_<dev-num>)) overrides it
+ OMP_NUM_TEAMS_ALL overrides it
+ - Number of teams is:
+ -> the value specific by num_teams([lower:]upper)
+ with lower := upper if unspecified
+ -> Otherwise, if nteams-var ICV > 0, #teams <= nteams-var ICV
+ -> Otherwise, if nteams-var ICV <= 0, #teams > 1
+ GCC uses 3 as default on the host and 1 for host fallback.
+ For offloading, it is device specific >> 1. */
+
+#include <omp.h>
+
+int
+main ()
+{
+ int num_teams_env = -1, num_teams_env_dev = -1;
+ int num_teams_env_devs[MY_MAX_DEVICES];
+
+#ifdef MY_OMP_NUM_TEAMS_ALL
+ num_teams_env = num_teams_env_dev = MY_OMP_NUM_TEAMS_ALL;
+#endif
+
+#ifdef MY_OMP_NUM_TEAMS
+ num_teams_env = MY_OMP_NUM_TEAMS;
+#endif
+
+#ifdef MY_OMP_NUM_TEAMS_DEV
+ num_teams_env_dev = MY_OMP_NUM_TEAMS_DEV;
+#endif
+
+#if MY_MAX_DEVICES != 3
+ #error "Currently strictly assuming MY_MAX_DEVICES = 3"
+#endif
+
+#if defined(MY_OMP_NUM_TEAMS_DEV_4) || defined(MY_OMP_NUM_TEAMS_DEV_5)
+ #error "Currently strictly assuming MY_MAX_DEVICES = 3"
+#endif
+
+#ifdef MY_OMP_NUM_TEAMS_DEV_0
+ num_teams_env_devs[0] = MY_OMP_NUM_TEAMS_DEV_0;
+#else
+ num_teams_env_devs[0] = num_teams_env_dev;
+#endif
+
+#ifdef MY_OMP_NUM_TEAMS_DEV_1
+ num_teams_env_devs[1] = MY_OMP_NUM_TEAMS_DEV_1;
+#else
+ num_teams_env_devs[1] = num_teams_env_dev;
+#endif
+
+#ifdef MY_OMP_NUM_TEAMS_DEV_2
+ num_teams_env_devs[2] = MY_OMP_NUM_TEAMS_DEV_2;
+#else
+ num_teams_env_devs[2] = num_teams_env_dev;
+#endif
+
+ /* Check that the number of teams (initial device and in target) is
+ >= 1 and, if omp_get_max_teams() > 0, it does not
+ exceed omp_get_max_teams (). */
+
+ int nteams, num_teams;
+
+ /* Assume that omp_get_max_teams (); returns the ICV, i.e. 0 as default init
+ and not the number of teams that would be run; hence: '>='. */
+ nteams = omp_get_max_teams ();
+ if (nteams < 0 || (num_teams_env >= 0 && nteams != num_teams_env))
+ __builtin_abort ();
+ num_teams = -1;
+
+ #pragma omp teams
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+ if (num_teams < 1 || (nteams > 0 && num_teams > nteams))
+ __builtin_abort ();
+
+ /* GCC hard codes 3 teams - check for it. */
+ if (nteams <= 0 && num_teams != 3)
+ __builtin_abort ();
+
+ /* For each device, including host fallback. */
+ for (int dev = 0; dev <= omp_get_num_devices (); dev++)
+ {
+ int num_teams_icv = num_teams_env_dev;
+ if (dev == omp_get_num_devices ())
+ num_teams_icv = num_teams_env;
+ else if (dev < MY_MAX_DEVICES)
+ num_teams_icv = num_teams_env_devs[dev];
+
+ nteams = -1;
+ #pragma omp target device(dev) map(from: nteams)
+ nteams = omp_get_max_teams ();
+ if (nteams < 0 || (num_teams_icv >= 0 && nteams != num_teams_icv))
+ __builtin_abort ();
+
+ num_teams = -1;
+ #pragma omp target teams device(dev) map(from: num_teams)
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+
+ if (num_teams < 1 || (nteams > 0 && num_teams > nteams))
+ __builtin_abort ();
+
+ /* GCC hard codes 1 team for host fallback - check for it. */
+ if (dev == omp_get_num_devices () && num_teams != 1)
+ __builtin_abort ();
+ }
+
+ /* Now set the nteams-var ICV and check that omp_get_max_teams()
+ returns the set value and that the following holds:
+ num_teams >= 1 and num_teams <= nteams-var ICV.
+
+ Additionally, implementation defined, assume:
+ - num_teams == (not '<=') nteams-var ICV, except:
+ - num_teams == 1 for host fallback. */
+
+ omp_set_num_teams (5);
+
+ nteams = omp_get_max_teams ();
+ if (nteams != 5)
+ __builtin_abort ();
+ num_teams = -1;
+
+ #pragma omp teams
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+ if (num_teams != 5)
+ __builtin_abort ();
+
+ /* For each device, including host fallback. */
+ for (int dev = 0; dev <= omp_get_num_devices (); dev++)
+ {
+ #pragma omp target device(dev) firstprivate(dev)
+ omp_set_num_teams (7 + dev);
+
+ #pragma omp target device(dev) map(from: nteams)
+ nteams = omp_get_max_teams ();
+ if (nteams != 7 + dev)
+ __builtin_abort ();
+
+ num_teams = -1;
+ #pragma omp target teams device(dev) map(from: num_teams)
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+
+ if (dev == omp_get_num_devices ())
+ {
+ if (num_teams != 1)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (num_teams != 7 + dev)
+ __builtin_abort ();
+ }
+ }
+
+ /* Now use the num_teams clause explicitly. */
+
+ num_teams = -1;
+ #pragma omp teams num_teams(6)
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+ if (num_teams != 6)
+ __builtin_abort ();
+
+ /* For each device, including host fallback. */
+ for (int dev = 0; dev <= omp_get_num_devices (); dev++)
+ {
+ num_teams = -1;
+ #pragma omp target teams device(dev) map(from: num_teams) num_teams(dev+3)
+ if (omp_get_team_num () == 0)
+ num_teams = omp_get_num_teams ();
+
+ /* This must match the set value, also with host fallback. */
+ if (num_teams != 3 + dev)
+ __builtin_abort ();
+ }
+
+ return 0;
+}