aboutsummaryrefslogtreecommitdiff
path: root/libgomp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2023-06-21 11:04:04 -0700
committerIan Lance Taylor <iant@golang.org>2023-06-21 11:04:04 -0700
commit97e31a0a2a2d2273687fcdb4e5416aab1a2186e1 (patch)
treed5c1cae4de436a0fe54a5f0a2a197d309f3d654c /libgomp
parent6612f4f8cb9b0d5af18ec69ad04e56debc3e6ced (diff)
parent577223aebc7acdd31e62b33c1682fe54a622ae27 (diff)
downloadgcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.zip
gcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.tar.gz
gcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.tar.bz2
Merge from trunk revision 577223aebc7acdd31e62b33c1682fe54a622ae27.
Diffstat (limited to 'libgomp')
-rw-r--r--libgomp/ChangeLog382
-rw-r--r--libgomp/Makefile.in3
-rw-r--r--libgomp/config/gcn/target.c4
-rw-r--r--libgomp/config/nvptx/target.c4
-rwxr-xr-xlibgomp/configure150
-rw-r--r--libgomp/configure.ac25
-rw-r--r--libgomp/env.c201
-rw-r--r--libgomp/icv-device.c4
-rw-r--r--libgomp/libgomp-plugin.c7
-rw-r--r--libgomp/libgomp-plugin.h6
-rw-r--r--libgomp/libgomp.h5
-rw-r--r--libgomp/libgomp.texi163
-rw-r--r--libgomp/plugin/plugin-gcn.c6
-rw-r--r--libgomp/plugin/plugin-nvptx.c77
-rw-r--r--libgomp/target.c204
-rw-r--r--libgomp/testsuite/Makefile.am79
-rw-r--r--libgomp/testsuite/Makefile.in80
-rw-r--r--libgomp/testsuite/config/default.exp2
-rwxr-xr-xlibgomp/testsuite/flock17
-rw-r--r--libgomp/testsuite/lib/libgomp.exp118
-rw-r--r--libgomp/testsuite/libgomp-site-extra.exp.in3
-rw-r--r--libgomp/testsuite/libgomp.c++/c++.exp84
-rw-r--r--libgomp/testsuite/libgomp.c++/target-18.C21
-rw-r--r--libgomp/testsuite/libgomp.c++/target-19.C13
-rw-r--r--libgomp/testsuite/libgomp.c++/target-map-class-1.C98
-rw-r--r--libgomp/testsuite/libgomp.c++/target-map-class-2.C6
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-1.c74
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-2.c85
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/scan-1.c68
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-3.c105
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c159
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-present-1.c40
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-present-2.c30
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-present-3.c41
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-1.c198
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-2.c8
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-3.c8
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-4.c14
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-1.c15
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-2.c17
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-3.c27
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-4.c15
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-5.c15
-rw-r--r--libgomp/testsuite/libgomp.c/allocator-6.c15
-rw-r--r--libgomp/testsuite/libgomp.c/c.exp13
-rw-r--r--libgomp/testsuite/libgomp.c/scan-23.c121
-rw-r--r--libgomp/testsuite/libgomp.c/simd-math-1.c1
-rw-r--r--libgomp/testsuite/libgomp.c/target-19.c21
-rw-r--r--libgomp/testsuite/libgomp.c/target-48.c31
-rw-r--r--libgomp/testsuite/libgomp.c/target-49.c18
-rw-r--r--libgomp/testsuite/libgomp.c/target-50.c27
-rw-r--r--libgomp/testsuite/libgomp.c/target-50a.c43
-rw-r--r--libgomp/testsuite/libgomp.c/target-51.c23
-rw-r--r--libgomp/testsuite/libgomp.c/target-52.c25
-rw-r--r--libgomp/testsuite/libgomp.c/target-53.c22
-rw-r--r--libgomp/testsuite/libgomp.c/target-54.c20
-rw-r--r--libgomp/testsuite/libgomp.c/target-55.c20
-rw-r--r--libgomp/testsuite/libgomp.c/target-55a.c23
-rw-r--r--libgomp/testsuite/libgomp.fortran/allocate-4.f9012
-rw-r--r--libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f903
-rw-r--r--libgomp/testsuite/libgomp.fortran/fortran.exp102
-rw-r--r--libgomp/testsuite/libgomp.fortran/requires-unified-addr-1.f90111
-rw-r--r--libgomp/testsuite/libgomp.fortran/scan-2.f9059
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-enter-data-3.f902
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-enter-data-4.f90540
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-enter-data-5.f90540
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90392
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-enter-data-7.f9078
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-present-1.f9031
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-present-2.f9031
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-present-3.f9036
-rw-r--r--libgomp/testsuite/libgomp.graphite/graphite.exp12
-rw-r--r--libgomp/testsuite/libgomp.oacc-c++/c++.exp214
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/present-1.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-c/c.exp13
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f904
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/fortran.exp189
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/pr109622-2.f9035
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/pr109622-3.f9035
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/pr109622-4.f9047
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/pr109622.f9035
81 files changed, 4983 insertions, 644 deletions
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index c50e591..002d802 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,385 @@
+2023-06-19 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c/target-51.c: Fix DejaGnu directive syntax
+ error.
+
+2023-06-19 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.c/target-51.c: Accept more error msg variants
+ as expected dg-output.
+
+2023-06-19 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/110270
+ * target.c (gomp_map_vars_internal): Copy host value instead of NULL
+ for GOMP_MAP_ZERO_LEN_ARRAY_SECTION if not mapped.
+ * libgomp.texi (OpenMP 5.2 Impl.): Mark as 'Y'.
+ * testsuite/libgomp.c/target-19.c: Update expected value.
+ * testsuite/libgomp.c++/target-18.C: Likewise.
+ * testsuite/libgomp.c++/target-19.C: Likewise.
+ * testsuite/libgomp.c-c++-common/requires-unified-addr-2.c: New test.
+ * testsuite/libgomp.c-c++-common/target-implicit-map-3.c: New test.
+ * testsuite/libgomp.c-c++-common/target-implicit-map-4.c: New test.
+
+2023-06-16 Tobias Burnus <tobias@codesourcery.com>
+
+ * target.c (resolve_device): Call gomp_get_num_devices early to ensure
+ gomp_init_targets_once was called before using default-device-var.
+ * testsuite/libgomp.c/target-55.c: New test.
+ * testsuite/libgomp.c/target-55a.c: New test.
+
+2023-06-15 Tobias Burnus <tobias@codesourcery.com>
+
+ * env.c (gomp_def_allocator_envvar): New var.
+ (parse_allocator): Handle OpenMP 5.1 syntax.
+ (cleanup_env): New.
+ (omp_display_env): Output gomp_def_allocator_envvar
+ for an allocator with traits.
+ * libgomp.texi (OMP_ALLOCATOR, OMP_AFFINITY_FORMAT,
+ OMP_DISPLAY_AFFINITY): New.
+ * testsuite/libgomp.c/allocator-1.c: New test.
+ * testsuite/libgomp.c/allocator-2.c: New test.
+ * testsuite/libgomp.c/allocator-3.c: New test.
+ * testsuite/libgomp.c/allocator-4.c: New test.
+ * testsuite/libgomp.c/allocator-5.c: New test.
+ * testsuite/libgomp.c/allocator-6.c: New test.
+
+2023-06-14 Thomas Schwinge <thomas@codesourcery.com>
+
+ * target.c (resolve_device): Align a
+ 'OMP_TARGET_OFFLOAD=mandatory' diagnostic with others.
+ * testsuite/libgomp.c/target-51.c: Adjust.
+
+2023-06-14 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.fortran/fortran.exp (lang_link_flags): Don't
+ set.
+ * testsuite/libgomp.oacc-fortran/fortran.exp (lang_link_flags):
+ Likewise.
+ * testsuite/libgomp.c/simd-math-1.c: Remove
+ '-foffload-options=-lm'.
+ * testsuite/libgomp.fortran/fortran-torture_execute_math.f90:
+ Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90:
+ Likewise.
+
+2023-06-14 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.fortran/fortran-torture_execute_math.f90: New.
+ * testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90:
+ Likewise.
+
+2023-06-14 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c/target-51.c: Fix typo.
+
+2023-06-14 Tobias Burnus <tobias@codesourcery.com>
+
+ * env.c (gomp_default_icv_values): Init default_device_var to
+ an nonconforming value - INT_MIN.
+ (initialize_env): After env-var parsing, set default_device_var to
+ device 0 unless OMP_TARGET_OFFLOAD=mandatory.
+ (omp_display_env): If default_device_var is INT_MIN, call
+ gomp_init_targets_once.
+ * icv-device.c (omp_get_default_device): Likewise.
+ * libgomp.texi (OMP_DEFAULT_DEVICE): Update init description.
+ (OpenMP 5.2 Impl. Status): Mark OMP_TARGET_OFFLOAD=mandatory as 'Y'.
+ * target.c (resolve_device): Improve error message device-num < 0
+ with 'mandatory' and no no-host devices available.
+ (gomp_target_init): Set default-device-var if INT_MIN.
+ * testsuite/libgomp.c/target-48.c: New test.
+ * testsuite/libgomp.c/target-49.c: New test.
+ * testsuite/libgomp.c/target-50.c: New test.
+ * testsuite/libgomp.c/target-50a.c: New test.
+ * testsuite/libgomp.c/target-51.c: New test.
+ * testsuite/libgomp.c/target-52.c: New test.
+ * testsuite/libgomp.c/target-53.c: New test.
+ * testsuite/libgomp.c/target-54.c: New test.
+
+2023-06-13 Tobias Burnus <tobias@codesourcery.com>
+
+ PR libgomp/109837
+ * testsuite/libgomp.c-c++-common/requires-unified-addr-1.c: New test.
+ * testsuite/libgomp.fortran/requires-unified-addr-1.f90: New test.
+
+2023-06-12 Tobias Burnus <tobias@codesourcery.com>
+
+ * target.c (gomp_to_device_kind_p, gomp_map_vars_internal): Replace
+ GOMP_MAP_PRESENT_{FROM,TO,TOFROM,ACLLOC} by GOMP_MAP_FORCE_PRESENT.
+ (gomp_map_vars_internal, gomp_update): Likewise; unify and improve
+ error message.
+ * testsuite/libgomp.c-c++-common/target-present-2.c: Update for
+ changed error message.
+ * testsuite/libgomp.fortran/target-present-1.f90: Likewise.
+ * testsuite/libgomp.fortran/target-present-2.f90: Likewise.
+ * testsuite/libgomp.oacc-c-c++-common/present-1.c: Likewise.
+ * testsuite/libgomp.c-c++-common/target-present-1.c: Likewise and
+ extend testcase to check that data is copied when needed.
+ * testsuite/libgomp.c-c++-common/target-present-3.c: Likewise.
+ * testsuite/libgomp.fortran/target-present-3.f90: Likewise.
+
+2023-06-07 Thomas Schwinge <thomas@codesourcery.com>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.c-c++-common/target-present-1.c: Run code
+ also for non-offload_device targets; check that it runs
+ successfully for those and for all until a checkpoint for all
+ * testsuite/libgomp.c-c++-common/target-present-2.c: Likewise.
+ * testsuite/libgomp.c-c++-common/target-present-3.c: Likewise.
+ * testsuite/libgomp.fortran/target-present-1.f90: Likewise.
+ * testsuite/libgomp.fortran/target-present-3.f90: Likewise.
+ * testsuite/libgomp.fortran/target-present-2.f90: Likewise;
+ add missing vars to map clause.
+
+2023-06-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_num_devices): Regard
+ unified_address requirement as supported.
+ * libgomp.texi (OpenMP 5.0, AMD Radeon, nvptx): Remove
+ 'unified_address' from the not-supported requirements.
+
+2023-06-06 Kwok Cheung Yeung <kcy@codesourcery.com>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ * libgomp.texi (OpenMP 5.1 Impl. status): Set 'present' support for
+ defaultmap to 'Y', add 'Y' entry for 'present' on to/from/map clauses.
+ * target.c (gomp_to_device_kind_p): Add map kinds with 'present'
+ modifier.
+ (gomp_map_vars_existing): Use new GOMP_MAP_FORCE_P macro.
+ (gomp_map_vars_internal, gomp_update, gomp_target_rev):
+ Emit runtime error if memory region not present.
+ * testsuite/libgomp.c-c++-common/target-present-1.c: New test.
+ * testsuite/libgomp.c-c++-common/target-present-2.c: New test.
+ * testsuite/libgomp.c-c++-common/target-present-3.c: New test.
+ * testsuite/libgomp.fortran/target-present-1.f90: New test.
+ * testsuite/libgomp.fortran/target-present-2.f90: New test.
+ * testsuite/libgomp.fortran/target-present-3.f90: New test.
+
+2023-06-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/66005
+ * testsuite/lib/libgomp.exp: 'flock' through stdout.
+ * testsuite/flock: New.
+ * configure.ac (FLOCK): Point to that if no 'flock' available, but
+ 'perl' is.
+ * configure: Regenerate.
+
+2023-06-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ * configure.ac (PERL): Remove.
+ * configure: Regenerate.
+ * Makefile.in: Likewise.
+ * testsuite/Makefile.in: Likewise.
+
+2023-06-01 Tobias Burnus <tobias@codesourcery.com>
+
+ * libgomp.texi (OpenMP 5.2): Mark pure-directive handling as 'Y'.
+
+2023-05-26 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.fortran/allocate-4.f90: Update dg-error.
+
+2023-05-21 Tobias Burnus <tobias@codesourcery.com>
+
+ PR libgomp/109875
+ * config/gcn/target.c (GOMP_teams4): Honor nteams-var ICV.
+ * config/nvptx/target.c (GOMP_teams4): Likewise.
+ * testsuite/libgomp.c-c++-common/teams-nteams-icv-1.c: New test.
+ * testsuite/libgomp.c-c++-common/teams-nteams-icv-2.c: New test.
+ * testsuite/libgomp.c-c++-common/teams-nteams-icv-3.c: New test.
+ * testsuite/libgomp.c-c++-common/teams-nteams-icv-4.c: New test.
+
+2023-05-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/109904
+ * configure.ac (link_gomp): Include also $DL_LIBS.
+ * configure: Regenerated.
+
+2023-05-17 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.fortran/target-enter-data-3.f90: Uncomment
+ 'target exit data'.
+ * testsuite/libgomp.fortran/target-enter-data-4.f90: New test.
+ * testsuite/libgomp.fortran/target-enter-data-5.f90: New test.
+ * testsuite/libgomp.fortran/target-enter-data-6.f90: New test.
+ * testsuite/libgomp.fortran/target-enter-data-7.f90: New test.
+
+2023-05-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/66005
+ * configure.ac: Look for 'flock'.
+ * testsuite/Makefile.am (gcc_test_parallel_slots): Enable parallel testing.
+ * testsuite/config/default.exp: Don't 'load_lib "standard.exp"' here...
+ * testsuite/lib/libgomp.exp: ... but here, instead.
+ (libgomp_load): Override for parallel testing.
+ * testsuite/libgomp-site-extra.exp.in (FLOCK): Set.
+ * configure: Regenerate.
+ * Makefile.in: Regenerate.
+ * testsuite/Makefile.in: Regenerate.
+
+2023-05-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/66005
+ * testsuite/Makefile.am (PWD_COMMAND): New variable.
+ (%/site.exp): New target.
+ (check_p_numbers0, check_p_numbers1, check_p_numbers2)
+ (check_p_numbers3, check_p_numbers4, check_p_numbers5)
+ (check_p_numbers6, check_p_numbers, gcc_test_parallel_slots)
+ (check_p_subdirs)
+ (check_DEJAGNU_libgomp_targets): New variables.
+ ($(check_DEJAGNU_libgomp_targets)): New target.
+ ($(check_DEJAGNU_libgomp_targets)): New dependency.
+ (check-DEJAGNU $(check_DEJAGNU_libgomp_targets)): New targets.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/lib/libgomp.exp: For parallel testing,
+ 'load_file ../libgomp-test-support.exp'.
+
+2023-05-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/91884
+ * configure.ac: 'AC_SUBST(CXX)'.
+ * configure: Regenerate.
+ * Makefile.in: Likewise.
+ * testsuite/Makefile.in: Likewise.
+ * testsuite/libgomp-site-extra.exp.in (GXX_UNDER_TEST)
+ (GFORTRAN_UNDER_TEST): Set.
+ * testsuite/lib/libgomp.exp (libgomp_init): Adjust.
+ * testsuite/libgomp.c++/c++.exp: Use 'GXX_UNDER_TEST'.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.fortran/fortran.exp: Use
+ 'GFORTRAN_UNDER_TEST'.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
+2023-05-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/91884
+ * testsuite/lib/libgomp.exp (libgomp_target_compile): Don't
+ specify compiler.
+ * testsuite/libgomp.c++/c++.exp (ALWAYS_CFLAGS): Specify compiler.
+ * testsuite/libgomp.c/c.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.fortran/fortran.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.graphite/graphite.exp (ALWAYS_CFLAGS):
+ Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.oacc-c/c.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran.exp (ALWAYS_CFLAGS):
+ Likewise.
+
+2023-05-12 Tobias Burnus <tobias@codesourcery.com>
+
+ PR libstdc++/109816
+ * testsuite/libgomp.c++/target-map-class-1.C: New test.
+ * testsuite/libgomp.c++/target-map-class-2.C: New test.
+
+2023-05-12 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/lib/libgomp.exp (libgomp_target_compile): Generalize
+ 'lang_library_path' into a list of 'lang_library_paths'.
+ * testsuite/libgomp.c++/c++.exp: Adjust.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.fortran/fortran.exp: Adjust. Use that for
+ libquadmath, too.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
+2023-05-12 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/lib/libgomp.exp (libgomp_target_compile): Don't look
+ at 'lang_test_file_found'.
+ * testsuite/libgomp.c++/c++.exp: Don't set and use it, and instead
+ 'return' early if not able to test. Simplify 'ld_library_path' setup.
+ * testsuite/libgomp.fortran/fortran.exp: Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
+2023-05-12 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp: Resolve 'lang_test_file_found'
+ first.
+ * testsuite/libgomp.fortran/fortran.exp: Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
+2023-05-12 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp: Localize 'lang_[...]' etc.
+ * testsuite/libgomp.c/c.exp: Likewise.
+ * testsuite/libgomp.fortran/fortran.exp: Likewise.
+ * testsuite/libgomp.graphite/graphite.exp: Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.oacc-c/c.exp: Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+
+2023-05-09 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp: Don't set 'lang_test_file'.
+ * testsuite/libgomp.fortran/fortran.exp: Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+ * testsuite/libgomp.oacc-fortran/fortran.exp: Likewise.
+ * testsuite/libgomp.c/c.exp: Unset 'lang_test_file_found' instead of
+ 'lang_test_file'.
+ * testsuite/libgomp.oacc-c/c.exp: Likewise.
+ * testsuite/libgomp.graphite/graphite.exp: Likewise.
+ * testsuite/lib/libgomp.exp (libgomp_target_compile): Look for
+ 'lang_test_file_found' instead of 'lang_test_file'.
+
+2023-05-09 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/lib/libgomp.exp (libgomp_init): Only use 'blddir' if
+ set.
+ * testsuite/libgomp.c++/c++.exp: Likewise.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+
+2023-05-09 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp (blddir): Don't set.
+ * testsuite/libgomp.oacc-c++/c++.exp (blddir): Likewise.
+
+2023-05-08 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp: Use 'lang_include_flags' instead
+ of 'libstdcxx_includes'.
+ * testsuite/libgomp.oacc-c++/c++.exp: Likewise.
+
+2023-05-08 Thomas Schwinge <thomas@codesourcery.com>
+
+ * target.c (gomp_target_rev): Instead of 'dev_to_host_cpy',
+ 'host_to_dev_cpy', 'token', take a single 'goacc_asyncqueue'.
+ * libgomp.h (gomp_target_rev): Adjust.
+ * libgomp-plugin.c (GOMP_PLUGIN_target_rev): Adjust.
+ * libgomp-plugin.h (GOMP_PLUGIN_target_rev): Adjust.
+ * plugin/plugin-gcn.c (process_reverse_offload): Adjust.
+ * plugin/plugin-nvptx.c (rev_off_dev_to_host_cpy)
+ (rev_off_host_to_dev_cpy): Remove.
+ (GOMP_OFFLOAD_run): Adjust.
+
+2023-05-04 Julian Brown <julian@codesourcery.com>
+
+ PR fortran/109622
+ * testsuite/libgomp.fortran/pr109622.f90: Move test...
+ * testsuite/libgomp.oacc-fortran/pr109622.f90: ...to here. Ignore
+ vector length warning.
+ * testsuite/libgomp.fortran/pr109622-2.f90: Move test...
+ * testsuite/libgomp.oacc-fortran/pr109622-2.f90: ...to here. Add
+ missing copyin/copyout variable. Ignore vector length warnings.
+ * testsuite/libgomp.fortran/pr109622-3.f90: Move test...
+ * testsuite/libgomp.oacc-fortran/pr109622-3.f90: ...to here. Ignore
+ vector length warnings.
+ * testsuite/libgomp.oacc-fortran/pr109622-4.f90: New test.
+
+2023-04-28 Julian Brown <julian@codesourcery.com>
+
+ PR fortran/109622
+ * testsuite/libgomp.fortran/pr109622.f90: New test.
+ * testsuite/libgomp.fortran/pr109622-2.f90: New test.
+ * testsuite/libgomp.fortran/pr109622-3.f90: New test.
+
+2023-04-25 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.c-c++-common/scan-1.c: New test.
+ * testsuite/libgomp.c/scan-23.c: New test.
+ * testsuite/libgomp.fortran/scan-2.f90: New test.
+
2023-03-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* testsuite/libgomp.oacc-c-c++-common/routine-nohost-2.c: Add
diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in
index 2c81cca..3ef05e6 100644
--- a/libgomp/Makefile.in
+++ b/libgomp/Makefile.in
@@ -368,6 +368,7 @@ CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPU_COUNT = @CPU_COUNT@
+CXX = @CXX@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -382,6 +383,7 @@ EXEEXT = @EXEEXT@
FC = @FC@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
+FLOCK = @FLOCK@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -428,7 +430,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
RANLIB = @RANLIB@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
diff --git a/libgomp/config/gcn/target.c b/libgomp/config/gcn/target.c
index c6691fd..ea5eb1f 100644
--- a/libgomp/config/gcn/target.c
+++ b/libgomp/config/gcn/target.c
@@ -48,7 +48,9 @@ GOMP_teams4 (unsigned int num_teams_lower, unsigned int num_teams_upper,
multiple times at least for some workgroups. */
(void) num_teams_lower;
if (!num_teams_upper || num_teams_upper >= num_workgroups)
- num_teams_upper = num_workgroups;
+ num_teams_upper = ((GOMP_ADDITIONAL_ICVS.nteams > 0
+ && num_workgroups > GOMP_ADDITIONAL_ICVS.nteams)
+ ? GOMP_ADDITIONAL_ICVS.nteams : num_workgroups);
else if (workgroup_id >= num_teams_upper)
return false;
gomp_num_teams_var = num_teams_upper - 1;
diff --git a/libgomp/config/nvptx/target.c b/libgomp/config/nvptx/target.c
index f102d7d..125d92a 100644
--- a/libgomp/config/nvptx/target.c
+++ b/libgomp/config/nvptx/target.c
@@ -55,7 +55,9 @@ GOMP_teams4 (unsigned int num_teams_lower, unsigned int num_teams_upper,
= thread_limit > INT_MAX ? UINT_MAX : thread_limit;
}
if (!num_teams_upper)
- num_teams_upper = num_blocks;
+ num_teams_upper = ((GOMP_ADDITIONAL_ICVS.nteams > 0
+ && num_blocks > GOMP_ADDITIONAL_ICVS.nteams)
+ ? GOMP_ADDITIONAL_ICVS.nteams : num_blocks);
else if (num_blocks < num_teams_lower)
num_teams_upper = num_teams_lower;
else if (num_blocks < num_teams_upper)
diff --git a/libgomp/configure b/libgomp/configure
index fd0e337..e4e79c5 100755
--- a/libgomp/configure
+++ b/libgomp/configure
@@ -656,6 +656,7 @@ tmake_file
XLDFLAGS
XCFLAGS
config_path
+FLOCK
CPU_COUNT
LIBGOMP_BUILD_VERSIONED_SHLIB_SUN_FALSE
LIBGOMP_BUILD_VERSIONED_SHLIB_SUN_TRUE
@@ -678,6 +679,7 @@ libtool_VERSION
ac_ct_FC
FCFLAGS
FC
+CXX
MAINT
MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
@@ -703,7 +705,6 @@ SED
LIBTOOL
BUILD_INFO_FALSE
BUILD_INFO_TRUE
-PERL
RANLIB
AR
am__fastdepCC_FALSE
@@ -4774,47 +4775,6 @@ else
RANLIB="$ac_cv_prog_RANLIB"
fi
-# Extract the first word of "perl", so it can be a program name with args.
-set dummy perl; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PERL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $PERL in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="perl-not-found-in-path-error"
- ;;
-esac
-fi
-PERL=$ac_cv_path_PERL
-if test -n "$PERL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
-$as_echo "$PERL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
@@ -11418,7 +11378,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11421 "configure"
+#line 11381 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11524,7 +11484,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11527 "configure"
+#line 11487 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11810,11 +11770,22 @@ fi
+# We optionally test libgomp C++ support, and for that want to use the proper
+# C++ driver, 'g++' (or 'xg++' for build-tree testing). Given that build of
+# target libstdc++-v3 depends on target libgomp (see '../Makefile.def'), we
+# cannot make build of target libgomp depend on target libstdc++-v3: circular
+# dependency. We thus cannot instantiate 'AC_PROG_CXX' here: we'd get
+# '-funconfigured-libstdc++-v3' (see '../configure.ac'). Therefore, just
+# capture 'CXX', and we'll fix this up at 'make check' time (see
+# 'testsuite/lib/libgomp.exp:libgomp_init').
+
+
# Create a spec file, so that compile/link tests don't fail
test -f libgfortran.spec || touch libgfortran.spec
FCFLAGS="$FCFLAGS -L."
-# We need gfortran to compile parts of the library
+# We need 'gfortran' to compile parts of the library, and test libgomp Fortran
+# support.
# We can't use AC_PROG_FC because it expects a fully working gfortran.
#AC_PROG_FC(gfortran)
case `echo $GFORTRAN` in
@@ -16486,6 +16457,91 @@ $as_echo "unable to detect (assuming 1)" >&6; }
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for flock implementation" >&5
+$as_echo "$as_me: checking for flock implementation" >&6;}
+for ac_prog in flock
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_FLOCK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$FLOCK"; then
+ ac_cv_prog_FLOCK="$FLOCK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FLOCK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FLOCK=$ac_cv_prog_FLOCK
+if test -n "$FLOCK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLOCK" >&5
+$as_echo "$FLOCK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$FLOCK" && break
+done
+
+# Fallback if 'perl' is available.
+if test -z "$FLOCK"; then
+ # Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_FLOCK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$FLOCK"; then
+ ac_cv_prog_FLOCK="$FLOCK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FLOCK="$srcdir/testsuite/flock"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FLOCK=$ac_cv_prog_FLOCK
+if test -n "$FLOCK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLOCK" >&5
+$as_echo "$FLOCK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
# Get target configury.
. ${srcdir}/configure.tgt
CFLAGS="$save_CFLAGS $XCFLAGS"
@@ -16732,9 +16788,9 @@ fi
# which will force linkage against -lpthread (or equivalent for the system).
# That's not 100% ideal, but about the best we can do easily.
if test $enable_shared = yes; then
- link_gomp="-lgomp %{static: $LIBS}"
+ link_gomp="-lgomp %{static: $LIBS${DL_LIBS:+ $DL_LIBS}}"
else
- link_gomp="-lgomp $LIBS"
+ link_gomp="-lgomp $LIBS${DL_LIBS:+ $DL_LIBS}"
fi
diff --git a/libgomp/configure.ac b/libgomp/configure.ac
index a9b1f39..1aad83a 100644
--- a/libgomp/configure.ac
+++ b/libgomp/configure.ac
@@ -132,7 +132,6 @@ AS_IF([test "x$enable_werror" != "xno" && test "x$GCC" = "xyes"],
# Find other programs we need.
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, ranlib-not-found-in-path-error)
-AC_PATH_PROG(PERL, perl, perl-not-found-in-path-error)
AC_PROG_MAKE_SET
AC_PROG_INSTALL
@@ -152,11 +151,22 @@ AC_SUBST(enable_static)
AM_MAINTAINER_MODE
+# We optionally test libgomp C++ support, and for that want to use the proper
+# C++ driver, 'g++' (or 'xg++' for build-tree testing). Given that build of
+# target libstdc++-v3 depends on target libgomp (see '../Makefile.def'), we
+# cannot make build of target libgomp depend on target libstdc++-v3: circular
+# dependency. We thus cannot instantiate 'AC_PROG_CXX' here: we'd get
+# '-funconfigured-libstdc++-v3' (see '../configure.ac'). Therefore, just
+# capture 'CXX', and we'll fix this up at 'make check' time (see
+# 'testsuite/lib/libgomp.exp:libgomp_init').
+AC_SUBST(CXX)
+
# Create a spec file, so that compile/link tests don't fail
test -f libgfortran.spec || touch libgfortran.spec
FCFLAGS="$FCFLAGS -L."
-# We need gfortran to compile parts of the library
+# We need 'gfortran' to compile parts of the library, and test libgomp Fortran
+# support.
# We can't use AC_PROG_FC because it expects a fully working gfortran.
#AC_PROG_FC(gfortran)
case `echo $GFORTRAN` in
@@ -339,6 +349,13 @@ fi
AX_COUNT_CPUS
AC_SUBST(CPU_COUNT)
+AC_MSG_NOTICE([checking for flock implementation])
+AC_CHECK_PROGS(FLOCK, flock)
+# Fallback if 'perl' is available.
+if test -z "$FLOCK"; then
+ AC_CHECK_PROG(FLOCK, perl, $srcdir/testsuite/flock)
+fi
+
# Get target configury.
. ${srcdir}/configure.tgt
CFLAGS="$save_CFLAGS $XCFLAGS"
@@ -385,9 +402,9 @@ fi
# which will force linkage against -lpthread (or equivalent for the system).
# That's not 100% ideal, but about the best we can do easily.
if test $enable_shared = yes; then
- link_gomp="-lgomp %{static: $LIBS}"
+ link_gomp="-lgomp %{static: $LIBS${DL_LIBS:+ $DL_LIBS}}"
else
- link_gomp="-lgomp $LIBS"
+ link_gomp="-lgomp $LIBS${DL_LIBS:+ $DL_LIBS}"
fi
AC_SUBST(link_gomp)
diff --git a/libgomp/env.c b/libgomp/env.c
index e7a035b..f24484d 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -62,13 +62,14 @@
#include "secure_getenv.h"
#include "environ.h"
-/* Default values of ICVs according to the OpenMP standard. */
+/* Default values of ICVs according to the OpenMP standard,
+ except for default-device-var. */
const struct gomp_default_icv gomp_default_icv_values = {
.nthreads_var = 1,
.thread_limit_var = UINT_MAX,
.run_sched_var = GFS_DYNAMIC,
.run_sched_chunk_size = 1,
- .default_device_var = 0,
+ .default_device_var = INT_MIN,
.max_active_levels_var = 1,
.bind_var = omp_proc_bind_false,
.nteams_var = 0,
@@ -111,6 +112,7 @@ unsigned long gomp_bind_var_list_len;
void **gomp_places_list;
unsigned long gomp_places_list_len;
uintptr_t gomp_def_allocator = omp_default_mem_alloc;
+char *gomp_def_allocator_envvar = NULL;
int gomp_debug_var;
unsigned int gomp_num_teams_var;
int gomp_nteams_var;
@@ -1232,8 +1234,12 @@ parse_affinity (bool ignore)
static bool
parse_allocator (const char *env, const char *val, void *const params[])
{
+ const char *orig_val = val;
uintptr_t *ret = (uintptr_t *) params[0];
*ret = omp_default_mem_alloc;
+ bool memspace = false;
+ size_t ntraits = 0;
+ omp_alloctrait_t *traits;
if (val == NULL)
return false;
@@ -1242,28 +1248,169 @@ parse_allocator (const char *env, const char *val, void *const params[])
++val;
if (0)
;
-#define C(v) \
+#define C(v, m) \
else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
{ \
*ret = v; \
val += sizeof (#v) - 1; \
- }
- C (omp_default_mem_alloc)
- C (omp_large_cap_mem_alloc)
- C (omp_const_mem_alloc)
- C (omp_high_bw_mem_alloc)
- C (omp_low_lat_mem_alloc)
- C (omp_cgroup_mem_alloc)
- C (omp_pteam_mem_alloc)
- C (omp_thread_mem_alloc)
+ memspace = m; \
+ }
+ C (omp_default_mem_alloc, false)
+ C (omp_large_cap_mem_alloc, false)
+ C (omp_const_mem_alloc, false)
+ C (omp_high_bw_mem_alloc, false)
+ C (omp_low_lat_mem_alloc, false)
+ C (omp_cgroup_mem_alloc, false)
+ C (omp_pteam_mem_alloc, false)
+ C (omp_thread_mem_alloc, false)
+ C (omp_default_mem_space, true)
+ C (omp_large_cap_mem_space, true)
+ C (omp_const_mem_space, true)
+ C (omp_high_bw_mem_space, true)
+ C (omp_low_lat_mem_space, true)
#undef C
else
- val = "X";
+ goto invalid;
+ if (memspace && *val == ':')
+ {
+ ++val;
+ const char *cp = val;
+ while (*cp != '\0')
+ {
+ if (*cp == '=')
+ ++ntraits;
+ ++cp;
+ }
+ traits = gomp_alloca (ntraits * sizeof (omp_alloctrait_t));
+ size_t n = 0;
+ while (*val != '\0')
+ {
+#define C(v) \
+ else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
+ { \
+ val += sizeof (#v); \
+ traits[n].key = omp_atk_ ## v;
+#define V(v) \
+ else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
+ { \
+ val += sizeof (#v) - 1; \
+ traits[n].value = omp_atv_ ## v; \
+ }
+ if (0)
+ ;
+ C (sync_hint)
+ if (0)
+ ;
+ V (contended)
+ V (uncontended)
+ V (serialized)
+ V (private)
+ else
+ goto invalid;
+ }
+ C (alignment)
+ char *end;
+ errno = 0;
+ traits[n].value = strtol (val, &end, 10);
+ if (errno || end == val || traits[n].value <= 0)
+ goto invalid;
+ val = end;
+ }
+ C (access)
+ if (0)
+ ;
+ V (all)
+ V (cgroup)
+ V (pteam)
+ V (thread)
+ else
+ goto invalid;
+ }
+ C (pool_size)
+ char *end;
+ errno = 0;
+ traits[n].value = strtol (val, &end, 10);
+ if (errno || end == val || traits[n].value <= 0)
+ goto invalid;
+ val = end;
+ }
+ C (fallback)
+ if (0)
+ ;
+ V (default_mem_fb)
+ V (null_fb)
+ V (abort_fb)
+ V (allocator_fb)
+ else
+ goto invalid;
+ }
+ /* Ignore fb_data, which expects an allocator handle. */
+ C (pinned)
+ if (0)
+ ;
+ V (true)
+ V (false)
+ else
+ goto invalid;
+ }
+ C (partition)
+ if (0)
+ ;
+ V (environment)
+ V (nearest)
+ V (blocked)
+ V (interleaved)
+ else
+ goto invalid;
+ }
+ else
+ goto invalid;
+ if (*val != ',')
+ break;
+ ++val;
+ ++n;
+ if (*val == '\0')
+ goto invalid;
+ }
+#undef C
+#undef V
+ }
+ else if (memspace)
+ switch (*ret)
+ {
+ case omp_default_mem_space: *ret = omp_default_mem_alloc; break;
+ case omp_large_cap_mem_space: *ret = omp_large_cap_mem_alloc; break;
+ case omp_const_mem_space: *ret = omp_const_mem_alloc; break;
+ case omp_high_bw_mem_space: *ret = omp_high_bw_mem_alloc; break;
+ case omp_low_lat_mem_space: *ret = omp_low_lat_mem_alloc; break;
+ default: __builtin_unreachable ();
+ }
while (isspace ((unsigned char) *val))
++val;
if (*val == '\0')
- return true;
- print_env_var_error (env, val);
+ {
+ if (ntraits)
+ {
+ *ret = omp_init_allocator (*ret, ntraits, traits);
+ if (*ret == omp_null_allocator)
+ {
+ gomp_error ("Allocator of environment variable %.*s cannot be "
+ "created, using omp_default_mem_alloc instead",
+ (int) (orig_val - env - 1), env);
+ *ret = omp_default_mem_alloc;
+ }
+ else
+ gomp_def_allocator_envvar = strdup (orig_val);
+ }
+ return true;
+ }
+invalid:
+ int len = (orig_val - env - 1);
+ if (*val == '\0')
+ gomp_error ("Missing value at the end of environment variable %s", env);
+ else
+ gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
+ len, env, val);
*ret = omp_default_mem_alloc;
return false;
}
@@ -1614,6 +1761,10 @@ omp_display_env (int verbose)
struct gomp_icv_list *none
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
+ if (none->icvs.default_device_var == INT_MIN)
+ /* This implies OMP_TARGET_OFFLOAD=mandatory. */
+ gomp_init_targets_once ();
+
fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
fputs (" _OPENMP = '201511'\n", stderr);
@@ -1779,7 +1930,11 @@ omp_display_env (int verbose)
C (omp_pteam_mem_alloc)
C (omp_thread_mem_alloc)
#undef C
- default: break;
+ /* For an OMP_ALLOCATOR with traits, '' will be output. */
+ default:
+ if (gomp_def_allocator_envvar)
+ fputs (gomp_def_allocator_envvar, stderr);
+ break;
}
fputs ("'\n", stderr);
@@ -2031,6 +2186,16 @@ startswith (const char *str, const char *prefix)
return strncmp (str, prefix, strlen (prefix)) == 0;
}
+static void __attribute__((destructor))
+cleanup_env (void)
+{
+ if (gomp_def_allocator_envvar != NULL)
+ {
+ free (gomp_def_allocator_envvar);
+ omp_destroy_allocator (gomp_def_allocator);
+ }
+}
+
static void __attribute__((constructor))
initialize_env (void)
{
@@ -2213,6 +2378,10 @@ initialize_env (void)
gomp_global_icv.max_active_levels_var = gomp_supported_active_levels;
}
+ if (gomp_global_icv.default_device_var == INT_MIN
+ && gomp_target_offload_var != GOMP_TARGET_OFFLOAD_MANDATORY)
+ none->icvs.default_device_var = gomp_global_icv.default_device_var = 0;
+
/* Process GOMP_* variables and dependencies between parsed ICVs. */
parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
diff --git a/libgomp/icv-device.c b/libgomp/icv-device.c
index a2bbedc..b48ea3b 100644
--- a/libgomp/icv-device.c
+++ b/libgomp/icv-device.c
@@ -27,6 +27,7 @@
expected to replace. */
#include "libgomp.h"
+#include <limits.h>
void
omp_set_default_device (int device_num)
@@ -41,6 +42,9 @@ int
omp_get_default_device (void)
{
struct gomp_task_icv *icv = gomp_icv (false);
+ if (icv->default_device_var == INT_MIN)
+ /* This implies OMP_TARGET_OFFLOAD=mandatory. */
+ gomp_init_targets_once ();
return icv->default_device_var;
}
diff --git a/libgomp/libgomp-plugin.c b/libgomp/libgomp-plugin.c
index 27e7c94..d696515 100644
--- a/libgomp/libgomp-plugin.c
+++ b/libgomp/libgomp-plugin.c
@@ -82,11 +82,8 @@ GOMP_PLUGIN_fatal (const char *msg, ...)
void
GOMP_PLUGIN_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
uint64_t sizes_ptr, uint64_t kinds_ptr, int dev_num,
- void (*dev_to_host_cpy) (void *, const void *, size_t,
- void *),
- void (*host_to_dev_cpy) (void *, const void *, size_t,
- void *), void *token)
+ struct goacc_asyncqueue *aq)
{
gomp_target_rev (fn_ptr, mapnum, devaddrs_ptr, sizes_ptr, kinds_ptr, dev_num,
- dev_to_host_cpy, host_to_dev_cpy, token);
+ aq);
}
diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h
index 28267f7..42ee3d6 100644
--- a/libgomp/libgomp-plugin.h
+++ b/libgomp/libgomp-plugin.h
@@ -121,11 +121,7 @@ extern void GOMP_PLUGIN_fatal (const char *, ...)
__attribute__ ((noreturn, format (printf, 1, 2)));
extern void GOMP_PLUGIN_target_rev (uint64_t, uint64_t, uint64_t, uint64_t,
- uint64_t, int,
- void (*) (void *, const void *, size_t,
- void *),
- void (*) (void *, const void *, size_t,
- void *), void *);
+ uint64_t, int, struct goacc_asyncqueue *);
/* Prototypes for functions implemented by libgomp plugins. */
extern const char *GOMP_OFFLOAD_get_name (void);
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index ba8fe34..4d2bfab 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1130,10 +1130,7 @@ extern void gomp_init_targets_once (void);
extern int gomp_get_num_devices (void);
extern bool gomp_target_task_fn (void *);
extern void gomp_target_rev (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
- int,
- void (*) (void *, const void *, size_t, void *),
- void (*) (void *, const void *, size_t, void *),
- void *);
+ int, struct goacc_asyncqueue *);
/* Splay tree definitions. */
typedef struct splay_tree_node_s *splay_tree_node;
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index dc6b4ac..db8b1f1 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -192,8 +192,7 @@ The OpenMP 4.5 specification is fully supported.
env variable @tab Y @tab
@item Nested-parallel changes to @emph{max-active-levels-var} ICV @tab Y @tab
@item @code{requires} directive @tab P
- @tab complete but no non-host devices provides @code{unified_address} or
- @code{unified_shared_memory}
+ @tab complete but no non-host devices provides @code{unified_shared_memory}
@item @code{teams} construct outside an enclosing target region @tab Y @tab
@item Non-rectangular loop nests @tab P @tab Full support for C/C++, partial for Fortran
@item @code{!=} as relational-op in canonical loop form for C/C++ @tab Y @tab
@@ -311,7 +310,7 @@ The OpenMP 4.5 specification is fully supported.
@item @code{inoutset} argument to the @code{depend} clause @tab Y @tab
@item @code{private} and @code{firstprivate} argument to @code{default}
clause in C and C++ @tab Y @tab
-@item @code{present} argument to @code{defaultmap} clause @tab N @tab
+@item @code{present} argument to @code{defaultmap} clause @tab Y @tab
@item @code{omp_set_num_teams}, @code{omp_set_teams_thread_limit},
@code{omp_get_max_teams}, @code{omp_get_teams_thread_limit} runtime
routines @tab Y @tab
@@ -353,6 +352,8 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
@item Optional comma between directive and clause in the @code{#pragma} form @tab Y @tab
@item @code{indirect} clause in @code{declare target} @tab N @tab
@item @code{device_type(nohost)}/@code{device_type(host)} for variables @tab N @tab
+@item @code{present} modifier to the @code{map}, @code{to} and @code{from}
+ clauses @tab Y @tab
@end multitable
@@ -383,12 +384,12 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
@item @code{declare mapper} with iterator and @code{present} modifiers
@tab N @tab
@item If a matching mapped list item is not found in the data environment, the
- pointer retains its original value @tab N @tab
+ pointer retains its original value @tab Y @tab
@item New @code{enter} clause as alias for @code{to} on declare target directive
@tab Y @tab
@item Deprecation of @code{to} clause on declare target directive @tab N @tab
@item Extended list of directives permitted in Fortran pure procedures
- @tab N @tab
+ @tab Y @tab
@item New @code{allocators} directive for Fortran @tab N @tab
@item Deprecation of @code{allocate} directive for Fortran
allocatables/pointers @tab N @tab
@@ -422,7 +423,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
@item Conforming device numbers and @code{omp_initial_device} and
@code{omp_invalid_device} enum/PARAMETER @tab Y @tab
@item Initial value of @emph{default-device-var} ICV with
- @code{OMP_TARGET_OFFLOAD=mandatory} @tab N @tab
+ @code{OMP_TARGET_OFFLOAD=mandatory} @tab Y @tab
@item @emph{interop_types} in any position of the modifier list for the @code{init} clause
of the @code{interop} construct @tab N @tab
@end multitable
@@ -1936,7 +1937,10 @@ section 4 of the OpenMP specification in version 4.5, while those
beginning with @env{GOMP_} are GNU extensions.
@menu
+* OMP_ALLOCATOR:: Set the default allocator
+* OMP_AFFINITY_FORMAT:: Set the format string used for affinity display
* OMP_CANCELLATION:: Set whether cancellation is activated
+* OMP_DISPLAY_AFFINITY:: Display thread affinity information
* OMP_DISPLAY_ENV:: Show OpenMP version and environment variables
* OMP_DEFAULT_DEVICE:: Set the device used in target regions
* OMP_DYNAMIC:: Dynamic adjustment of threads
@@ -1961,6 +1965,125 @@ beginning with @env{GOMP_} are GNU extensions.
@end menu
+@node OMP_ALLOCATOR
+@section @env{OMP_ALLOCATOR} -- Set the default allocator
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Sets the default allocator that is used when no allocator has been specified
+in the @code{allocate} or @code{allocator} clause or if an OpenMP memory
+routine is invoked with the @code{omp_null_allocator} allocator.
+If unset, @code{omp_default_mem_alloc} is used.
+
+The value can either be a predefined allocator or a predefined memory space
+or a predefined memory space followed by a colon and a comma-separated list
+of memory trait and value pairs, separated by @code{=}.
+
+@multitable @columnfractions .45 .45
+@headitem Predefined allocators @tab Predefined memory spaces
+@item omp_default_mem_alloc @tab omp_default_mem_space
+@item omp_large_cap_mem_alloc @tab omp_large_cap_mem_space
+@item omp_const_mem_alloc @tab omp_const_mem_space
+@item omp_high_bw_mem_alloc @tab omp_high_bw_mem_space
+@item omp_low_lat_mem_alloc @tab omp_low_lat_mem_space
+@item omp_cgroup_mem_alloc @tab --
+@item omp_pteam_mem_alloc @tab --
+@item omp_thread_mem_alloc @tab --
+@end multitable
+
+@multitable @columnfractions .30 .60
+@headitem Trait @tab Allowed values
+@item @code{sync_hint} @tab @code{contended}, @code{uncontended},
+ @code{serialized}, @code{private}
+@item @code{alignment} @tab Positive integer being a power of two
+@item @code{access} @tab @code{all}, @code{cgroup},
+ @code{pteam}, @code{thread}
+@item @code{pool_size} @tab Positive integer
+@item @code{fallback} @tab @code{default_mem_fb}, @code{null_fb},
+ @code{abort_fb}, @code{allocator_fb}
+@item @code{fb_data} @tab @emph{unsupported as it needs an allocator handle}
+@item @code{pinned} @tab @code{true}, @code{false}
+@item @code{partition} @tab @code{environment}, @code{nearest},
+ @code{blocked}, @code{interleaved}
+@end multitable
+
+Examples:
+@smallexample
+OMP_ALLOCATOR=omp_high_bw_mem_alloc
+OMP_ALLOCATOR=omp_large_cap_mem_space
+OMP_ALLOCATR=omp_low_lat_mem_space:pinned=true,partition=nearest
+@end smallexample
+
+@c @item @emph{See also}:
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.21
+@end table
+
+
+
+@node OMP_AFFINITY_FORMAT
+@section @env{OMP_AFFINITY_FORMAT} -- Set the format string used for affinity display
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Sets the format string used when displaying OpenMP thread affinity information.
+Special values are output using @code{%} followed by an optional size
+specification and then either the single-character field type or its long
+name enclosed in curly braces; using @code{%%} will display a literal percent.
+The size specification consists of an optional @code{0.} or @code{.} followed
+by a positive integer, specifing the minimal width of the output. With
+@code{0.} and numerical values, the output is padded with zeros on the left;
+with @code{.}, the output is padded by spaces on the left; otherwise, the
+output is padded by spaces on the right. If unset, the value is
+``@code{level %L thread %i affinity %A}''.
+
+Supported field types are:
+
+@multitable @columnfractions .10 .25 .60
+@item t @tab team_num @tab value returned by @code{omp_get_team_num}
+@item T @tab num_teams @tab value returned by @code{omp_get_num_teams}
+@item L @tab nesting_level @tab value returned by @code{omp_get_level}
+@item n @tab thread_num @tab value returned by @code{omp_get_thread_num}
+@item N @tab num_threads @tab value returned by @code{omp_get_num_threads}
+@item a @tab ancestor_tnum
+ @tab value returned by
+ @code{omp_get_ancestor_thread_num(omp_get_level()-1)}
+@item H @tab host @tab name of the host that executes the thread
+@item P @tab process_id @tab process identifier
+@item i @tab native_thread_id @tab native thread identifier
+@item A @tab thread_affinity
+ @tab comma separated list of integer values or ranges, representing the
+ processors on which a process might execute, subject to affinity
+ mechanisms
+@end multitable
+
+For instance, after setting
+
+@smallexample
+OMP_AFFINITY_FORMAT="%0.2a!%n!%.4L!%N;%.2t;%0.2T;%@{team_num@};%@{num_teams@};%A"
+@end smallexample
+
+with either @code{OMP_DISPLAY_AFFINITY} being set or when calling
+@code{omp_display_affinity} with @code{NULL} or an empty string, the program
+might display the following:
+
+@smallexample
+00!0! 1!4; 0;01;0;1;0-11
+00!3! 1!4; 0;01;0;1;0-11
+00!2! 1!4; 0;01;0;1;0-11
+00!1! 1!4; 0;01;0;1;0-11
+@end smallexample
+
+@item @emph{See also}:
+@ref{OMP_DISPLAY_AFFINITY}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.14
+@end table
+
+
+
@node OMP_CANCELLATION
@section @env{OMP_CANCELLATION} -- Set whether cancellation is activated
@cindex Environment Variable
@@ -1978,6 +2101,26 @@ if unset, cancellation is disabled and the @code{cancel} construct is ignored.
+@node OMP_DISPLAY_AFFINITY
+@section @env{OMP_DISPLAY_AFFINITY} -- Display thread affinity information
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+If set to @code{FALSE} or if unset, affinity displaying is disabled.
+If set to @code{TRUE}, the runtime will display affinity information about
+OpenMP threads in a parallel region upon entering the region and every time
+any change occurs.
+
+@item @emph{See also}:
+@ref{OMP_AFFINITY_FORMAT}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v5.0}, Section 6.13
+@end table
+
+
+
+
@node OMP_DISPLAY_ENV
@section @env{OMP_DISPLAY_ENV} -- Show OpenMP version and environment variables
@cindex Environment Variable
@@ -2005,6 +2148,8 @@ Set to choose the device which is used in a @code{target} region, unless the
value is overridden by @code{omp_set_default_device} or by a @code{device}
clause. The value shall be the nonnegative device number. If no device with
the given device number exists, the code is executed on the host. If unset,
+@env{OMP_TARGET_OFFLOAD} is @code{mandatory} and no non-host devices are
+available, it is set to @code{omp_invalid_device}. Otherwise, if unset,
device number 0 will be used.
@@ -4458,7 +4603,7 @@ The implementation remark:
@code{device(ancestor:1)}) are processed serially per @code{target} region
such that the next reverse offload region is only executed after the previous
one returned.
-@item OpenMP code that has a requires directive with @code{unified_address} or
+@item OpenMP code that has a @code{requires} directive with
@code{unified_shared_memory} will remove any GCN device from the list of
available devices (``host fallback'').
@item The available stack size can be changed using the @code{GCN_STACK_SIZE}
@@ -4520,8 +4665,8 @@ The implementation remark:
Per device, reverse offload regions are processed serially such that
the next reverse offload region is only executed after the previous
one returned.
-@item OpenMP code that has a requires directive with @code{unified_address}
- or @code{unified_shared_memory} will remove any nvptx device from the
+@item OpenMP code that has a @code{requires} directive with
+ @code{unified_shared_memory} will remove any nvptx device from the
list of available devices (``host fallback'').
@end itemize
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index 3478037..ef22d48 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -1949,7 +1949,7 @@ process_reverse_offload (uint64_t fn, uint64_t mapnum, uint64_t hostaddrs,
{
int dev_num = dev_num64;
GOMP_PLUGIN_target_rev (fn, mapnum, hostaddrs, sizes, kinds, dev_num,
- NULL, NULL, NULL);
+ NULL);
}
/* Output any data written to console output from the kernel. It is expected
@@ -3231,7 +3231,9 @@ GOMP_OFFLOAD_get_num_devices (unsigned int omp_requires_mask)
/* Return -1 if no omp_requires_mask cannot be fulfilled but
devices were present. */
if (hsa_context.agent_count > 0
- && (omp_requires_mask & ~GOMP_REQUIRES_REVERSE_OFFLOAD) != 0)
+ && ((omp_requires_mask
+ & ~(GOMP_REQUIRES_UNIFIED_ADDRESS
+ | GOMP_REQUIRES_REVERSE_OFFLOAD)) != 0))
return -1;
return hsa_context.agent_count;
}
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index b3481c4..ffc8e2d 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -56,6 +56,7 @@
#include <unistd.h>
#include <assert.h>
#include <errno.h>
+#include <stdlib.h>
/* An arbitrary fixed limit (128MB) for the size of the OpenMP soft stacks
block to cache between kernel invocations. For soft-stacks blocks bigger
@@ -1625,11 +1626,11 @@ GOMP_OFFLOAD_openacc_cuda_set_stream (struct goacc_asyncqueue *aq, void *stream)
return 1;
}
-struct goacc_asyncqueue *
-GOMP_OFFLOAD_openacc_async_construct (int device __attribute__((unused)))
+static struct goacc_asyncqueue *
+nvptx_goacc_asyncqueue_construct (unsigned int flags)
{
CUstream stream = NULL;
- CUDA_CALL_ERET (NULL, cuStreamCreate, &stream, CU_STREAM_DEFAULT);
+ CUDA_CALL_ERET (NULL, cuStreamCreate, &stream, flags);
struct goacc_asyncqueue *aq
= GOMP_PLUGIN_malloc (sizeof (struct goacc_asyncqueue));
@@ -1637,14 +1638,26 @@ GOMP_OFFLOAD_openacc_async_construct (int device __attribute__((unused)))
return aq;
}
-bool
-GOMP_OFFLOAD_openacc_async_destruct (struct goacc_asyncqueue *aq)
+struct goacc_asyncqueue *
+GOMP_OFFLOAD_openacc_async_construct (int device __attribute__((unused)))
+{
+ return nvptx_goacc_asyncqueue_construct (CU_STREAM_DEFAULT);
+}
+
+static bool
+nvptx_goacc_asyncqueue_destruct (struct goacc_asyncqueue *aq)
{
CUDA_CALL_ERET (false, cuStreamDestroy, aq->cuda_stream);
free (aq);
return true;
}
+bool
+GOMP_OFFLOAD_openacc_async_destruct (struct goacc_asyncqueue *aq)
+{
+ return nvptx_goacc_asyncqueue_destruct (aq);
+}
+
int
GOMP_OFFLOAD_openacc_async_test (struct goacc_asyncqueue *aq)
{
@@ -1658,14 +1671,20 @@ GOMP_OFFLOAD_openacc_async_test (struct goacc_asyncqueue *aq)
return -1;
}
-bool
-GOMP_OFFLOAD_openacc_async_synchronize (struct goacc_asyncqueue *aq)
+static bool
+nvptx_goacc_asyncqueue_synchronize (struct goacc_asyncqueue *aq)
{
CUDA_CALL_ERET (false, cuStreamSynchronize, aq->cuda_stream);
return true;
}
bool
+GOMP_OFFLOAD_openacc_async_synchronize (struct goacc_asyncqueue *aq)
+{
+ return nvptx_goacc_asyncqueue_synchronize (aq);
+}
+
+bool
GOMP_OFFLOAD_openacc_async_serialize (struct goacc_asyncqueue *aq1,
struct goacc_asyncqueue *aq2)
{
@@ -1925,22 +1944,6 @@ nvptx_stacks_acquire (struct ptx_device *ptx_dev, size_t size, int num)
void
-rev_off_dev_to_host_cpy (void *dest, const void *src, size_t size,
- CUstream stream)
-{
- CUDA_CALL_ASSERT (cuMemcpyDtoHAsync, dest, (CUdeviceptr) src, size, stream);
- CUDA_CALL_ASSERT (cuStreamSynchronize, stream);
-}
-
-void
-rev_off_host_to_dev_cpy (void *dest, const void *src, size_t size,
- CUstream stream)
-{
- CUDA_CALL_ASSERT (cuMemcpyHtoDAsync, (CUdeviceptr) dest, src, size, stream);
- CUDA_CALL_ASSERT (cuStreamSynchronize, stream);
-}
-
-void
GOMP_OFFLOAD_run (int ord, void *tgt_fn, void *tgt_vars, void **args)
{
struct targ_fn_descriptor *tgt_fn_desc
@@ -1973,9 +1976,17 @@ GOMP_OFFLOAD_run (int ord, void *tgt_fn, void *tgt_vars, void **args)
}
nvptx_adjust_launch_bounds (tgt_fn, ptx_dev, &teams, &threads);
- size_t stack_size = nvptx_stacks_size ();
bool reverse_offload = ptx_dev->rev_data != NULL;
- CUstream copy_stream = NULL;
+ struct goacc_asyncqueue *reverse_offload_aq = NULL;
+ if (reverse_offload)
+ {
+ reverse_offload_aq
+ = nvptx_goacc_asyncqueue_construct (CU_STREAM_NON_BLOCKING);
+ if (!reverse_offload_aq)
+ exit (EXIT_FAILURE);
+ }
+
+ size_t stack_size = nvptx_stacks_size ();
pthread_mutex_lock (&ptx_dev->omp_stacks.lock);
void *stacks = nvptx_stacks_acquire (ptx_dev, stack_size, teams * threads);
@@ -1989,8 +2000,6 @@ GOMP_OFFLOAD_run (int ord, void *tgt_fn, void *tgt_vars, void **args)
GOMP_PLUGIN_debug (0, " %s: kernel %s: launch"
" [(teams: %u), 1, 1] [(lanes: 32), (threads: %u), 1]\n",
__FUNCTION__, fn_name, teams, threads);
- if (reverse_offload)
- CUDA_CALL_ASSERT (cuStreamCreate, &copy_stream, CU_STREAM_NON_BLOCKING);
r = CUDA_CALL_NOCHECK (cuLaunchKernel, function, teams, 1, 1,
32, threads, 1, 0, NULL, NULL, config);
if (r != CUDA_SUCCESS)
@@ -2013,17 +2022,15 @@ GOMP_OFFLOAD_run (int ord, void *tgt_fn, void *tgt_vars, void **args)
GOMP_PLUGIN_target_rev (rev_data->fn, rev_data->mapnum,
rev_data->addrs, rev_data->sizes,
rev_data->kinds, rev_data->dev_num,
- rev_off_dev_to_host_cpy,
- rev_off_host_to_dev_cpy, copy_stream);
- CUDA_CALL_ASSERT (cuStreamSynchronize, copy_stream);
+ reverse_offload_aq);
+ if (!nvptx_goacc_asyncqueue_synchronize (reverse_offload_aq))
+ exit (EXIT_FAILURE);
__atomic_store_n (&rev_data->fn, 0, __ATOMIC_RELEASE);
}
usleep (1);
}
else
r = CUDA_CALL_NOCHECK (cuCtxSynchronize, );
- if (reverse_offload)
- CUDA_CALL_ASSERT (cuStreamDestroy, copy_stream);
if (r == CUDA_ERROR_LAUNCH_FAILED)
GOMP_PLUGIN_fatal ("cuCtxSynchronize error: %s %s\n", cuda_error (r),
maybe_abort_msg);
@@ -2031,6 +2038,12 @@ GOMP_OFFLOAD_run (int ord, void *tgt_fn, void *tgt_vars, void **args)
GOMP_PLUGIN_fatal ("cuCtxSynchronize error: %s", cuda_error (r));
pthread_mutex_unlock (&ptx_dev->omp_stacks.lock);
+
+ if (reverse_offload)
+ {
+ if (!nvptx_goacc_asyncqueue_destruct (reverse_offload_aq))
+ exit (EXIT_FAILURE);
+ }
}
/* TODO: Implement GOMP_OFFLOAD_async_run. */
diff --git a/libgomp/target.c b/libgomp/target.c
index b30c6a50..80c25a1 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -138,6 +138,10 @@ gomp_get_num_devices (void)
static struct gomp_device_descr *
resolve_device (int device_id, bool remapped)
{
+ /* Get number of devices and thus ensure that 'gomp_init_targets_once' was
+ called, which must be done before using default_device_var. */
+ int num_devices = gomp_get_num_devices ();
+
if (remapped && device_id == GOMP_DEVICE_ICV)
{
struct gomp_task_icv *icv = gomp_icv (false);
@@ -150,7 +154,11 @@ resolve_device (int device_id, bool remapped)
if (device_id == (remapped ? GOMP_DEVICE_HOST_FALLBACK
: omp_initial_device))
return NULL;
- if (device_id == omp_invalid_device)
+ if (gomp_target_offload_var == GOMP_TARGET_OFFLOAD_MANDATORY
+ && num_devices == 0)
+ gomp_fatal ("OMP_TARGET_OFFLOAD is set to MANDATORY, "
+ "but only the host device is available");
+ else if (device_id == omp_invalid_device)
gomp_fatal ("omp_invalid_device encountered");
else if (gomp_target_offload_var == GOMP_TARGET_OFFLOAD_MANDATORY)
gomp_fatal ("OMP_TARGET_OFFLOAD is set to MANDATORY, "
@@ -158,10 +166,10 @@ resolve_device (int device_id, bool remapped)
return NULL;
}
- else if (device_id >= gomp_get_num_devices ())
+ else if (device_id >= num_devices)
{
if (gomp_target_offload_var == GOMP_TARGET_OFFLOAD_MANDATORY
- && device_id != num_devices_openmp)
+ && device_id != num_devices)
gomp_fatal ("OMP_TARGET_OFFLOAD is set to MANDATORY, "
"but device not found");
@@ -358,6 +366,8 @@ gomp_to_device_kind_p (int kind)
case GOMP_MAP_FORCE_ALLOC:
case GOMP_MAP_FORCE_FROM:
case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_ALWAYS_PRESENT_FROM:
+ case GOMP_MAP_FORCE_PRESENT:
return false;
default:
return true;
@@ -593,7 +603,7 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep,
else
tgt_var->length = newn->host_end - newn->host_start;
- if ((kind & GOMP_MAP_FLAG_FORCE)
+ if (GOMP_MAP_FORCE_P (kind)
/* For implicit maps, old contained in new is valid. */
|| !(implicit_subset
/* Otherwise, new contained inside old is considered valid. */
@@ -1143,7 +1153,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
if (!n)
{
tgt->list[i].key = NULL;
- tgt->list[i].offset = OFFSET_POINTER;
+ tgt->list[i].offset = OFFSET_INLINED;
continue;
}
}
@@ -1697,20 +1707,26 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
i = j - 1;
break;
case GOMP_MAP_FORCE_PRESENT:
+ case GOMP_MAP_ALWAYS_PRESENT_TO:
+ case GOMP_MAP_ALWAYS_PRESENT_FROM:
+ case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
{
/* We already looked up the memory region above and it
was missing. */
size_t size = k->host_end - k->host_start;
gomp_mutex_unlock (&devicep->lock);
#ifdef HAVE_INTTYPES_H
- gomp_fatal ("present clause: !acc_is_present (%p, "
- "%"PRIu64" (0x%"PRIx64"))",
- (void *) k->host_start,
- (uint64_t) size, (uint64_t) size);
+ gomp_fatal ("present clause: not present on the device "
+ "(addr: %p, size: %"PRIu64" (0x%"PRIx64"), "
+ "dev: %d)", (void *) k->host_start,
+ (uint64_t) size, (uint64_t) size,
+ devicep->target_id);
#else
- gomp_fatal ("present clause: !acc_is_present (%p, "
- "%lu (0x%lx))", (void *) k->host_start,
- (unsigned long) size, (unsigned long) size);
+ gomp_fatal ("present clause: not present on the device "
+ "(addr: %p, size: %lu (0x%lx), dev: %d)",
+ (void *) k->host_start,
+ (unsigned long) size, (unsigned long) size,
+ devicep->target_id);
#endif
}
break;
@@ -2124,6 +2140,29 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs,
gomp_copy_dev2host (devicep, NULL, hostaddr, devaddr, size);
}
}
+ else
+ {
+ int kind = get_kind (short_mapkind, kinds, i);
+
+ if (GOMP_MAP_PRESENT_P (kind))
+ {
+ /* We already looked up the memory region above and it
+ was missing. */
+ gomp_mutex_unlock (&devicep->lock);
+#ifdef HAVE_INTTYPES_H
+ gomp_fatal ("present clause: not present on the device "
+ "(addr: %p, size: %"PRIu64" (0x%"PRIx64"), "
+ "dev: %d)", (void *) hostaddrs[i],
+ (uint64_t) sizes[i], (uint64_t) sizes[i],
+ devicep->target_id);
+#else
+ gomp_fatal ("present clause: not present on the device "
+ "(addr: %p, size: %lu (0x%lx), dev: %d)",
+ (void *) hostaddrs[i], (unsigned long) sizes[i],
+ (unsigned long) sizes[i], devicep->target_id);
+#endif
+ }
+ }
}
gomp_mutex_unlock (&devicep->lock);
}
@@ -3299,9 +3338,7 @@ gomp_map_cdata_lookup (struct cpy_data *d, uint64_t *devaddrs,
void
gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
uint64_t sizes_ptr, uint64_t kinds_ptr, int dev_num,
- void (*dev_to_host_cpy) (void *, const void *, size_t, void*),
- void (*host_to_dev_cpy) (void *, const void *, size_t, void*),
- void *token)
+ struct goacc_asyncqueue *aq)
{
/* Return early if there is no offload code. */
if (sizeof (OFFLOAD_PLUGINS) == sizeof (""))
@@ -3343,26 +3380,17 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
devaddrs = (uint64_t *) gomp_malloc (mapnum * sizeof (uint64_t));
sizes = (uint64_t *) gomp_malloc (mapnum * sizeof (uint64_t));
kinds = (unsigned short *) gomp_malloc (mapnum * sizeof (unsigned short));
- if (dev_to_host_cpy)
- {
- dev_to_host_cpy (devaddrs, (const void *) (uintptr_t) devaddrs_ptr,
- mapnum * sizeof (uint64_t), token);
- dev_to_host_cpy (sizes, (const void *) (uintptr_t) sizes_ptr,
- mapnum * sizeof (uint64_t), token);
- dev_to_host_cpy (kinds, (const void *) (uintptr_t) kinds_ptr,
- mapnum * sizeof (unsigned short), token);
- }
- else
- {
- gomp_copy_dev2host (devicep, NULL, devaddrs,
- (const void *) (uintptr_t) devaddrs_ptr,
- mapnum * sizeof (uint64_t));
- gomp_copy_dev2host (devicep, NULL, sizes,
- (const void *) (uintptr_t) sizes_ptr,
- mapnum * sizeof (uint64_t));
- gomp_copy_dev2host (devicep, NULL, kinds, (const void *) (uintptr_t) kinds_ptr,
- mapnum * sizeof (unsigned short));
- }
+ gomp_copy_dev2host (devicep, aq, devaddrs,
+ (const void *) (uintptr_t) devaddrs_ptr,
+ mapnum * sizeof (uint64_t));
+ gomp_copy_dev2host (devicep, aq, sizes,
+ (const void *) (uintptr_t) sizes_ptr,
+ mapnum * sizeof (uint64_t));
+ gomp_copy_dev2host (devicep, aq, kinds,
+ (const void *) (uintptr_t) kinds_ptr,
+ mapnum * sizeof (unsigned short));
+ if (aq && !devicep->openacc.async.synchronize_func (aq))
+ exit (EXIT_FAILURE);
}
size_t tgt_align = 0, tgt_size = 0;
@@ -3389,13 +3417,14 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
memcpy (tgt + tgt_size, (void *) (uintptr_t) devaddrs[i],
(size_t) sizes[i]);
- else if (dev_to_host_cpy)
- dev_to_host_cpy (tgt + tgt_size, (void *) (uintptr_t) devaddrs[i],
- (size_t) sizes[i], token);
else
- gomp_copy_dev2host (devicep, NULL, tgt + tgt_size,
- (void *) (uintptr_t) devaddrs[i],
- (size_t) sizes[i]);
+ {
+ gomp_copy_dev2host (devicep, aq, tgt + tgt_size,
+ (void *) (uintptr_t) devaddrs[i],
+ (size_t) sizes[i]);
+ if (aq && !devicep->openacc.async.synchronize_func (aq))
+ exit (EXIT_FAILURE);
+ }
devaddrs[i] = (uint64_t) (uintptr_t) tgt + tgt_size;
tgt_size = tgt_size + sizes[i];
if ((devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
@@ -3432,7 +3461,8 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
case GOMP_MAP_DELETE:
case GOMP_MAP_RELEASE:
case GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION:
- /* Assume it is present; look it up - but ignore otherwise. */
+ /* Assume it is present; look it up - but ignore unless the
+ present clause is there. */
case GOMP_MAP_ALLOC:
case GOMP_MAP_FROM:
case GOMP_MAP_FORCE_ALLOC:
@@ -3444,6 +3474,10 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
case GOMP_MAP_FORCE_TOFROM:
case GOMP_MAP_ALWAYS_TO:
case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_FORCE_PRESENT:
+ case GOMP_MAP_ALWAYS_PRESENT_FROM:
+ case GOMP_MAP_ALWAYS_PRESENT_TO:
+ case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
cdata[i].devaddr = devaddrs[i];
bool zero_len = (kind == GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION
@@ -3464,7 +3498,23 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
devaddrs[i] + sizes[i], zero_len);
cdata[i].present = n2 != NULL;
}
- if (!cdata[i].present
+ if (!cdata[i].present && GOMP_MAP_PRESENT_P (kind))
+ {
+ gomp_mutex_unlock (&devicep->lock);
+#ifdef HAVE_INTTYPES_H
+ gomp_fatal ("present clause: no corresponding data on "
+ "parent device at %p with size %"PRIu64,
+ (void *) (uintptr_t) devaddrs[i],
+ (uint64_t) sizes[i]);
+#else
+ gomp_fatal ("present clause: no corresponding data on "
+ "parent device at %p with size %lu",
+ (void *) (uintptr_t) devaddrs[i],
+ (unsigned long) sizes[i]);
+#endif
+ break;
+ }
+ else if (!cdata[i].present
&& kind != GOMP_MAP_DELETE
&& kind != GOMP_MAP_RELEASE
&& kind != GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION)
@@ -3482,18 +3532,17 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
&& (kind == GOMP_MAP_TO || kind == GOMP_MAP_TOFROM))
|| kind == GOMP_MAP_FORCE_TO
|| kind == GOMP_MAP_FORCE_TOFROM
- || kind == GOMP_MAP_ALWAYS_TO
- || kind == GOMP_MAP_ALWAYS_TOFROM)
+ || GOMP_MAP_ALWAYS_TO_P (kind))
{
- if (dev_to_host_cpy)
- dev_to_host_cpy ((void *) (uintptr_t) devaddrs[i],
- (void *) (uintptr_t) cdata[i].devaddr,
- sizes[i], token);
- else
- gomp_copy_dev2host (devicep, NULL,
- (void *) (uintptr_t) devaddrs[i],
- (void *) (uintptr_t) cdata[i].devaddr,
- sizes[i]);
+ gomp_copy_dev2host (devicep, aq,
+ (void *) (uintptr_t) devaddrs[i],
+ (void *) (uintptr_t) cdata[i].devaddr,
+ sizes[i]);
+ if (aq && !devicep->openacc.async.synchronize_func (aq))
+ {
+ gomp_mutex_unlock (&devicep->lock);
+ exit (EXIT_FAILURE);
+ }
}
if (struct_cpy)
struct_cpy--;
@@ -3560,15 +3609,15 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
devaddrs[i]
= (uint64_t) (uintptr_t) gomp_aligned_alloc (align,
sizes[i]);
- if (dev_to_host_cpy)
- dev_to_host_cpy ((void *) (uintptr_t) devaddrs[i],
- (void *) (uintptr_t) cdata[i].devaddr,
- sizes[i], token);
- else
- gomp_copy_dev2host (devicep, NULL,
- (void *) (uintptr_t) devaddrs[i],
- (void *) (uintptr_t) cdata[i].devaddr,
- sizes[i]);
+ gomp_copy_dev2host (devicep, aq,
+ (void *) (uintptr_t) devaddrs[i],
+ (void *) (uintptr_t) cdata[i].devaddr,
+ sizes[i]);
+ if (aq && !devicep->openacc.async.synchronize_func (aq))
+ {
+ gomp_mutex_unlock (&devicep->lock);
+ exit (EXIT_FAILURE);
+ }
}
for (j = i + 1; j < mapnum; j++)
{
@@ -3668,19 +3717,21 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr,
case GOMP_MAP_FORCE_TOFROM:
case GOMP_MAP_ALWAYS_FROM:
case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_ALWAYS_PRESENT_FROM:
+ case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
copy = true;
/* FALLTHRU */
case GOMP_MAP_FROM:
case GOMP_MAP_TOFROM:
- if (copy && host_to_dev_cpy)
- host_to_dev_cpy ((void *) (uintptr_t) cdata[i].devaddr,
- (void *) (uintptr_t) devaddrs[i],
- sizes[i], token);
- else if (copy)
- gomp_copy_host2dev (devicep, NULL,
- (void *) (uintptr_t) cdata[i].devaddr,
- (void *) (uintptr_t) devaddrs[i],
- sizes[i], false, NULL);
+ if (copy)
+ {
+ gomp_copy_host2dev (devicep, aq,
+ (void *) (uintptr_t) cdata[i].devaddr,
+ (void *) (uintptr_t) devaddrs[i],
+ sizes[i], false, NULL);
+ if (aq && !devicep->openacc.async.synchronize_func (aq))
+ exit (EXIT_FAILURE);
+ }
default:
break;
}
@@ -5141,6 +5192,15 @@ gomp_target_init (void)
if (devs[i].capabilities & GOMP_OFFLOAD_CAP_OPENACC_200)
goacc_register (&devs[i]);
}
+ if (gomp_global_icv.default_device_var == INT_MIN)
+ {
+ /* This implies OMP_TARGET_OFFLOAD=mandatory. */
+ struct gomp_icv_list *none;
+ none = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX);
+ gomp_global_icv.default_device_var = (num_devs_openmp
+ ? 0 : omp_invalid_device);
+ none->icvs.default_device_var = gomp_global_icv.default_device_var;
+ }
num_devices = num_devs;
num_devices_openmp = num_devs_openmp;
diff --git a/libgomp/testsuite/Makefile.am b/libgomp/testsuite/Makefile.am
index 655a413..0cc91cc 100644
--- a/libgomp/testsuite/Makefile.am
+++ b/libgomp/testsuite/Makefile.am
@@ -12,6 +12,8 @@ _RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \
echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+PWD_COMMAND = $${PWDCMD-pwd}
+
EXTRA_DEJAGNU_SITE_CONFIG = libgomp-site-extra.exp
# Instead of directly in ../testsuite/libgomp-test-support.exp.in, the
@@ -25,17 +27,6 @@ libgomp-test-support.exp: libgomp-test-support.pt.exp Makefile
'set offload_additional_lib_paths "$(offload_additional_lib_paths)"'
mv $@.tmp $@
-check-DEJAGNU: site.exp
- srcdir='$(srcdir)'; export srcdir; \
- EXPECT=$(EXPECT); export EXPECT; \
- if $(SHELL) -c "$(_RUNTEST) --version" > /dev/null 2>&1; then \
- exit_status=0; l='$(PACKAGE)'; for tool in $$l; do \
- if $(_RUNTEST) $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
- then :; else exit_status=1; fi; \
- done; \
- else echo "WARNING: could not find '$(_RUNTEST)'" 1>&2; :;\
- fi; \
- exit $$exit_status
site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
@echo 'Making a new site.exp file ...'
@echo '## these variables are automatically generated by make ##' >site.tmp
@@ -63,6 +54,72 @@ site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
@test ! -f site.exp || mv site.exp site.bak
@mv site.tmp site.exp
+%/site.exp: site.exp
+ -@test -d $* || mkdir $*
+ @srcdir=`cd $(srcdir); ${PWD_COMMAND}`;
+ @objdir=`${PWD_COMMAND}`/$*; \
+ sed -e "s|^set srcdir .*$$|set srcdir $$srcdir|" \
+ -e "s|^set objdir .*$$|set objdir $$objdir|" \
+ site.exp > $*/site.exp.tmp
+ @-rm -f $*/site.bak
+ @test ! -f $*/site.exp || mv $*/site.exp $*/site.bak
+ @mv $*/site.exp.tmp $*/site.exp
+
+check_p_numbers0:=1 2 3 4 5 6 7 8 9
+check_p_numbers1:=0 $(check_p_numbers0)
+check_p_numbers2:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers1)))
+check_p_numbers3:=$(addprefix 0,$(check_p_numbers1)) $(check_p_numbers2)
+check_p_numbers4:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers3)))
+check_p_numbers5:=$(addprefix 0,$(check_p_numbers3)) $(check_p_numbers4)
+check_p_numbers6:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers5)))
+check_p_numbers:=$(check_p_numbers0) $(check_p_numbers2) $(check_p_numbers4) $(check_p_numbers6)
+# If unable to serialize execution testing, use just one parallel slot.
+gcc_test_parallel_slots:=$(if $(FLOCK),$(if $(GCC_TEST_PARALLEL_SLOTS),$(GCC_TEST_PARALLEL_SLOTS),19),1)
+check_p_subdirs=$(wordlist 1,$(gcc_test_parallel_slots),$(check_p_numbers))
+check_DEJAGNU_libgomp_targets = $(addprefix check-DEJAGNUlibgomp,$(check_p_subdirs))
+$(check_DEJAGNU_libgomp_targets): check-DEJAGNUlibgomp%: libgomp%/site.exp
+
+check-DEJAGNU $(check_DEJAGNU_libgomp_targets): check-DEJAGNU%: site.exp
+ $(if $*,@)AR="$(AR)"; export AR; \
+ RANLIB="$(RANLIB)"; export RANLIB; \
+ if [ -z "$*" ] && [ -n "$(filter -j%, $(MFLAGS))" ]; then \
+ rm -rf libgomp-parallel || true; \
+ mkdir libgomp-parallel; \
+ $(MAKE) $(AM_MAKEFLAGS) $(check_DEJAGNU_libgomp_targets); \
+ rm -rf libgomp-parallel || true; \
+ for idx in $(check_p_subdirs); do \
+ if [ -d libgomp$$idx ]; then \
+ mv -f libgomp$$idx/libgomp.sum libgomp$$idx/libgomp.sum.sep; \
+ mv -f libgomp$$idx/libgomp.log libgomp$$idx/libgomp.log.sep; \
+ fi; \
+ done; \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh \
+ libgomp[0-9]*/libgomp.sum.sep > libgomp.sum; \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh -L \
+ libgomp[0-9]*/libgomp.log.sep > libgomp.log; \
+ exit 0; \
+ fi; \
+ srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \
+ EXPECT=$(EXPECT); export EXPECT; \
+ runtest=$(_RUNTEST); \
+ if [ -z "$$runtest" ]; then runtest=runtest; fi; \
+ tool=libgomp; \
+ if [ -n "$*" ]; then \
+ if [ -f libgomp-parallel/finished ]; then rm -rf "$*"; exit 0; fi; \
+ GCC_RUNTEST_PARALLELIZE_DIR=`${PWD_COMMAND}`/libgomp-parallel; \
+ export GCC_RUNTEST_PARALLELIZE_DIR; \
+ cd "$*"; \
+ fi; \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) \
+ $(RUNTESTFLAGS); \
+ if [ -n "$*" ]; then \
+ touch $$GCC_RUNTEST_PARALLELIZE_DIR/finished; \
+ fi; \
+ else \
+ echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
+
distclean-DEJAGNU:
-rm -f site.exp site.bak
-l='$(PACKAGE)'; for tool in $$l; do \
diff --git a/libgomp/testsuite/Makefile.in b/libgomp/testsuite/Makefile.in
index 7a88f0f..d743e46 100644
--- a/libgomp/testsuite/Makefile.in
+++ b/libgomp/testsuite/Makefile.in
@@ -147,6 +147,7 @@ CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPU_COUNT = @CPU_COUNT@
+CXX = @CXX@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -161,6 +162,7 @@ EXEEXT = @EXEEXT@
FC = @FC@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
+FLOCK = @FLOCK@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -207,7 +209,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
RANLIB = @RANLIB@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
@@ -299,7 +300,20 @@ _RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \
echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+PWD_COMMAND = $${PWDCMD-pwd}
EXTRA_DEJAGNU_SITE_CONFIG = libgomp-site-extra.exp
+check_p_numbers0 := 1 2 3 4 5 6 7 8 9
+check_p_numbers1 := 0 $(check_p_numbers0)
+check_p_numbers2 := $(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers1)))
+check_p_numbers3 := $(addprefix 0,$(check_p_numbers1)) $(check_p_numbers2)
+check_p_numbers4 := $(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers3)))
+check_p_numbers5 := $(addprefix 0,$(check_p_numbers3)) $(check_p_numbers4)
+check_p_numbers6 := $(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers5)))
+check_p_numbers := $(check_p_numbers0) $(check_p_numbers2) $(check_p_numbers4) $(check_p_numbers6)
+# If unable to serialize execution testing, use just one parallel slot.
+gcc_test_parallel_slots := $(if $(FLOCK),$(if $(GCC_TEST_PARALLEL_SLOTS),$(GCC_TEST_PARALLEL_SLOTS),19),1)
+check_p_subdirs = $(wordlist 1,$(gcc_test_parallel_slots),$(check_p_numbers))
+check_DEJAGNU_libgomp_targets = $(addprefix check-DEJAGNUlibgomp,$(check_p_subdirs))
all: all-am
.SUFFIXES:
@@ -474,17 +488,6 @@ libgomp-test-support.exp: libgomp-test-support.pt.exp Makefile
'set offload_additional_lib_paths "$(offload_additional_lib_paths)"'
mv $@.tmp $@
-check-DEJAGNU: site.exp
- srcdir='$(srcdir)'; export srcdir; \
- EXPECT=$(EXPECT); export EXPECT; \
- if $(SHELL) -c "$(_RUNTEST) --version" > /dev/null 2>&1; then \
- exit_status=0; l='$(PACKAGE)'; for tool in $$l; do \
- if $(_RUNTEST) $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
- then :; else exit_status=1; fi; \
- done; \
- else echo "WARNING: could not find '$(_RUNTEST)'" 1>&2; :;\
- fi; \
- exit $$exit_status
site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
@echo 'Making a new site.exp file ...'
@echo '## these variables are automatically generated by make ##' >site.tmp
@@ -512,6 +515,59 @@ site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
@test ! -f site.exp || mv site.exp site.bak
@mv site.tmp site.exp
+%/site.exp: site.exp
+ -@test -d $* || mkdir $*
+ @srcdir=`cd $(srcdir); ${PWD_COMMAND}`;
+ @objdir=`${PWD_COMMAND}`/$*; \
+ sed -e "s|^set srcdir .*$$|set srcdir $$srcdir|" \
+ -e "s|^set objdir .*$$|set objdir $$objdir|" \
+ site.exp > $*/site.exp.tmp
+ @-rm -f $*/site.bak
+ @test ! -f $*/site.exp || mv $*/site.exp $*/site.bak
+ @mv $*/site.exp.tmp $*/site.exp
+$(check_DEJAGNU_libgomp_targets): check-DEJAGNUlibgomp%: libgomp%/site.exp
+
+check-DEJAGNU $(check_DEJAGNU_libgomp_targets): check-DEJAGNU%: site.exp
+ $(if $*,@)AR="$(AR)"; export AR; \
+ RANLIB="$(RANLIB)"; export RANLIB; \
+ if [ -z "$*" ] && [ -n "$(filter -j%, $(MFLAGS))" ]; then \
+ rm -rf libgomp-parallel || true; \
+ mkdir libgomp-parallel; \
+ $(MAKE) $(AM_MAKEFLAGS) $(check_DEJAGNU_libgomp_targets); \
+ rm -rf libgomp-parallel || true; \
+ for idx in $(check_p_subdirs); do \
+ if [ -d libgomp$$idx ]; then \
+ mv -f libgomp$$idx/libgomp.sum libgomp$$idx/libgomp.sum.sep; \
+ mv -f libgomp$$idx/libgomp.log libgomp$$idx/libgomp.log.sep; \
+ fi; \
+ done; \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh \
+ libgomp[0-9]*/libgomp.sum.sep > libgomp.sum; \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh -L \
+ libgomp[0-9]*/libgomp.log.sep > libgomp.log; \
+ exit 0; \
+ fi; \
+ srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \
+ EXPECT=$(EXPECT); export EXPECT; \
+ runtest=$(_RUNTEST); \
+ if [ -z "$$runtest" ]; then runtest=runtest; fi; \
+ tool=libgomp; \
+ if [ -n "$*" ]; then \
+ if [ -f libgomp-parallel/finished ]; then rm -rf "$*"; exit 0; fi; \
+ GCC_RUNTEST_PARALLELIZE_DIR=`${PWD_COMMAND}`/libgomp-parallel; \
+ export GCC_RUNTEST_PARALLELIZE_DIR; \
+ cd "$*"; \
+ fi; \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) \
+ $(RUNTESTFLAGS); \
+ if [ -n "$*" ]; then \
+ touch $$GCC_RUNTEST_PARALLELIZE_DIR/finished; \
+ fi; \
+ else \
+ echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
+
distclean-DEJAGNU:
-rm -f site.exp site.bak
-l='$(PACKAGE)'; for tool in $$l; do \
diff --git a/libgomp/testsuite/config/default.exp b/libgomp/testsuite/config/default.exp
index b7afc82..01569e6 100644
--- a/libgomp/testsuite/config/default.exp
+++ b/libgomp/testsuite/config/default.exp
@@ -13,5 +13,3 @@
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-
-load_lib "standard.exp"
diff --git a/libgomp/testsuite/flock b/libgomp/testsuite/flock
new file mode 100755
index 0000000..71878b1
--- /dev/null
+++ b/libgomp/testsuite/flock
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+# Only arguments '--exclusive 1' exactly are supported.
+(@ARGV == 2) or die;
+my $mode = shift;
+($mode eq "--exclusive") or die;
+my $fd = shift;
+($fd eq "1") or die;
+
+use Fcntl ':flock';
+
+open(my $fh, '>&=', 1) or die "open: $!";
+
+flock($fh, LOCK_EX) or die "flock: $!";
diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index e12236e..2f9e538 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -9,6 +9,7 @@ proc load_gcc_lib { filename } {
}
load_lib dg.exp
+load_lib standard.exp
# Required to use gcc-dg.exp - however, the latter should NOT be
# loaded until ${tool}_target_compile is defined since it uses that
@@ -42,14 +43,15 @@ load_gcc_lib torture-options.exp
load_gcc_lib fortran-modules.exp
# Try to load a test support file, built during libgomp configuration.
-load_file libgomp-test-support.exp
+# Search in '..' vs. '.' to support parallel vs. sequential testing.
+if [info exists ::env(GCC_RUNTEST_PARALLELIZE_DIR)] {
+ load_file ../libgomp-test-support.exp
+} else {
+ load_file libgomp-test-support.exp
+}
set dg-do-what-default run
-#
-# GCC_UNDER_TEST is the compiler under test.
-#
-
set libgomp_compile_options ""
#
@@ -66,12 +68,11 @@ proc libgomp_init { args } {
global srcdir blddir objdir tool_root_dir
global libgomp_initialized
global tmpdir
- global blddir
global gluefile wrap_flags
global ALWAYS_CFLAGS
global CFLAGS
global TOOL_EXECUTABLE TOOL_OPTIONS
- global GCC_UNDER_TEST
+ global GCC_UNDER_TEST GXX_UNDER_TEST GFORTRAN_UNDER_TEST
global TESTING_IN_BUILD_TREE
global target_triplet
global always_ld_library_path
@@ -90,12 +91,45 @@ proc libgomp_init { args } {
setenv LANG C.ASCII
}
+ if { $blddir != "" } {
+ # Fix up '-funconfigured-libstdc++-v3' in 'GXX_UNDER_TEST' (see
+ # '../../configure.ac').
+ set flags_file "${blddir}/../libstdc++-v3/scripts/testsuite_flags"
+ if { [file exists $flags_file] } {
+ set flags [exec sh $flags_file --build-includes]
+ verbose -log "GXX_UNDER_TEST = $GXX_UNDER_TEST"
+ set GXX_UNDER_TEST [string map [list \
+ " -funconfigured-libstdc++-v3 " " $flags " \
+ ] $GXX_UNDER_TEST]
+ verbose -log "GXX_UNDER_TEST = $GXX_UNDER_TEST"
+ }
+ }
if ![info exists GCC_UNDER_TEST] then {
if [info exists TOOL_EXECUTABLE] {
set GCC_UNDER_TEST $TOOL_EXECUTABLE
} else {
set GCC_UNDER_TEST "[find_gcc]"
}
+ # Only if we're guessing 'GCC_UNDER_TEST', we're also going to guess
+ # 'GXX_UNDER_TEST', 'GFORTRAN_UNDER_TEST'.
+ if ![info exists GXX_UNDER_TEST] then {
+ if [info exists TOOL_EXECUTABLE] {
+ set GXX_UNDER_TEST $TOOL_EXECUTABLE
+ } else {
+ set GXX_UNDER_TEST "[find_g++]"
+ }
+ } else {
+ error "GXX_UNDER_TEST set but not GCC_UNDER_TEST"
+ }
+ if ![info exists GFORTRAN_UNDER_TEST] then {
+ if [info exists TOOL_EXECUTABLE] {
+ set GFORTRAN_UNDER_TEST $TOOL_EXECUTABLE
+ } else {
+ set GFORTRAN_UNDER_TEST "[find_gfortran]"
+ }
+ } else {
+ error "GFORTRAN_UNDER_TEST set but not GCC_UNDER_TEST"
+ }
}
if ![info exists tmpdir] {
@@ -118,7 +152,7 @@ proc libgomp_init { args } {
}
# Compute what needs to be put into LD_LIBRARY_PATH
- set always_ld_library_path ".:${blddir}/.libs"
+ set always_ld_library_path "."
global offload_additional_lib_paths
if { $offload_additional_lib_paths != "" } {
@@ -157,6 +191,8 @@ proc libgomp_init { args } {
lappend ALWAYS_CFLAGS "additional_flags=-B${blddir}/.libs"
lappend ALWAYS_CFLAGS "additional_flags=-I${blddir}"
lappend ALWAYS_CFLAGS "ldflags=-L${blddir}/.libs"
+
+ append always_ld_library_path ":${blddir}/.libs"
}
# The top-level include directory, for gomp-constants.h.
lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/../../include"
@@ -233,25 +269,26 @@ proc libgomp_target_compile { source dest type options } {
global gluefile wrap_flags
global ALWAYS_CFLAGS
global GCC_UNDER_TEST
- global lang_test_file
- global lang_library_path
- global lang_link_flags
- global lang_include_flags
- global lang_source_re
-
- if { [info exists lang_test_file] } {
- if { $blddir != "" } {
- # Some targets use libgfortran.a%s in their specs, so they need
- # a -B option for uninstalled testing.
- lappend options "additional_flags=-B${blddir}/${lang_library_path}"
- lappend options "ldflags=-L${blddir}/${lang_library_path}"
- }
- lappend options "ldflags=${lang_link_flags}"
- if { [info exists lang_include_flags] \
- && [regexp ${lang_source_re} ${source}] } {
- lappend options "additional_flags=${lang_include_flags}"
+
+ global lang_source_re lang_include_flags
+ if { [info exists lang_include_flags] \
+ && [regexp ${lang_source_re} ${source}] } {
+ lappend options "additional_flags=${lang_include_flags}"
+ }
+
+ global lang_library_paths
+ if { [info exists lang_library_paths] } {
+ foreach lang_library_path $lang_library_paths {
+ # targets that use lib[...].a%s in their specs need a -B option
+ # for uninstalled testing.
+ lappend options "additional_flags=-B${blddir}/${lang_library_path}"
+ lappend options "ldflags=-L${blddir}/${lang_library_path}"
}
}
+ global lang_link_flags
+ if { [info exists lang_link_flags] } {
+ lappend options "ldflags=${lang_link_flags}"
+ }
if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
lappend options "libs=${gluefile}"
@@ -260,7 +297,6 @@ proc libgomp_target_compile { source dest type options } {
lappend options "additional_flags=[libio_include_flags]"
lappend options "timeout=[timeout_value]"
- lappend options "compiler=$GCC_UNDER_TEST"
set options [concat $libgomp_compile_options $options]
@@ -292,6 +328,36 @@ proc libgomp_option_proc { option } {
}
}
+if ![info exists ::env(GCC_RUNTEST_PARALLELIZE_DIR)] {
+ # No parallel testing.
+} elseif { $FLOCK == "" } {
+ # Using just one parallel slot.
+} else {
+ # Using several parallel slots. Override DejaGnu
+ # 'standard.exp:${tool}_load'...
+ rename libgomp_load standard_libgomp_load
+ proc libgomp_load { program args } {
+ # ... in order to serialize execution testing via an exclusive lock.
+ # We use stdout, as per <https://perldoc.perl.org/functions/flock>
+ # "[...] FILEHANDLE [...] be open with write intent to use LOCK_EX".
+ set lock_file ../lock
+ set lock_kind --exclusive
+ set lock_fd [open $lock_file a+]
+ set lock_clock_begin [clock seconds]
+ global FLOCK
+ exec $FLOCK $lock_kind 1 >@ $lock_fd
+ set lock_clock_end [clock seconds]
+ verbose -log "Got ${FLOCK}('$lock_file', '$lock_kind') at [clock format $lock_clock_end] after [expr $lock_clock_end - $lock_clock_begin] s" 2
+
+ set result [standard_libgomp_load $program $args]
+
+ # Unlock (implicit with 'close').
+ close $lock_fd
+
+ return $result
+ }
+}
+
# Translate offload target to OpenACC device type. Return the empty string if
# not supported, and 'host' for offload target 'disable'.
proc offload_target_to_openacc_device_type { offload_target } {
diff --git a/libgomp/testsuite/libgomp-site-extra.exp.in b/libgomp/testsuite/libgomp-site-extra.exp.in
index c0d2666..c824d85 100644
--- a/libgomp/testsuite/libgomp-site-extra.exp.in
+++ b/libgomp/testsuite/libgomp-site-extra.exp.in
@@ -1 +1,4 @@
+set FLOCK {@FLOCK@}
set GCC_UNDER_TEST {@CC@}
+set GXX_UNDER_TEST {@CXX@}
+set GFORTRAN_UNDER_TEST {@FC@}
diff --git a/libgomp/testsuite/libgomp.c++/c++.exp b/libgomp/testsuite/libgomp.c++/c++.exp
index f4884e2..8b4563b 100644
--- a/libgomp/testsuite/libgomp.c++/c++.exp
+++ b/libgomp/testsuite/libgomp.c++/c++.exp
@@ -1,15 +1,21 @@
load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
-global shlib_ext
-
-set shlib_ext [get_shlib_extension]
-set lang_link_flags "-lstdc++"
-set lang_test_file_found 0
-set lang_library_path "../libstdc++-v3/src/.libs"
-if [info exists lang_include_flags] then {
- unset lang_include_flags
+if { $blddir != "" } {
+ set libstdc++_library_path "../libstdc++-v3/src/.libs"
+ set shlib_ext [get_shlib_extension]
+ if { ![file exists "${blddir}/${libstdc++_library_path}/libstdc++.a"]
+ && ![file exists "${blddir}/${libstdc++_library_path}/libstdc++.${shlib_ext}"] } {
+ verbose -log "No libstdc++ library found, will not execute c++ tests"
+ unset libstdc++_library_path
+ return
+ }
+ lappend lang_library_paths ${libstdc++_library_path}
+} elseif { ![info exists GXX_UNDER_TEST] } {
+ verbose -log "GXX_UNDER_TEST not defined, will not execute c++ tests"
+ return
}
+lappend ALWAYS_CFLAGS "compiler=$GXX_UNDER_TEST"
# If a testcase doesn't have special options, use these.
if ![info exists DEFAULT_CFLAGS] then {
@@ -22,61 +28,25 @@ dg-init
# Turn on OpenMP.
lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
-# Switch into C++ mode. Otherwise, the libgomp.c-c++-common/*.c
-# files would be compiled as C files.
-set SAVE_GCC_UNDER_TEST "$GCC_UNDER_TEST"
-set GCC_UNDER_TEST "$GCC_UNDER_TEST -x c++"
-
-set blddir [lookfor_file [get_multilibs] libgomp]
-
+# Gather a list of all tests.
+set tests [lsort [concat \
+ [find $srcdir/$subdir *.C] \
+ [find $srcdir/$subdir/../libgomp.c-c++-common *.c]]]
+set ld_library_path $always_ld_library_path
if { $blddir != "" } {
- # Look for a static libstdc++ first.
- if [file exists "${blddir}/${lang_library_path}/libstdc++.a"] {
- set lang_test_file "${lang_library_path}/libstdc++.a"
- set lang_test_file_found 1
- # We may have a shared only build, so look for a shared libstdc++.
- } elseif [file exists "${blddir}/${lang_library_path}/libstdc++.${shlib_ext}"] {
- set lang_test_file "${lang_library_path}/libstdc++.${shlib_ext}"
- set lang_test_file_found 1
- } else {
- puts "No libstdc++ library found, will not execute c++ tests"
- }
-} elseif { [info exists GXX_UNDER_TEST] } {
- set lang_test_file_found 1
- # Needs to exist for libgomp.exp.
- set lang_test_file ""
-} else {
- puts "GXX_UNDER_TEST not defined, will not execute c++ tests"
+ append ld_library_path ":${blddir}/${libstdc++_library_path}"
}
+append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
+set_ld_library_path_env_vars
-if { $lang_test_file_found } {
- # Gather a list of all tests.
- set tests [lsort [concat \
- [find $srcdir/$subdir *.C] \
- [find $srcdir/$subdir/../libgomp.c-c++-common *.c]]]
+# Main loop.
+dg-runtest $tests "" $DEFAULT_CFLAGS
- if { $blddir != "" } {
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}"
- } else {
- set ld_library_path "$always_ld_library_path"
- }
- append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
- set_ld_library_path_env_vars
-
- set flags_file "${blddir}/../libstdc++-v3/scripts/testsuite_flags"
- if { [file exists $flags_file] } {
- set libstdcxx_includes [exec sh $flags_file --build-includes]
- } else {
- set libstdcxx_includes ""
- }
-
- # Main loop.
- dg-runtest $tests "" "$libstdcxx_includes $DEFAULT_CFLAGS"
+if { $blddir != "" } {
+ unset libstdc++_library_path
+ unset lang_library_paths
}
-# See above.
-set GCC_UNDER_TEST "$SAVE_GCC_UNDER_TEST"
-
# All done.
dg-finish
diff --git a/libgomp/testsuite/libgomp.c++/target-18.C b/libgomp/testsuite/libgomp.c++/target-18.C
index f1085b1..a21ed4e 100644
--- a/libgomp/testsuite/libgomp.c++/target-18.C
+++ b/libgomp/testsuite/libgomp.c++/target-18.C
@@ -20,7 +20,9 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -37,7 +39,9 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -55,7 +59,9 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -91,7 +97,8 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
@@ -110,7 +117,8 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
@@ -130,7 +138,8 @@ foo (int *&p, int *&q, int *&r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
diff --git a/libgomp/testsuite/libgomp.c++/target-19.C b/libgomp/testsuite/libgomp.c++/target-19.C
index afa6e68..7bae31d 100644
--- a/libgomp/testsuite/libgomp.c++/target-19.C
+++ b/libgomp/testsuite/libgomp.c++/target-19.C
@@ -1,3 +1,8 @@
+/* { dg-additional-options "-O0" } */
+/* Disable optimization to ensure that the compiler does not exploit that
+ S::r + t will never be NULL due to int (&r) and (&t). */
+
+
extern "C" void abort ();
struct S { char a[64]; int (&r)[2]; char b[64]; };
@@ -19,7 +24,9 @@ foo (S s, int (&t)[3], int z)
#pragma omp target map(from: err) map(tofrom: s.r[:0], t[:0])
{
if (sep)
- err = s.r != (int *) 0 || t != (int *) 0;
+ /* Since OpenMP 5.2, if no matching mapped list it has been found,
+ pointers retain their original value. */
+ err = s.r == (int *) 0 || t == (int *) 0;
else
err = t[0] != 1 || t[1] != 2 || t[2] != 3 || s.r[0] != 6 || s.r[1] != 7;
}
@@ -28,7 +35,9 @@ foo (S s, int (&t)[3], int z)
#pragma omp target map(from: err) map(tofrom: s.r[:z], t[:z])
{
if (sep)
- err = s.r != (int *) 0 || t != (int *) 0;
+ /* Since OpenMP 5.2, if no matching mapped list it has been found,
+ pointers retain their original value. */
+ err = s.r == (int *) 0 || t == (int *) 0;
else
err = t[0] != 1 || t[1] != 2 || t[2] != 3 || s.r[0] != 6 || s.r[1] != 7;
}
diff --git a/libgomp/testsuite/libgomp.c++/target-map-class-1.C b/libgomp/testsuite/libgomp.c++/target-map-class-1.C
new file mode 100644
index 0000000..ad4802d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-map-class-1.C
@@ -0,0 +1,98 @@
+/* PR middle-end/109816 */
+
+/* This variant: without -flto, see target-map-class-2.C for -flto. */
+
+/* iostream.h adds 'globl _ZSt21ios_base_library_initv' with _GLIBCXX_SYMVER_GNU,
+ but it shouldn't end up in the offload assembly but only in the host assembly. */
+
+/* Example based on sollve_vv's test_target_data_map_classes.cpp; however,
+ relevant is only the 'include' and not the actual executable code. */
+
+#include <iostream>
+#include <omp.h>
+
+using namespace std;
+
+#define N 1000
+
+struct A
+{
+ int *h_array;
+ int size, sum;
+
+ A (int *array, const int s) : h_array(array), size(s), sum(0) { }
+ ~A() { h_array = NULL; }
+};
+
+void
+test_map_tofrom_class_heap ()
+{
+ int *array = new int[N];
+ A *obj = new A (array, N);
+
+ #pragma omp target map(from: array[:N]) map(tofrom: obj[:1])
+ {
+ int *tmp_h_array = obj->h_array;
+ obj->h_array = array;
+ int tmp = 0;
+ for (int i = 0; i < N; ++i)
+ {
+ obj->h_array[i] = 4*i;
+ tmp += 3;
+ }
+ obj->h_array = tmp_h_array;
+ obj->sum = tmp;
+ }
+
+ for (int i = 0; i < N; ++i)
+ if (obj->h_array[i] != 4*i)
+ __builtin_abort ();
+
+ if (3*N != obj->sum)
+ {
+ std::cout << "sum: " << obj->sum << std::endl;
+ __builtin_abort ();
+ }
+
+ delete obj;
+ delete[] array;
+}
+
+void
+test_map_tofrom_class_stack ()
+{
+ int array[N];
+ A obj(array, N);
+
+ #pragma omp target map(from: array[:N]) map(tofrom: obj)
+ {
+ int *tmp_h_array = obj.h_array;
+ obj.h_array = array;
+ int tmp = 0;
+ for (int i = 0; i < N; ++i)
+ {
+ obj.h_array[i] = 7*i;
+ tmp += 5;
+ }
+ obj.h_array = tmp_h_array;
+ obj.sum = tmp;
+ }
+
+ for (int i = 0; i < N; ++i)
+ if (obj.h_array[i] != 7*i)
+ __builtin_abort ();
+
+ if (5*N != obj.sum)
+ {
+ std::cout << "sum: " << obj.sum << std::endl;
+ __builtin_abort ();
+ }
+}
+
+int
+main()
+{
+ test_map_tofrom_class_heap();
+ test_map_tofrom_class_stack();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/target-map-class-2.C b/libgomp/testsuite/libgomp.c++/target-map-class-2.C
new file mode 100644
index 0000000..1ef20f7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-map-class-2.C
@@ -0,0 +1,6 @@
+/* { dg-additional-options "-flto" } */
+/* PR middle-end/109816 */
+
+/* This variant: with -flto, see target-map-class-1.C for without -flto. */
+
+#include "target-map-class-1.C"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-1.c b/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-1.c
new file mode 100644
index 0000000..bff0a6b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-1.c
@@ -0,0 +1,74 @@
+/* PR libgomp/109837 */
+
+#include <assert.h>
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#pragma omp requires unified_address
+
+#define N 15
+
+void
+test_device (int dev)
+{
+ struct st {
+ int *ptr;
+ int n;
+ };
+ struct st s;
+
+ s.n = 10;
+ s.ptr = (int *) omp_target_alloc (sizeof (int)*s.n, dev);
+ int *ptr1 = (int *) omp_target_alloc (sizeof (int)*N, dev);
+ assert (s.ptr != NULL);
+ assert (ptr1 != NULL);
+
+ int q[4] = {1,2,3,4};
+ int *qptr;
+ #pragma omp target enter data map(q) device(device_num: dev)
+ #pragma omp target data use_device_addr(q) device(device_num: dev)
+ qptr = q;
+
+ #pragma omp target map(to:s) device(device_num: dev)
+ for (int i = 0; i < s.n; i++)
+ s.ptr[i] = 23*i;
+
+ int *ptr2 = &s.ptr[3];
+
+ #pragma omp target firstprivate(qptr) map(tofrom:ptr2) device(device_num: dev)
+ for (int i = 0; i < 4; i++)
+ *(qptr++) = ptr2[i];
+
+ #pragma omp target exit data map(q) device(device_num: dev)
+ for (int i = 0; i < 4; i++)
+ q[i] = 23 * (i+3);
+
+ #pragma omp target map(to: ptr1) device(device_num: dev)
+ for (int i = 0; i < N; i++)
+ ptr1[i] = 11*i;
+
+ int *ptr3 = (int *) malloc (sizeof (int)*N);
+ assert (0 == omp_target_memcpy(ptr3, ptr1, N * sizeof(int), 0, 0,
+ omp_get_initial_device(), dev));
+ for (int i = 0; i < N; i++)
+ assert (ptr3[i] == 11*i);
+
+ free (ptr3);
+ omp_target_free (ptr1, dev);
+ omp_target_free (s.ptr, dev);
+}
+
+int
+main()
+{
+ int ntgts = omp_get_num_devices();
+ if (ntgts)
+ fprintf (stderr, "Offloading devices exist\n"); /* { dg-output "Offloading devices exist(\n|\r\n|\r)" { target offload_device } } */
+ else
+ fprintf (stderr, "Only host fallback\n"); /* { dg-output "Only host fallback(\n|\r\n|\r)" { target { ! offload_device } } } */
+
+ for (int i = 0; i <= ntgts; i++)
+ test_device (i);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-2.c b/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-2.c
new file mode 100644
index 0000000..3b5dcd3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/requires-unified-addr-2.c
@@ -0,0 +1,85 @@
+/* PR middle-end/110270 */
+
+/* OpenMP 5.2's 'defaultmap(default : pointer) for C/C++ pointers retains the
+ pointer value instead of setting it to NULL if the pointer cannot be found.
+ Contrary to requires-unified-addr-1.c which is valid OpenMP 5.0/5.1/5.2,
+ this testcase is only valid since OpenMP 5.2. */
+
+/* This is kind of a follow-up to the requires-unified-addr-1.c testcase
+ and PR libgomp/109837 */
+
+
+#include <assert.h>
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#pragma omp requires unified_address
+
+#define N 15
+
+void
+test_device (int dev)
+{
+ struct st {
+ int *ptr;
+ int n;
+ };
+ struct st s;
+
+ s.n = 10;
+ s.ptr = (int *) omp_target_alloc (sizeof (int)*s.n, dev);
+ int *ptr1 = (int *) omp_target_alloc (sizeof (int)*N, dev);
+ assert (s.ptr != NULL);
+ assert (ptr1 != NULL);
+
+ int q[4] = {1,2,3,4};
+ int *qptr;
+ #pragma omp target enter data map(q) device(device_num: dev)
+ #pragma omp target data use_device_addr(q) device(device_num: dev)
+ qptr = q;
+
+ #pragma omp target map(to:s) device(device_num: dev)
+ for (int i = 0; i < s.n; i++)
+ s.ptr[i] = 23*i;
+
+ int *ptr2 = &s.ptr[3];
+
+ /* s.ptr is not mapped (but omp_target_alloc'ed) thus ptr2 shall retain its value. */
+ #pragma omp target device(device_num: dev) /* implied: defaultmap(default : pointer) */
+ for (int i = 0; i < 4; i++)
+ *(qptr++) = ptr2[i];
+
+ #pragma omp target exit data map(q) device(device_num: dev)
+ for (int i = 0; i < 4; i++)
+ q[i] = 23 * (i+3);
+
+ /* ptr1 retains the value as it is not mapped (but it is omp_target_alloc'ed). */
+ #pragma omp target defaultmap(default : pointer) device(device_num: dev)
+ for (int i = 0; i < N; i++)
+ ptr1[i] = 11*i;
+
+ int *ptr3 = (int *) malloc (sizeof (int)*N);
+ assert (0 == omp_target_memcpy(ptr3, ptr1, N * sizeof(int), 0, 0,
+ omp_get_initial_device(), dev));
+ for (int i = 0; i < N; i++)
+ assert (ptr3[i] == 11*i);
+
+ free (ptr3);
+ omp_target_free (ptr1, dev);
+ omp_target_free (s.ptr, dev);
+}
+
+int
+main()
+{
+ int ntgts = omp_get_num_devices();
+ if (ntgts)
+ fprintf (stderr, "Offloading devices exist\n"); /* { dg-output "Offloading devices exist(\n|\r\n|\r)" { target offload_device } } */
+ else
+ fprintf (stderr, "Only host fallback\n"); /* { dg-output "Only host fallback(\n|\r\n|\r)" { target { ! offload_device } } } */
+
+ for (int i = 0; i <= ntgts; i++)
+ test_device (i);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/scan-1.c b/libgomp/testsuite/libgomp.c-c++-common/scan-1.c
new file mode 100644
index 0000000..d1951a3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/scan-1.c
@@ -0,0 +1,68 @@
+#define N 30
+#define M 3
+
+int a[N][M], b[N][M], c[N][M];
+
+int
+main()
+{
+ int x, y, shift;
+ int j = 0;
+ for (int i = 0; i < N; i++)
+ {
+ a[i][0] = (i+1)*32;
+ a[i][1] = (i+1)*17;
+ a[i][2] = (i+1)*11;
+ b[i][0] = (i+1)*7;
+ b[i][1] = (i+1)*5;
+ b[i][2] = (i+1)*3;
+ }
+
+ x = 0;
+ #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < M; j++)
+ {
+ x += a[i][j];
+ x += b[i][j];
+ #pragma omp scan inclusive(x)
+ shift = i + 29*j;
+ c[i][j] = x + shift;
+ }
+
+ y = 0;
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < M; j++)
+ {
+ y += a[i][j] + b[i][j];
+ if (c[i][j] != y + i + 29*j)
+ __builtin_abort ();
+ }
+ if (x != y)
+ __builtin_abort ();
+
+ x = 0;
+ #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < M; j++)
+ {
+ shift = i + 29*j;
+ c[i][j] = x + shift;
+ #pragma omp scan exclusive(x)
+ x += a[i][j];
+ x += b[i][j];
+ }
+
+ y = 0;
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < M; j++)
+ {
+ if (c[i][j] != y + i + 29*j)
+ __builtin_abort ();
+ y += a[i][j] + b[i][j];
+ }
+ if (x != y)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-3.c b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-3.c
new file mode 100644
index 0000000..863cf0e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-3.c
@@ -0,0 +1,105 @@
+/* PR middle-end/110270 */
+
+/* Ensure that defaultmap(default : pointer) uses correct OpenMP 5.2
+ semantic, i.e. keeping the pointer value even if not mapped;
+ before OpenMP 5.0/5.1 required that it is NULL, causing issues
+ especially with unified-shared memory but also the code below
+ shows why that's not a good idea. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <omp.h>
+
+/* 'unified_address' is required by the OpenMP spec as only then
+ 'is_device_ptr' can be left out. All our devices support this
+ while remote offloading would not. However, in practice it is
+ sufficient that the host and device pointer size is the same
+ (or the device pointer is smaller) - and then a device pointer is
+ representable and omp_target_alloc can return a bare device pointer.
+
+ We here assume that this weaker condition holds and do not
+ require: #pragma omp requires unified_address */
+
+void
+test_device (int dev)
+{
+ int *p1 = (int*) 0x12345;
+ int *p1a = (int*) 0x67890;
+ int *p2 = (int*) omp_target_alloc (sizeof (int) * 5, dev);
+ int *p2a = (int*) omp_target_alloc (sizeof (int) * 10, dev);
+ intptr_t ip = (intptr_t) p2;
+ intptr_t ipa = (intptr_t) p2a;
+
+ int A[3] = {1,2,3};
+ int B[5] = {4,5,6,7,8};
+ int *p3 = &A[0];
+ int *p3a = &B[0];
+
+ #pragma omp target enter data map(to:A) device(dev)
+
+ #pragma omp target device(dev) /* defaultmap(default:pointer) */
+ {
+ /* The pointees aren't mapped. */
+ /* OpenMP 5.2 -> same value as before the target region. */
+ if ((intptr_t) p1 != 0x12345) __builtin_abort ();
+ if ((intptr_t) p2 != ip) __builtin_abort ();
+ for (int i = 0; i < 5; i++)
+ p2[i] = 13*i;
+
+ for (int i = 0; i < 10; i++)
+ ((int *)ipa)[i] = 7*i;
+
+ /* OpenMP: Mapped => must point to the corresponding device storage of 'A' */
+ if (p3[0] != 1 || p3[1] != 2 || p3[2] != 3)
+ __builtin_abort ();
+ p3[0] = -11; p3[1] = -22; p3[2] = -33;
+ }
+ #pragma omp target exit data map(from:A) device(dev)
+
+ if (p3[0] != -11 || p3[1] != -22 || p3[2] != -33)
+ __builtin_abort ();
+
+ // With defaultmap:
+
+ #pragma omp target enter data map(to:B) device(dev)
+
+ #pragma omp target device(dev) defaultmap(default:pointer)
+ {
+ /* The pointees aren't mapped. */
+ /* OpenMP 5.2 -> same value as before the target region. */
+ if ((intptr_t) p1a != 0x67890) __builtin_abort ();
+ if ((intptr_t) p2a != ipa) __builtin_abort ();
+
+ for (int i = 0; i < 5; i++)
+ ((int *)ip)[i] = 13*i;
+
+ for (int i = 0; i < 10; i++)
+ p2a[i] = 7*i;
+
+ /* OpenMP: Mapped => must point to the corresponding device storage of 'B' */
+ if (p3a[0] != 4 || p3a[1] != 5 || p3a[2] != 6 || p3a[3] != 7 || p3a[4] != 8)
+ __builtin_abort ();
+ p3a[0] = -44; p3a[1] = -55; p3a[2] = -66; p3a[3] = -77; p3a[4] = -88;
+ }
+ #pragma omp target exit data map(from:B) device(dev)
+
+ if (p3a[0] != -44 || p3a[1] != -55 || p3a[2] != -66 || p3a[3] != -77 || p3a[4] != -88)
+ __builtin_abort ();
+
+ omp_target_free (p2, dev);
+ omp_target_free (p2a, dev);
+}
+
+int
+main()
+{
+ int ntgts = omp_get_num_devices();
+ if (ntgts)
+ fprintf (stderr, "Offloading devices exist\n"); /* { dg-output "Offloading devices exist(\n|\r\n|\r)" { target offload_device } } */
+ else
+ fprintf (stderr, "Only host fallback\n"); /* { dg-output "Only host fallback(\n|\r\n|\r)" { target { ! offload_device } } } */
+
+ for (int i = 0; i <= ntgts; i++)
+ test_device (i);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c
new file mode 100644
index 0000000..d0b0cd1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c
@@ -0,0 +1,159 @@
+/* PR middle-end/110270 */
+
+/* Same as target-implicit-map-3.c but uses the following requiement
+ and for not mapping the stack variables 'A' and 'B' (not mapped
+ but accessible -> USM makes this tested feature even more important.) */
+
+#pragma omp requires unified_shared_memory
+
+/* Ensure that defaultmap(default : pointer) uses correct OpenMP 5.2
+ semantic, i.e. keeping the pointer value even if not mapped;
+ before OpenMP 5.0/5.1 required that it is NULL. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <omp.h>
+
+void
+test_device (int dev)
+{
+ int *p1 = (int*) 0x12345;
+ int *p1a = (int*) 0x67890;
+ int *p2 = (int*) omp_target_alloc (sizeof (int) * 5, dev);
+ int *p2a = (int*) omp_target_alloc (sizeof (int) * 10, dev);
+ intptr_t ip = (intptr_t) p2;
+ intptr_t ipa = (intptr_t) p2a;
+
+ int A[3] = {1,2,3};
+ int B[5] = {4,5,6,7,8};
+ int *p3 = &A[0];
+ int *p3a = &B[0];
+
+ const omp_alloctrait_t traits[]
+ = { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 }};
+ omp_allocator_handle_t a = omp_init_allocator (omp_default_mem_space, 2, traits);
+
+ int *p4 = (int*) malloc (sizeof (int) * 5);
+ int *p4a = (int*) omp_alloc (sizeof (int) * 10, a);
+ intptr_t ip4 = (intptr_t) p4;
+ intptr_t ip4a = (intptr_t) p4a;
+
+ for (int i = 0; i < 5; i++)
+ p4[i] = -31*i;
+
+ for (int i = 0; i < 10; i++)
+ p4a[i] = -43*i;
+
+ /* Note: 'A' is not mapped but USM accessible. */
+ #pragma omp target device(dev) /* defaultmap(default:pointer) */
+ {
+ /* The pointees aren't mapped. */
+ /* OpenMP 5.2 -> same value as before the target region. */
+ if ((intptr_t) p1 != 0x12345) abort ();
+ if ((intptr_t) p2 != ip) abort ();
+ for (int i = 0; i < 5; i++)
+ p2[i] = 13*i;
+
+ for (int i = 0; i < 10; i++)
+ ((int *)ipa)[i] = 7*i;
+
+ /* OpenMP: Points to 'A'. */
+ if (p3[0] != 1 || p3[1] != 2 || p3[2] != 3)
+ abort ();
+ p3[0] = -11; p3[1] = -22; p3[2] = -33;
+
+ /* USM accesible allocated host memory. */
+ if ((intptr_t) p4 != ip4)
+ abort ();
+ for (int i = 0; i < 5; i++)
+ if (p4[i] != -31*i)
+ abort ();
+ for (int i = 0; i < 10; i++)
+ if (((int *)ip4a)[i] != -43*i)
+ abort ();
+ for (int i = 0; i < 5; i++)
+ p4[i] = 9*i;
+ for (int i = 0; i < 10; i++)
+ ((int *)ip4a)[i] = 18*i;
+ }
+
+ if (p3[0] != -11 || p3[1] != -22 || p3[2] != -33)
+ abort ();
+
+ for (int i = 0; i < 5; i++)
+ if (p4[i] != 9*i)
+ abort ();
+ for (int i = 0; i < 10; i++)
+ if (p4a[i] != 18*i)
+ abort ();
+ for (int i = 0; i < 5; i++)
+ p4[i] = -77*i;
+ for (int i = 0; i < 10; i++)
+ p4a[i] = -65*i;
+
+ // With defaultmap:
+
+ /* Note: 'B' is not mapped but USM accessible. */
+ #pragma omp target device(dev) defaultmap(default:pointer)
+ {
+ /* The pointees aren't mapped. */
+ /* OpenMP 5.2 -> same value as before the target region. */
+ if ((intptr_t) p1a != 0x67890) abort ();
+ if ((intptr_t) p2a != ipa) abort ();
+
+ for (int i = 0; i < 5; i++)
+ ((int *)ip)[i] = 13*i;
+
+ for (int i = 0; i < 10; i++)
+ p2a[i] = 7*i;
+
+ /* USM accesible allocated host memory. */
+ if ((intptr_t) p4a != ip4a) abort ();
+
+ /* OpenMP: Points to 'B'. */
+ if (p3a[0] != 4 || p3a[1] != 5 || p3a[2] != 6 || p3a[3] != 7 || p3a[4] != 8)
+ abort ();
+ p3a[0] = -44; p3a[1] = -55; p3a[2] = -66; p3a[3] = -77; p3a[4] = -88;
+
+ /* USM accesible allocated host memory. */
+ if ((intptr_t) p4a != ip4a)
+ abort ();
+ for (int i = 0; i < 5; i++)
+ if (((int *)ip4)[i] != -77*i)
+ abort ();
+ for (int i = 0; i < 10; i++)
+ if (p4a[i] != -65*i)
+ abort ();
+ for (int i = 0; i < 5; i++)
+ p4[i] = 36*i;
+ for (int i = 0; i < 10; i++)
+ ((int *)ip4a)[i] = 4*i;
+ }
+
+ if (p3a[0] != -44 || p3a[1] != -55 || p3a[2] != -66 || p3a[3] != -77 || p3a[4] != -88)
+ abort ();
+
+ for (int i = 0; i < 5; i++)
+ if (p4[i] != 36*i)
+ abort ();
+ for (int i = 0; i < 10; i++)
+ if (p4a[i] != 4*i)
+ abort ();
+
+ omp_target_free (p2, dev);
+ omp_target_free (p2a, dev);
+ free (p4);
+ omp_free (p4a, a);
+ omp_destroy_allocator (a);
+}
+
+int
+main()
+{
+ int ntgts = omp_get_num_devices();
+ for (int i = 0; i <= ntgts; i++)
+ test_device (i);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-present-1.c b/libgomp/testsuite/libgomp.c-c++-common/target-present-1.c
new file mode 100644
index 0000000..5eaa9cd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-present-1.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+
+#define N 100
+
+int main (void)
+{
+ int a[N], b[N], c[N], d[N];
+
+ for (int i = 0; i < N; i++) {
+ a[i] = i * 2;
+ b[i] = i * 3 + 1;
+ d[i] = i * 5;
+ }
+
+ #pragma omp target enter data map (alloc: c, d) map(to: a)
+ #pragma omp target map (present, always, to: d)
+ for (int i = 0; i < N; i++)
+ if (d[i] != i * 5)
+ __builtin_abort ();
+
+ /* a has already been mapped and 'c' allocated so this should be okay. */
+ #pragma omp target map (present, to: a) map(present, always, from: c)
+ for (int i = 0; i < N; i++)
+ c[i] = a[i];
+
+ for (int i = 0; i < N; i++)
+ if (c[i] != i * 2)
+ __builtin_abort ();
+
+ fprintf (stderr, "CheCKpOInT\n");
+ /* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
+
+ /* b has not been allocated, so this should result in an error. */
+ /* { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } } */
+ /* { dg-shouldfail "present error triggered" { offload_device_nonshared_as } } */
+ #pragma omp target map (present, to: b)
+ for (int i = 0; i < N; i++)
+ c[i] += b[i];
+ #pragma omp target exit data map (from: c)
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-present-2.c b/libgomp/testsuite/libgomp.c-c++-common/target-present-2.c
new file mode 100644
index 0000000..07ae90b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-present-2.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+#define N 100
+
+int main (void)
+{
+ int a[N], b[N], c[N];
+
+ for (int i = 0; i < N; i++) {
+ a[i] = i * 2;
+ b[i] = i * 3 + 1;
+ }
+
+ #pragma omp target enter data map (alloc: a, c)
+ /* a and c have already been allocated, so this should be okay. */
+ #pragma omp target defaultmap (present)
+ for (int i = 0; i < N; i++)
+ c[i] = a[i];
+
+ fprintf (stderr, "CheCKpOInT\n");
+ /* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
+
+ /* b has not been allocated, so this should result in an error. */
+ /* { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } } */
+ /* { dg-shouldfail "present error triggered" { offload_device_nonshared_as } } */
+ #pragma omp target defaultmap (present)
+ for (int i = 0; i < N; i++)
+ c[i] += b[i];
+ #pragma omp target exit data map (from: c)
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-present-3.c b/libgomp/testsuite/libgomp.c-c++-common/target-present-3.c
new file mode 100644
index 0000000..582247d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-present-3.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+#define N 100
+
+int main (void)
+{
+ int a[N], b[N], c[N];
+
+ for (int i = 0; i < N; i++) {
+ a[i] = i * 2;
+ b[i] = i * 3 + 1;
+ }
+
+ #pragma omp target enter data map (alloc: a, c)
+
+ /* This should work as a has already been allocated. */
+ #pragma omp target update to (present: a)
+
+ #pragma omp target map(present,alloc: a, c)
+ for (int i = 0; i < N; i++) {
+ if (a[i] != i * 2)
+ __builtin_abort ();
+ c[i] = 23*i;
+ }
+
+ #pragma omp target update from(present : c)
+ for (int i = 0; i < N; i++) {
+ if (c[i] != 23*i)
+ __builtin_abort ();
+ }
+
+ fprintf (stderr, "CheCKpOInT\n");
+ /* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
+
+ /* This should fail as b has not been allocated. */
+ /* { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } } */
+ /* { dg-shouldfail "present error triggered" { offload_device_nonshared_as } } */
+ #pragma omp target update to (present: b)
+
+ #pragma omp target exit data map (from: c)
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-1.c b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-1.c
new file mode 100644
index 0000000..c3c2109
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-1.c
@@ -0,0 +1,198 @@
+/* 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;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-2.c b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-2.c
new file mode 100644
index 0000000..7bd80de
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-2.c
@@ -0,0 +1,8 @@
+/* PR libgomp/109875 */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_ALL 9 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_DEV 7 } */
+
+#define MY_OMP_NUM_TEAMS_ALL 9
+#define MY_OMP_NUM_TEAMS_DEV 7
+
+#include "teams-nteams-icv-1.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-3.c b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-3.c
new file mode 100644
index 0000000..10a1cdc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-3.c
@@ -0,0 +1,8 @@
+/* PR libgomp/109875 */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_ALL 7 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS 8 } */
+
+#define MY_OMP_NUM_TEAMS_ALL 7
+#define MY_OMP_NUM_TEAMS 8
+
+#include "teams-nteams-icv-1.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-4.c b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-4.c
new file mode 100644
index 0000000..c5d6577
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/teams-nteams-icv-4.c
@@ -0,0 +1,14 @@
+/* PR libgomp/109875 */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_ALL 7 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS 4 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_DEV 8 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_DEV_0 5 } */
+/* { dg-set-target-env-var OMP_NUM_TEAMS_DEV_1 11 } */
+
+#define MY_OMP_NUM_TEAMS_ALL 7
+#define MY_OMP_NUM_TEAMS 4
+#define MY_OMP_NUM_TEAMS_DEV 8
+#define MY_OMP_NUM_TEAMS_DEV_0 5
+#define MY_OMP_NUM_TEAMS_DEV_1 11
+
+#include "teams-nteams-icv-1.c"
diff --git a/libgomp/testsuite/libgomp.c/allocator-1.c b/libgomp/testsuite/libgomp.c/allocator-1.c
new file mode 100644
index 0000000..2757792
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-1.c
@@ -0,0 +1,15 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_large_cap_mem_alloc" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = 'omp_large_cap_mem_alloc'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ if (m != omp_large_cap_mem_alloc)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/allocator-2.c b/libgomp/testsuite/libgomp.c/allocator-2.c
new file mode 100644
index 0000000..ac680e5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-2.c
@@ -0,0 +1,17 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_large_cap_mem_space" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* Expect omp_large_cap_mem_alloc as allocator for omp_large_cap_mem_space. */
+/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = 'omp_large_cap_mem_alloc'.*" } */
+#include <omp.h>
+
+int
+main ()
+{
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ /* Without traits, omp_large_cap_mem_space implies
+ omp_large_cap_mem_alloc. */
+ if (m != omp_large_cap_mem_alloc)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/allocator-3.c b/libgomp/testsuite/libgomp.c/allocator-3.c
new file mode 100644
index 0000000..a28f4e75
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-3.c
@@ -0,0 +1,27 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR " omp_default_mem_space:alignment=512,pinned=false,access=all " } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* We copied the environment string; hence, it may contain white space. */
+/* { dg-output ".\\\[host\\\] OMP_ALLOCATOR = ' omp_default_mem_space:alignment=512,pinned=false,access=all '.*" } */
+
+#include <stdint.h>
+#include <omp.h>
+
+int
+main ()
+{
+ int *a, *b;
+ a = omp_alloc (sizeof (int) * 1024, omp_null_allocator);
+
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ b = omp_alloc (sizeof (int) * 1024, m);
+
+ if ((uintptr_t) a % 512 != 0)
+ __builtin_abort ();
+
+ if ((uintptr_t) b % 512 != 0)
+ __builtin_abort ();
+ omp_free (a, omp_null_allocator);
+ omp_free (b, m);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/allocator-4.c b/libgomp/testsuite/libgomp.c/allocator-4.c
new file mode 100644
index 0000000..e5d0b09
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-4.c
@@ -0,0 +1,15 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_const_mem_space:alignment=3,pinned=" } */
+
+/* { dg-output ".*libgomp: Missing value at the end of environment variable OMP_ALLOCATOR=omp_const_mem_space:alignment=3,pinned=.*" } */
+/* OMP_ALLOCATOR syntax error -> use omp_default_mem_alloc. */
+
+#include <omp.h>
+
+int
+main ()
+{
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ if (m != omp_default_mem_alloc)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/allocator-5.c b/libgomp/testsuite/libgomp.c/allocator-5.c
new file mode 100644
index 0000000..0f900cf
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-5.c
@@ -0,0 +1,15 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_const_mem_space:access=none,pinned=false" } */
+
+/* { dg-output ".*libgomp: Invalid value for environment variable OMP_ALLOCATOR when parsing: none,pinned=false.*" } */
+/* OMP_ALLOCATOR syntax error -> use omp_default_mem_alloc. */
+
+#include <omp.h>
+
+int
+main ()
+{
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ if (m != omp_default_mem_alloc)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/allocator-6.c b/libgomp/testsuite/libgomp.c/allocator-6.c
new file mode 100644
index 0000000..7c99e0e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/allocator-6.c
@@ -0,0 +1,15 @@
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_default_mem_space:alignment=3" } */
+
+/* { dg-output ".*libgomp: Allocator of environment variable OMP_ALLOCATOR cannot be created, using omp_default_mem_alloc instead.*" } */
+/* OMP_ALLOCATOR's alignment is not power of 2 -> use omp_default_mem_alloc. */
+
+#include <omp.h>
+
+int
+main ()
+{
+ omp_allocator_handle_t m = omp_get_default_allocator ();
+ if (m != omp_default_mem_alloc)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/c.exp b/libgomp/testsuite/libgomp.c/c.exp
index 31bdd57..aae2824 100644
--- a/libgomp/testsuite/libgomp.c/c.exp
+++ b/libgomp/testsuite/libgomp.c/c.exp
@@ -1,17 +1,8 @@
-if [info exists lang_library_path] then {
- unset lang_library_path
- unset lang_link_flags
-}
-if [info exists lang_test_file] then {
- unset lang_test_file
-}
-if [info exists lang_include_flags] then {
- unset lang_include_flags
-}
-
load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
+lappend ALWAYS_CFLAGS "compiler=$GCC_UNDER_TEST"
+
# If a testcase doesn't have special options, use these.
if ![info exists DEFAULT_CFLAGS] then {
set DEFAULT_CFLAGS "-O2"
diff --git a/libgomp/testsuite/libgomp.c/scan-23.c b/libgomp/testsuite/libgomp.c/scan-23.c
new file mode 100644
index 0000000..e7681ad
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/scan-23.c
@@ -0,0 +1,121 @@
+/* { dg-require-effective-target size32plus } */
+/* Same as scan-9.c, instead of using { ... } it simply uses multiple
+ executable stmt before 'omp scan'. */
+
+extern void abort (void);
+int r, a[1024], b[1024], x, y, z;
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+ #pragma omp for reduction (inscan, +:r) lastprivate (conditional: z) firstprivate (x) private (y)
+ for (int i = 0; i < 1024; i++)
+ {
+ y = a[i];
+ r += y + x + 12;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ if ((i & 1) == 0 && i < 937)
+ z = r;
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int s = 0;
+ #pragma omp parallel
+ #pragma omp for reduction (inscan, +:s) firstprivate (x) private (y) lastprivate (z)
+ for (int i = 0; i < 1024; i++)
+ {
+ y = 2 * a[i]; s += y; z = y;
+ #pragma omp scan inclusive(s)
+ y = s; b[i] = y + x + 12;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+ #pragma omp parallel for reduction (inscan, +:r) firstprivate (x) lastprivate (x)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i] + x + 12; if (i == 1023) x = 29;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int s = 0;
+ #pragma omp parallel for reduction (inscan, +:s) lastprivate (conditional: x, y)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i]; if ((a[i] & 1) == 1 && i < 825) x = a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s; if ((a[i] & 1) == 0 && i < 829) y = a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ x = -12;
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ #pragma omp parallel
+ foo (a, b);
+ if (r != 1024 * 1023 / 2 || x != -12 || z != b[936])
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ }
+ if (bar () != 1024 * 1023 || x != -12 || z != 2 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ }
+ r = 0;
+ baz (a, b);
+ if (r != 1024 * 1023 / 2 || x != 29)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ }
+ if (qux () != 1024 * 1023 || x != 823 || y != 828)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-math-1.c b/libgomp/testsuite/libgomp.c/simd-math-1.c
index 947bf60..dd2077c 100644
--- a/libgomp/testsuite/libgomp.c/simd-math-1.c
+++ b/libgomp/testsuite/libgomp.c/simd-math-1.c
@@ -4,7 +4,6 @@
/* { dg-do run } */
/* { dg-options "-O2 -ftree-vectorize -fno-math-errno" } */
/* { dg-additional-options -foffload-options=amdgcn-amdhsa=-mstack-size=3000000 { target offload_target_amdgcn } } */
-/* { dg-additional-options -foffload-options=-lm } */
#undef PRINT_RESULT
#define VERBOSE 0
diff --git a/libgomp/testsuite/libgomp.c/target-19.c b/libgomp/testsuite/libgomp.c/target-19.c
index 2505caf..dac7c56 100644
--- a/libgomp/testsuite/libgomp.c/target-19.c
+++ b/libgomp/testsuite/libgomp.c/target-19.c
@@ -20,7 +20,9 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -37,7 +39,9 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -55,7 +59,9 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
if (sep)
{
- if (q != (int *) 0 || r != (int *) 0)
+ /* Since OpenMP 5.2, 'q'/'r' are no longer set to NULL if pointing to
+ unmapped storage. */
+ if (q == (int *) 0 || r == (int *) 0)
err = 1;
}
else if (p + 8 != q || r != s)
@@ -91,7 +97,8 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
@@ -110,7 +117,8 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
@@ -130,7 +138,8 @@ foo (int *p, int *q, int *r, int n, int m)
err = 1;
else if (sep)
{
- if (r != (int *) 0)
+ /* Since OpenMP 5.2, 'r' is no longer set to NULL if *r is unmapped.*/
+ if (r == (int *) 0)
err = 1;
}
else if (r != q + 1)
diff --git a/libgomp/testsuite/libgomp.c/target-48.c b/libgomp/testsuite/libgomp.c/target-48.c
new file mode 100644
index 0000000..8e95c1c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-48.c
@@ -0,0 +1,31 @@
+/* Check OMP_TARGET_OFFLOAD on systems with no available non-host devices;
+ omp_invalid_device == -4 with GCC. */
+
+/* { dg-do run { target { ! offload_device } } } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '-4'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ if (omp_get_default_device () != omp_invalid_device)
+ __builtin_abort ();
+
+ omp_set_default_device (omp_initial_device);
+
+ /* The spec is a bit unclear whether the line above sets the device number
+ (a) to -1 (= omp_initial_device) or
+ (b) to omp_get_initial_device() == omp_get_num_devices(). Therefore,
+ we accept either value. */
+
+ if (omp_get_default_device() != omp_get_initial_device()
+ && omp_get_default_device() != omp_initial_device)
+ __builtin_abort ();
+
+ omp_display_env (0);
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-49.c b/libgomp/testsuite/libgomp.c/target-49.c
new file mode 100644
index 0000000..970cb91
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-49.c
@@ -0,0 +1,18 @@
+/* Check OMP_TARGET_OFFLOAD on systems with no available non-host devices,
+ which is enforced by using -foffload=disable. */
+
+/* { dg-do run } */
+/* { dg-additional-options "-foffload=disable" } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* See comment in target-50.c/target-50.c for why default-device-var can be '0'. */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '-4'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" { target { ! offload_device } } } */
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '0'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" { target offload_device } } */
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-50.c b/libgomp/testsuite/libgomp.c/target-50.c
new file mode 100644
index 0000000..6f15569
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-50.c
@@ -0,0 +1,27 @@
+/* Check OMP_TARGET_OFFLOAD on systems with no available non-host devices;
+ here with using -foffload=disable.
+ As default-device-var is set to 0 (= host in this case), it should not fail. */
+
+/* Note that -foffload=disable will still find devices on the system and only
+ when trying to use them, it will fail as no binary data has been produced.
+ The "target offload_device" case is checked for in 'target-50a.c'. */
+
+/* { dg-do run { target { ! offload_device } } } */
+
+/* { dg-additional-options "-foffload=disable" } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+/* { dg-set-target-env-var OMP_DEFAULT_DEVICE "0" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '0'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" } */
+
+int
+main ()
+{
+ int x;
+ #pragma omp target map(tofrom:x)
+ x = 5;
+ if (x != 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-50a.c b/libgomp/testsuite/libgomp.c/target-50a.c
new file mode 100644
index 0000000..0835cb5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-50a.c
@@ -0,0 +1,43 @@
+/* Check OMP_TARGET_OFFLOAD on systems with non-host devices but no executable
+ code due to -foffload=disable.
+
+ Note: While one might expect that -foffload=disable implies no non-host
+ devices, libgomp actually detects the devices and only fails when trying to
+ run as no executable code is availale for that device.
+ (Without MANDATORY it simply uses host fallback, which should usually be fine
+ but might have issues in corner cases.)
+
+ We have default-device-var = 0 (default but also explicitly set), which will
+ fail at runtime. For -foffload=disable without non-host devices, see
+ target-50.c testcase. */
+
+/* { dg-do run { target offload_device } } */
+
+/* { dg-additional-options "-foffload=disable" } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+/* { dg-set-target-env-var OMP_DEFAULT_DEVICE "0" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '0'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ int x;
+ /* We know that there are non-host devices. With GCC, we still find them as
+ available devices, hence, check for it. */
+ if (omp_get_num_devices() <= 0)
+ __builtin_abort ();
+
+ /* But due to -foffload=disable, there are no binary code for (default) device '0' */
+
+ /* { dg-output ".*libgomp: OMP_TARGET_OFFLOAD is set to MANDATORY, but device cannot be used for offloading.*" } */
+ /* { dg-shouldfail "OMP_TARGET_OFFLOAD=mandatory and no binary code for a non-host device" } */
+ #pragma omp target map(tofrom:x)
+ x = 5;
+ if (x != 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-51.c b/libgomp/testsuite/libgomp.c/target-51.c
new file mode 100644
index 0000000..7ff8122
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-51.c
@@ -0,0 +1,23 @@
+/* Check OMP_TARGET_OFFLOAD on systems with no available non-host devices,
+ which is enforced by using -foffload=disable. */
+
+/* { dg-do run } */
+/* { dg-additional-options "-foffload=disable" } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+
+/* { dg-shouldfail "OMP_TARGET_OFFLOAD=mandatory and no available device" } */
+
+/* See comment in target-50.c/target-50.c for why the output differs. */
+
+/* { dg-output ".*libgomp: OMP_TARGET_OFFLOAD is set to MANDATORY, but .*" } */
+
+int
+main ()
+{
+ int x;
+ #pragma omp target map(tofrom:x)
+ x = 5;
+ if (x != 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-52.c b/libgomp/testsuite/libgomp.c/target-52.c
new file mode 100644
index 0000000..809380c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-52.c
@@ -0,0 +1,25 @@
+/* Only run this with available non-host devices; in that case, GCC sets
+ the default-device-var to 0. */
+
+/* { dg-do run { target { offload_device } } } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '0'.*OMP_TARGET_OFFLOAD = 'MANDATORY'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ int x;
+ #pragma omp target map(tofrom:x)
+ x = 5 + omp_is_initial_device ();
+
+ if (x != 5)
+ __builtin_abort ();
+
+ if (0 != omp_get_default_device())
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-53.c b/libgomp/testsuite/libgomp.c/target-53.c
new file mode 100644
index 0000000..866e896
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-53.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "disabled" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '\[0-9\]+'.*OMP_TARGET_OFFLOAD = 'DISABLED'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ int x;
+ #pragma omp target map(tofrom:x)
+ x = 5 + omp_is_initial_device ();
+
+ if (x != 5+1)
+ __builtin_abort ();
+
+ if (omp_get_default_device() != omp_get_initial_device())
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-54.c b/libgomp/testsuite/libgomp.c/target-54.c
new file mode 100644
index 0000000..bc4e69b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-54.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "default" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+/* { dg-output ".*OMP_DEFAULT_DEVICE = '0'.*OMP_TARGET_OFFLOAD = 'DEFAULT'.*" } */
+
+#include <omp.h>
+
+int
+main ()
+{
+ int x;
+ #pragma omp target map(tofrom:x)
+ x = 5 + omp_is_initial_device ();
+
+ if (x != 5 + (omp_get_default_device() == omp_get_initial_device()))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-55.c b/libgomp/testsuite/libgomp.c/target-55.c
new file mode 100644
index 0000000..1314b3c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-55.c
@@ -0,0 +1,20 @@
+/* { dg-do run { target { offload_device } } } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+
+/* Should pass - see target-55a.c for !offload_device */
+
+/* Check OMP_TARGET_OFFLOAD - it shall run on systems with offloading
+ devices available and fail otherwise. Note that this did always
+ fail - as the device handling wasn't initialized before doing the
+ mandatory checking. */
+
+int
+main ()
+{
+ int x = 1;
+ #pragma omp target map(tofrom: x)
+ x = 5;
+ if (x != 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-55a.c b/libgomp/testsuite/libgomp.c/target-55a.c
new file mode 100644
index 0000000..53978c3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-55a.c
@@ -0,0 +1,23 @@
+/* { dg-do run { target { ! offload_device } } } */
+/* { dg-set-target-env-var OMP_TARGET_OFFLOAD "mandatory" } */
+
+/* Should fail - see target-55a.c for offload_device */
+
+/* { dg-shouldfail "omp_invalid_device" } */
+/* { dg-output ".*libgomp: OMP_TARGET_OFFLOAD is set to MANDATORY, but only the host device is available.*" } */
+
+/* Check OMP_TARGET_OFFLOAD - it shall run on systems with offloading
+ devices available and fail otherwise. Note that this did always
+ fail - as the device handling wasn't initialized before doing the
+ mandatory checking. */
+
+int
+main ()
+{
+ int x = 1;
+ #pragma omp target map(tofrom: x)
+ x = 5;
+ if (x != 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/allocate-4.f90 b/libgomp/testsuite/libgomp.fortran/allocate-4.f90
index ddb507b..1f833b6 100644
--- a/libgomp/testsuite/libgomp.fortran/allocate-4.f90
+++ b/libgomp/testsuite/libgomp.fortran/allocate-4.f90
@@ -16,27 +16,27 @@ integer, parameter :: cnst(2) = [64, 101]
!$omp parallel allocate( allocator (omp_high_bw_mem_alloc) : x) firstprivate(x) ! { dg-error "Expected integer expression of the 'omp_allocator_handle_kind' kind" }
!$omp end parallel
-!$omp parallel allocate( align (q) : x) firstprivate(x) ! { dg-error "32:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align (q) : x) firstprivate(x) ! { dg-error "32:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
!$omp parallel allocate( align (32) : x) firstprivate(x) ! OK
!$omp end parallel
-!$omp parallel allocate( align(q) : x) firstprivate(x) ! { dg-error "31:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align(q) : x) firstprivate(x) ! { dg-error "31:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
!$omp parallel allocate( align(cnst(1)) : x ) firstprivate(x) ! OK
!$omp end parallel
-!$omp parallel allocate( align(cnst(2)) : x) firstprivate(x) ! { dg-error "31:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align(cnst(2)) : x) firstprivate(x) ! { dg-error "31:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
-!$omp parallel allocate( align( 31) :x) firstprivate(x) ! { dg-error "32:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align( 31) :x) firstprivate(x) ! { dg-error "32:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
-!$omp parallel allocate( align (32.0): x) firstprivate(x) ! { dg-error "32:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align (32.0): x) firstprivate(x) ! { dg-error "32:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
-!$omp parallel allocate( align(cnst ) : x ) firstprivate(x) ! { dg-error "31:ALIGN modifier requires at \\(1\\) a scalar positive constant integer alignment expression that is a power of two" }
+!$omp parallel allocate( align(cnst ) : x ) firstprivate(x) ! { dg-error "31:ALIGN requires a scalar positive constant integer alignment expression at \\(1\\) that is a power of two" }
!$omp end parallel
end
diff --git a/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90 b/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90
new file mode 100644
index 0000000..2d0caa6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/fortran-torture_execute_math.f90
@@ -0,0 +1,3 @@
+! { dg-do run }
+
+include '../../../gcc/testsuite/gfortran.fortran-torture/execute/math.f90'
diff --git a/libgomp/testsuite/libgomp.fortran/fortran.exp b/libgomp/testsuite/libgomp.fortran/fortran.exp
index eb70131..32e4bb2 100644
--- a/libgomp/testsuite/libgomp.fortran/fortran.exp
+++ b/libgomp/testsuite/libgomp.fortran/fortran.exp
@@ -2,18 +2,33 @@ load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
load_gcc_lib gfortran-dg.exp
-global shlib_ext
-global ALWAYS_CFLAGS
+if { $blddir != "" } {
+ set libgfortran_library_path "../libgfortran/.libs"
+ set shlib_ext [get_shlib_extension]
+ if { ![file exists "${blddir}/${libgfortran_library_path}/libgfortran.a"]
+ && ![file exists "${blddir}/${libgfortran_library_path}/libgfortran.${shlib_ext}"] } {
+ verbose -log "No libgfortran library found, will not execute fortran tests"
+ unset libgfortran_library_path
+ return
+ }
+ lappend lang_library_paths $libgfortran_library_path
-set shlib_ext [get_shlib_extension]
-set lang_library_path "../libgfortran/.libs"
-set lang_link_flags "-lgfortran -foffload=-lgfortran"
-if [info exists lang_include_flags] then {
- unset lang_include_flags
+ set libquadmath_library_path "../libquadmath/.libs"
+ if { [file exists "${blddir}/${libquadmath_library_path}/libquadmath.a"]
+ || [file exists "${blddir}/${libquadmath_library_path}/libquadmath.${shlib_ext}"] } {
+ lappend lang_library_paths $libquadmath_library_path
+ } else {
+ set libquadmath_library_path ""
+ }
+} elseif { ![info exists GFORTRAN_UNDER_TEST] } {
+ verbose -log "GFORTRAN_UNDER_TEST not defined, will not execute fortran tests"
+ return
}
-set lang_test_file_found 0
-set quadmath_library_path "../libquadmath/.libs"
-
+if { $blddir != "" } {
+ set lang_source_re {^.*\.[fF](|90|95|03|08)$}
+ set lang_include_flags "-fintrinsic-modules-path=${blddir}"
+}
+lappend ALWAYS_CFLAGS "compiler=$GFORTRAN_UNDER_TEST"
# Initialize dg.
dg-init
@@ -21,58 +36,31 @@ dg-init
# Turn on OpenMP.
lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+# Gather a list of all tests.
+set tests [lsort [find $srcdir/$subdir *.\[fF\]{,90,95,03,08}]]
+
+set ld_library_path $always_ld_library_path
if { $blddir != "" } {
- set lang_source_re {^.*\.[fF](|90|95|03|08)$}
- set lang_include_flags "-fintrinsic-modules-path=${blddir}"
- # Look for a static libgfortran first.
- if [file exists "${blddir}/${lang_library_path}/libgfortran.a"] {
- set lang_test_file "${lang_library_path}/libgfortran.a"
- set lang_test_file_found 1
- # We may have a shared only build, so look for a shared libgfortran.
- } elseif [file exists "${blddir}/${lang_library_path}/libgfortran.${shlib_ext}"] {
- set lang_test_file "${lang_library_path}/libgfortran.${shlib_ext}"
- set lang_test_file_found 1
- } else {
- puts "No libgfortran library found, will not execute fortran tests"
+ append ld_library_path ":${blddir}/${libgfortran_library_path}"
+
+ if { $libquadmath_library_path != "" } {
+ append ld_library_path ":${blddir}/${libquadmath_library_path}"
}
-} elseif [info exists GFORTRAN_UNDER_TEST] {
- set lang_test_file_found 1
- # Needs to exist for libgomp.exp.
- set lang_test_file ""
-} else {
- puts "GFORTRAN_UNDER_TEST not defined, will not execute fortran tests"
}
+append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
+set_ld_library_path_env_vars
-if { $lang_test_file_found } {
- # Gather a list of all tests.
- set tests [lsort [find $srcdir/$subdir *.\[fF\]{,90,95,03,08}]]
+# For Fortran we're doing torture testing, as Fortran has far more tests
+# with arrays etc. that testing just -O0 or -O2 is insufficient, that is
+# typically not the case for C/C++.
+gfortran-dg-runtest $tests "" ""
- if { $blddir != "" } {
- if { [file exists "${blddir}/${quadmath_library_path}/libquadmath.a"]
- || [file exists "${blddir}/${quadmath_library_path}/libquadmath.${shlib_ext}"] } {
- lappend ALWAYS_CFLAGS "ldflags=-L${blddir}/${quadmath_library_path}/"
- # Allow for spec subsitution.
- lappend ALWAYS_CFLAGS "additional_flags=-B${blddir}/${quadmath_library_path}/"
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}:${blddir}/${quadmath_library_path}"
- append lang_link_flags " -lquadmath"
- } else {
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}"
- }
- } else {
- set ld_library_path "$always_ld_library_path"
- if { [check_no_compiler_messages has_libquadmath executable {
- int main() {return 0;}
- } "-lgfortran -lquadmath"] } then {
- append lang_link_flags " -lquadmath"
- }
- }
- append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
- set_ld_library_path_env_vars
-
- # For Fortran we're doing torture testing, as Fortran has far more tests
- # with arrays etc. that testing just -O0 or -O2 is insufficient, that is
- # typically not the case for C/C++.
- gfortran-dg-runtest $tests "" ""
+if { $blddir != "" } {
+ unset lang_source_re
+ unset lang_include_flags
+ unset libgfortran_library_path
+ unset libquadmath_library_path
+ unset lang_library_paths
}
# All done.
diff --git a/libgomp/testsuite/libgomp.fortran/requires-unified-addr-1.f90 b/libgomp/testsuite/libgomp.fortran/requires-unified-addr-1.f90
new file mode 100644
index 0000000..f5a5adf
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/requires-unified-addr-1.f90
@@ -0,0 +1,111 @@
+! PR libgomp/109837
+
+program main
+ use iso_c_binding
+ use iso_fortran_env
+ use omp_lib
+ implicit none (external, type)
+ !$omp requires unified_address
+
+ integer(c_intptr_t), parameter :: N = 15
+ integer :: i, ntgts
+
+ ntgts = omp_get_num_devices();
+ if (ntgts > 0) then
+ write (ERROR_UNIT, '(a)') "Offloading devices exist" ! { dg-output "Offloading devices exist(\n|\r\n|\r)" { target offload_device } }
+ else
+ write (ERROR_UNIT, '(a)') "Only host fallback" ! { dg-output "Only host fallback(\n|\r\n|\r)" { target { ! offload_device } } }
+ endif
+
+ do i = 0, ntgts
+ call test_device (i);
+ end do
+
+contains
+
+ subroutine test_device (dev)
+ integer, value, intent(in) :: dev
+
+ type t
+ integer(c_intptr_t) :: n, m
+ integer, pointer :: fptr(:)
+ type(c_ptr) :: cptr
+ end type t
+ type(t) :: s
+ type(c_ptr) :: cptr, qptr, cptr2, cptr2a
+ integer, target :: q(4)
+ integer, pointer :: fptr(:)
+ integer(c_intptr_t) :: i
+
+ s%n = 10;
+ s%m = 23;
+ s%cptr = omp_target_alloc (s%n * NUMERIC_STORAGE_SIZE/CHARACTER_STORAGE_SIZE, dev);
+ cptr = omp_target_alloc (s%m * NUMERIC_STORAGE_SIZE/CHARACTER_STORAGE_SIZE, dev);
+ if (.not. c_associated(s%cptr)) stop 1
+ if (.not. c_associated(cptr)) stop 2
+ call c_f_pointer (cptr, s%fptr, [s%m])
+
+ cptr = omp_target_alloc (N * NUMERIC_STORAGE_SIZE/CHARACTER_STORAGE_SIZE, dev);
+ if (.not. c_associated(cptr)) stop 3
+
+ q = [1, 2, 3, 4]
+ !$omp target enter data map(q) device(device_num: dev)
+ !$omp target data use_device_addr(q) device(device_num: dev)
+ qptr = c_loc(q)
+ !$omp end target data
+
+ !$omp target map(to:s) device(device_num: dev)
+ block
+ integer, pointer :: iptr(:)
+ call c_f_pointer(s%cptr, iptr, [s%n])
+ do i = 1, s%n
+ iptr(i) = 23 * int(i)
+ end do
+ do i = 1, s%m
+ s%fptr(i) = 35 * int(i)
+ end do
+ end block
+
+ cptr2 = c_loc(s%fptr(4))
+ cptr2a = s%cptr
+
+ !$omp target firstprivate(qptr) map(tofrom: cptr2) map(to :cptr2a) device(device_num: dev)
+ block
+ integer, pointer :: iptr(:), iptr2(:), qvar(:)
+ call c_f_pointer(cptr2, iptr, [4])
+ call c_f_pointer(cptr2a, iptr2, [4])
+ call c_f_pointer(qptr, qvar, [4])
+ qvar = iptr + iptr2
+ end block
+
+ !$omp target exit data map(q) device(device_num: dev)
+ do i = 1, 4
+ if (q(i) /= 23 * int(i) + 35 * (int(i) + 4 - 1)) stop 4
+ end do
+
+ !$omp target map(to: cptr) device(device_num: dev)
+ block
+ integer, pointer :: p(:)
+ call c_f_pointer(cptr, p, [N])
+ do i = 1, N
+ p(i) = 11 * int(i)
+ end do
+ end block
+
+ allocate(fptr(N))
+ if (0 /= omp_target_memcpy (c_loc(fptr), cptr, &
+ N * NUMERIC_STORAGE_SIZE/CHARACTER_STORAGE_SIZE, &
+ 0_c_intptr_t, 0_c_intptr_t, &
+ omp_get_initial_device(), dev)) &
+ stop 5
+
+ do i = 1, N
+ if (fptr(i) /= 11 * int(i)) stop 6
+ end do
+
+ deallocate (fptr);
+ call omp_target_free (cptr, dev);
+ call omp_target_free (s%cptr, dev);
+ call omp_target_free (c_loc(s%fptr), dev);
+ end
+end
diff --git a/libgomp/testsuite/libgomp.fortran/scan-2.f90 b/libgomp/testsuite/libgomp.fortran/scan-2.f90
new file mode 100644
index 0000000..2815ec7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/scan-2.f90
@@ -0,0 +1,59 @@
+implicit none
+integer, parameter :: N = 30
+integer, parameter :: M = 3
+
+integer :: a(M,N), b(M,N), c(M,N)
+integer :: x, y, shift
+integer :: i, j
+
+do i = 1, N
+ a(1,i) = i*32
+ a(2,i) = i*17
+ a(3,i) = i*11
+ b(1,i) = i*7
+ b(2,i) = i*5
+ b(3,i) = i*3
+end do
+
+x = 0
+!$omp parallel do simd collapse(2) reduction(inscan,+: x) private(shift)
+do i = 1, N
+ do j = 1, M
+ x = x + a(j,i)
+ x = x + b(j,i)
+ !$omp scan inclusive(x)
+ shift = i + 29*j
+ c(j,i) = x + shift;
+ end do
+end do
+
+y = 0
+do i = 1, N
+ do j = 1, M
+ y = y + a(j,i) + b(j,i)
+ if (c(j,i) /= y + i + 29*j) error stop 1
+ end do
+end do
+if (x /= y) error stop 2
+
+x = 0
+!$omp parallel do simd collapse(2) reduction(inscan,+: x) private(shift)
+do i = 1, N
+ do j = 1, M
+ shift = i + 29*j
+ c(j,i) = x + shift;
+ !$omp scan exclusive(x)
+ x = x + a(j,i)
+ x = x + b(j,i)
+ end do
+end do
+
+y = 0
+do i = 1, N
+ do j = 1, M
+ if (c(j,i) /= y + i + 29*j) error stop 1
+ y = y + a(j,i) + b(j,i)
+ end do
+end do
+if (x /= y) error stop 2
+end
diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-3.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-3.f90
index 5d97566..1b3cdf9 100644
--- a/libgomp/testsuite/libgomp.fortran/target-enter-data-3.f90
+++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-3.f90
@@ -17,6 +17,6 @@ var%p2 = [46,679,54]
if (any (var%p1 /= [22,53,28,6,4])) stop 3
if (any (var%p2 /= [46,679,54])) stop 4
!$omp end target
-!!$omp target exit data map(from:var%p1, var%p2)
+!$omp target exit data map(from:var%p1, var%p2)
end
diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-4.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-4.f90
new file mode 100644
index 0000000..6192bf2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-4.f90
@@ -0,0 +1,540 @@
+! Check that 'map(alloc:' properly works with
+! - deferred-length character strings
+! - arrays with array descriptors
+! For those, the array descriptor / string length must be mapped with 'to:'
+
+program main
+implicit none
+
+type t
+ integer :: ic(2:5), ic2
+ character(len=11) :: ccstr(3:4), ccstr2
+ character(len=11,kind=4) :: cc4str(3:7), cc4str2
+ integer, pointer :: pc(:), pc2
+ character(len=:), pointer :: pcstr(:), pcstr2
+ character(len=:,kind=4), pointer :: pc4str(:), pc4str2
+end type t
+
+type(t) :: dt
+
+integer :: ii(5), ii2
+character(len=11) :: clstr(-1:1), clstr2
+character(len=11,kind=4) :: cl4str(0:3), cl4str2
+integer, pointer :: ip(:), ip2
+integer, allocatable :: ia(:), ia2
+character(len=:), pointer :: pstr(:), pstr2
+character(len=:), allocatable :: astr(:), astr2
+character(len=:,kind=4), pointer :: p4str(:), p4str2
+character(len=:,kind=4), allocatable :: a4str(:), a4str2
+
+allocate(dt%pc(5), dt%pc2)
+allocate(character(len=2) :: dt%pcstr(2))
+allocate(character(len=4) :: dt%pcstr2)
+
+allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+allocate(character(len=5,kind=4) :: dt%pc4str2)
+
+allocate(ip(5), ip2, ia(8), ia2)
+allocate(character(len=2) :: pstr(-2:0))
+allocate(character(len=4) :: pstr2)
+allocate(character(len=6) :: astr(3:5))
+allocate(character(len=8) :: astr2)
+
+allocate(character(len=3,kind=4) :: p4str(2:4))
+allocate(character(len=5,kind=4) :: p4str2)
+allocate(character(len=7,kind=4) :: a4str(-2:3))
+allocate(character(len=9,kind=4) :: a4str2)
+
+
+! integer :: ic(2:5), ic2
+
+!$omp target enter data map(alloc: dt%ic)
+!$omp target map(alloc: dt%ic)
+ if (size(dt%ic) /= 4) error stop
+ if (lbound(dt%ic, 1) /= 2) error stop
+ if (ubound(dt%ic, 1) /= 5) error stop
+ dt%ic = [22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%ic)
+if (size(dt%ic) /= 4) error stop
+if (lbound(dt%ic, 1) /= 2) error stop
+if (ubound(dt%ic, 1) /= 5) error stop
+if (any (dt%ic /= [22, 33, 44, 55])) error stop
+
+!$omp target enter data map(alloc: dt%ic2)
+!$omp target map(alloc: dt%ic2)
+ dt%ic2 = 42
+!$omp end target
+!$omp target exit data map(from: dt%ic2)
+if (dt%ic2 /= 42) error stop
+
+
+! character(len=11) :: ccstr(3:4), ccstr2
+
+!$omp target enter data map(alloc: dt%ccstr)
+!$omp target map(alloc: dt%ccstr)
+ if (len(dt%ccstr) /= 11) error stop
+ if (size(dt%ccstr) /= 2) error stop
+ if (lbound(dt%ccstr, 1) /= 3) error stop
+ if (ubound(dt%ccstr, 1) /= 4) error stop
+ dt%ccstr = ["12345678901", "abcdefghijk"]
+!$omp end target
+!$omp target exit data map(from: dt%ccstr)
+if (len(dt%ccstr) /= 11) error stop
+if (size(dt%ccstr) /= 2) error stop
+if (lbound(dt%ccstr, 1) /= 3) error stop
+if (ubound(dt%ccstr, 1) /= 4) error stop
+if (any (dt%ccstr /= ["12345678901", "abcdefghijk"])) error stop
+
+!$omp target enter data map(alloc: dt%ccstr2)
+!$omp target map(alloc: dt%ccstr2)
+ if (len(dt%ccstr2) /= 11) error stop
+ dt%ccstr2 = "ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: dt%ccstr2)
+if (len(dt%ccstr2) /= 11) error stop
+if (dt%ccstr2 /= "ABCDEFGHIJK") error stop
+
+
+! character(len=11,kind=4) :: cc4str(3:7), cc4str2
+
+! Value check fails
+!$omp target enter data map(alloc: dt%cc4str)
+!$omp target map(alloc: dt%cc4str)
+ if (len(dt%cc4str) /= 11) error stop
+ if (size(dt%cc4str) /= 5) error stop
+ if (lbound(dt%cc4str, 1) /= 3) error stop
+ if (ubound(dt%cc4str, 1) /= 7) error stop
+ dt%cc4str = [4_"12345678901", 4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4.", &
+ 4_"45ngwj56sj2"]
+!$omp end target
+!$omp target exit data map(from: dt%cc4str)
+if (len(dt%cc4str) /= 11) error stop
+if (size(dt%cc4str) /= 5) error stop
+if (lbound(dt%cc4str, 1) /= 3) error stop
+if (ubound(dt%cc4str, 1) /= 7) error stop
+if (dt%cc4str(3) /= 4_"12345678901") error stop
+if (dt%cc4str(4) /= 4_"abcdefghijk") error stop
+if (dt%cc4str(5) /= 4_"qerftcea6ds") error stop
+if (dt%cc4str(6) /= 4_"a1f9g37ga4.") error stop
+if (dt%cc4str(7) /= 4_"45ngwj56sj2") error stop
+
+!$omp target enter data map(alloc: dt%cc4str2)
+!$omp target map(alloc: dt%cc4str2)
+ if (len(dt%cc4str2) /= 11) error stop
+ dt%cc4str2 = 4_"ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: dt%cc4str2)
+if (len(dt%cc4str2) /= 11) error stop
+if (dt%cc4str2 /= 4_"ABCDEFGHIJK") error stop
+
+
+! integer, pointer :: pc(:), pc2
+! allocate(dt%pc(5), dt%pc2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(alloc: dt%pc)
+!$omp target map(alloc: dt%pc)
+ if (.not. associated(dt%pc)) error stop
+ if (size(dt%pc) /= 5) error stop
+ if (lbound(dt%pc, 1) /= 1) error stop
+ if (ubound(dt%pc, 1) /= 5) error stop
+ dt%pc = [11, 22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%pc)
+if (.not. associated(dt%pc)) error stop
+if (size(dt%pc) /= 5) error stop
+if (lbound(dt%pc, 1) /= 1) error stop
+if (ubound(dt%pc, 1) /= 5) error stop
+if (any (dt%pc /= [11, 22, 33, 44, 55])) error stop
+
+!$omp target enter data map(alloc: dt%pc2)
+!$omp target map(alloc: dt%pc2)
+ if (.not. associated(dt%pc2)) error stop
+ dt%pc2 = 99
+!$omp end target
+!$omp target exit data map(from: dt%pc2)
+if (dt%pc2 /= 99) error stop
+if (.not. associated(dt%pc2)) error stop
+
+
+! character(len=:), pointer :: pcstr(:), pcstr2
+! allocate(character(len=2) :: dt%pcstr(2))
+! allocate(character(len=4) :: dt%pcstr2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(alloc: dt%pcstr)
+!$omp target map(alloc: dt%pcstr)
+ if (.not. associated(dt%pcstr)) error stop
+ if (len(dt%pcstr) /= 2) error stop
+ if (size(dt%pcstr) /= 2) error stop
+ if (lbound(dt%pcstr, 1) /= 1) error stop
+ if (ubound(dt%pcstr, 1) /= 2) error stop
+ dt%pcstr = ["01", "jk"]
+!$omp end target
+!$omp target exit data map(from: dt%pcstr)
+if (.not. associated(dt%pcstr)) error stop
+if (len(dt%pcstr) /= 2) error stop
+if (size(dt%pcstr) /= 2) error stop
+if (lbound(dt%pcstr, 1) /= 1) error stop
+if (ubound(dt%pcstr, 1) /= 2) error stop
+if (any (dt%pcstr /= ["01", "jk"])) error stop
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x01
+
+!$omp target enter data map(alloc: dt%pcstr2)
+!$omp target map(alloc: dt%pcstr2)
+ if (.not. associated(dt%pcstr2)) error stop
+ if (len(dt%pcstr2) /= 4) error stop
+ dt%pcstr2 = "HIJK"
+!$omp end target
+!$omp target exit data map(from: dt%pcstr2)
+if (.not. associated(dt%pcstr2)) error stop
+if (len(dt%pcstr2) /= 4) error stop
+if (dt%pcstr2 /= "HIJK") error stop
+
+
+! character(len=:,kind=4), pointer :: pc4str(:), pc4str2
+! allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+! allocate(character(len=5,kind=4) :: dt%pc4str2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+! structure element when other mapped elements from the same structure weren't mapped together with it
+!$omp target enter data map(alloc: dt%pc4str)
+!$omp target map(alloc: dt%pc4str)
+ if (.not. associated(dt%pc4str)) error stop
+ if (len(dt%pc4str) /= 3) error stop
+ if (size(dt%pc4str) /= 2) error stop
+ if (lbound(dt%pc4str, 1) /= 2) error stop
+ if (ubound(dt%pc4str, 1) /= 3) error stop
+ dt%pc4str = [4_"456", 4_"tzu"]
+!$omp end target
+!$omp target exit data map(from: dt%pc4str)
+if (.not. associated(dt%pc4str)) error stop
+if (len(dt%pc4str) /= 3) error stop
+if (size(dt%pc4str) /= 2) error stop
+if (lbound(dt%pc4str, 1) /= 2) error stop
+if (ubound(dt%pc4str, 1) /= 3) error stop
+if (dt%pc4str(2) /= 4_"456") error stop
+if (dt%pc4str(3) /= 4_"tzu") error stop
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x01
+
+!$omp target enter data map(alloc: dt%pc4str2)
+!$omp target map(alloc: dt%pc4str2)
+ if (.not. associated(dt%pc4str2)) error stop
+ if (len(dt%pc4str2) /= 5) error stop
+ dt%pc4str2 = 4_"98765"
+!$omp end target
+!$omp target exit data map(from: dt%pc4str2)
+if (.not. associated(dt%pc4str2)) error stop
+if (len(dt%pc4str2) /= 5) error stop
+if (dt%pc4str2 /= 4_"98765") error stop
+
+
+! integer :: ii(5), ii2
+
+!$omp target enter data map(alloc: ii)
+!$omp target map(alloc: ii)
+ if (size(ii) /= 5) error stop
+ if (lbound(ii, 1) /= 1) error stop
+ if (ubound(ii, 1) /= 5) error stop
+ ii = [-1, -2, -3, -4, -5]
+!$omp end target
+!$omp target exit data map(from: ii)
+if (size(ii) /= 5) error stop
+if (lbound(ii, 1) /= 1) error stop
+if (ubound(ii, 1) /= 5) error stop
+if (any (ii /= [-1, -2, -3, -4, -5])) error stop
+
+!$omp target enter data map(alloc: ii2)
+!$omp target map(alloc: ii2)
+ ii2 = -410
+!$omp end target
+!$omp target exit data map(from: ii2)
+if (ii2 /= -410) error stop
+
+
+! character(len=11) :: clstr(-1:1), clstr2
+
+!$omp target enter data map(alloc: clstr)
+!$omp target map(alloc: clstr)
+ if (len(clstr) /= 11) error stop
+ if (size(clstr) /= 3) error stop
+ if (lbound(clstr, 1) /= -1) error stop
+ if (ubound(clstr, 1) /= 1) error stop
+ clstr = ["12345678901", "abcdefghijk", "ABCDEFGHIJK"]
+!$omp end target
+!$omp target exit data map(from: clstr)
+if (len(clstr) /= 11) error stop
+if (size(clstr) /= 3) error stop
+if (lbound(clstr, 1) /= -1) error stop
+if (ubound(clstr, 1) /= 1) error stop
+if (any (clstr /= ["12345678901", "abcdefghijk", "ABCDEFGHIJK"])) error stop
+
+!$omp target enter data map(alloc: clstr2)
+!$omp target map(alloc: clstr2)
+ if (len(clstr2) /= 11) error stop
+ clstr2 = "ABCDEFghijk"
+!$omp end target
+!$omp target exit data map(from: clstr2)
+if (len(clstr2) /= 11) error stop
+if (clstr2 /= "ABCDEFghijk") error stop
+
+
+! character(len=11,kind=4) :: cl4str(0:3), cl4str2
+
+!$omp target enter data map(alloc: cl4str)
+!$omp target map(alloc: cl4str)
+ if (len(cl4str) /= 11) error stop
+ if (size(cl4str) /= 4) error stop
+ if (lbound(cl4str, 1) /= 0) error stop
+ if (ubound(cl4str, 1) /= 3) error stop
+ cl4str = [4_"12345678901", 4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4."]
+!$omp end target
+!$omp target exit data map(from: cl4str)
+if (len(cl4str) /= 11) error stop
+if (size(cl4str) /= 4) error stop
+if (lbound(cl4str, 1) /= 0) error stop
+if (ubound(cl4str, 1) /= 3) error stop
+if (cl4str(0) /= 4_"12345678901") error stop
+if (cl4str(1) /= 4_"abcdefghijk") error stop
+if (cl4str(2) /= 4_"qerftcea6ds") error stop
+if (cl4str(3) /= 4_"a1f9g37ga4.") error stop
+
+!$omp target enter data map(alloc: cl4str2)
+!$omp target map(alloc: cl4str2)
+ if (len(cl4str2) /= 11) error stop
+ cl4str2 = 4_"ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: cl4str2)
+if (len(cl4str2) /= 11) error stop
+if (cl4str2 /= 4_"ABCDEFGHIJK") error stop
+
+
+! allocate(ip(5), ip2, ia(8), ia2)
+
+!$omp target enter data map(alloc: ip)
+!$omp target map(alloc: ip)
+ if (.not. associated(ip)) error stop
+ if (size(ip) /= 5) error stop
+ if (lbound(ip, 1) /= 1) error stop
+ if (ubound(ip, 1) /= 5) error stop
+ ip = [11, 22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: ip)
+if (.not. associated(ip)) error stop
+if (size(ip) /= 5) error stop
+if (lbound(ip, 1) /= 1) error stop
+if (ubound(ip, 1) /= 5) error stop
+if (any (ip /= [11, 22, 33, 44, 55])) error stop
+
+!$omp target enter data map(alloc: ip2)
+!$omp target map(alloc: ip2)
+ if (.not. associated(ip2)) error stop
+ ip2 = 99
+!$omp end target
+!$omp target exit data map(from: ip2)
+if (ip2 /= 99) error stop
+if (.not. associated(ip2)) error stop
+
+
+! allocate(ip(5), ip2, ia(8), ia2)
+
+!$omp target enter data map(alloc: ia)
+!$omp target map(alloc: ia)
+ if (.not. allocated(ia)) error stop
+ if (size(ia) /= 8) error stop
+ if (lbound(ia, 1) /= 1) error stop
+ if (ubound(ia, 1) /= 8) error stop
+ ia = [1,2,3,4,5,6,7,8]
+!$omp end target
+!$omp target exit data map(from: ia)
+if (.not. allocated(ia)) error stop
+if (size(ia) /= 8) error stop
+if (lbound(ia, 1) /= 1) error stop
+if (ubound(ia, 1) /= 8) error stop
+if (any (ia /= [1,2,3,4,5,6,7,8])) error stop
+
+!$omp target enter data map(alloc: ia2)
+!$omp target map(alloc: ia2)
+ if (.not. allocated(ia2)) error stop
+ ia2 = 102
+!$omp end target
+!$omp target exit data map(from: ia2)
+if (ia2 /= 102) error stop
+if (.not. allocated(ia2)) error stop
+
+
+! character(len=:), pointer :: pstr(:), pstr2
+! allocate(character(len=2) :: pstr(-2:0))
+! allocate(character(len=4) :: pstr2)
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(alloc: pstr)
+!$omp target map(alloc: pstr)
+ if (.not. associated(pstr)) error stop
+ if (len(pstr) /= 2) error stop
+ if (size(pstr) /= 3) error stop
+ if (lbound(pstr, 1) /= -2) error stop
+ if (ubound(pstr, 1) /= 0) error stop
+ pstr = ["01", "jk", "aq"]
+!$omp end target
+!$omp target exit data map(from: pstr)
+if (.not. associated(pstr)) error stop
+if (len(pstr) /= 2) error stop
+if (size(pstr) /= 3) error stop
+if (lbound(pstr, 1) /= -2) error stop
+if (ubound(pstr, 1) /= 0) error stop
+if (any (pstr /= ["01", "jk", "aq"])) error stop
+
+!$omp target enter data map(alloc: pstr2)
+!$omp target map(alloc: pstr2)
+ if (.not. associated(pstr2)) error stop
+ if (len(pstr2) /= 4) error stop
+ pstr2 = "HIJK"
+!$omp end target
+!$omp target exit data map(from: pstr2)
+if (.not. associated(pstr2)) error stop
+if (len(pstr2) /= 4) error stop
+if (pstr2 /= "HIJK") error stop
+
+
+! character(len=:), allocatable :: astr(:), astr2
+! allocate(character(len=6) :: astr(3:5))
+! allocate(character(len=8) :: astr2)
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(alloc: astr)
+!$omp target map(alloc: astr)
+ if (.not. allocated(astr)) error stop
+ if (len(astr) /= 6) error stop
+ if (size(astr) /= 3) error stop
+ if (lbound(astr, 1) /= 3) error stop
+ if (ubound(astr, 1) /= 5) error stop
+ astr = ["01db45", "jk$D%S", "zutg47"]
+!$omp end target
+!$omp target exit data map(from: astr)
+if (.not. allocated(astr)) error stop
+if (len(astr) /= 6) error stop
+if (size(astr) /= 3) error stop
+if (lbound(astr, 1) /= 3) error stop
+if (ubound(astr, 1) /= 5) error stop
+if (any (astr /= ["01db45", "jk$D%S", "zutg47"])) error stop
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(alloc: astr2)
+!$omp target map(alloc: astr2)
+ if (.not. allocated(astr2)) error stop
+ if (len(astr2) /= 8) error stop
+ astr2 = "HIJKhijk"
+!$omp end target
+!$omp target exit data map(from: astr2)
+if (.not. allocated(astr2)) error stop
+if (len(astr2) /= 8) error stop
+if (astr2 /= "HIJKhijk") error stop
+
+
+! character(len=:,kind=4), pointer :: p4str(:), p4str2
+! allocate(character(len=3,kind=4) :: p4str(2:4))
+! allocate(character(len=5,kind=4) :: p4str2)
+
+! FAILS with value check
+
+!$omp target enter data map(alloc: p4str)
+!$omp target map(alloc: p4str)
+ if (.not. associated(p4str)) error stop
+ if (len(p4str) /= 3) error stop
+ if (size(p4str) /= 3) error stop
+ if (lbound(p4str, 1) /= 2) error stop
+ if (ubound(p4str, 1) /= 4) error stop
+ p4str(:) = [4_"f85", 4_"8af", 4_"A%F"]
+!$omp end target
+!$omp target exit data map(from: p4str)
+if (.not. associated(p4str)) error stop
+if (len(p4str) /= 3) error stop
+if (size(p4str) /= 3) error stop
+if (lbound(p4str, 1) /= 2) error stop
+if (ubound(p4str, 1) /= 4) error stop
+if (p4str(2) /= 4_"f85") error stop
+if (p4str(3) /= 4_"8af") error stop
+if (p4str(4) /= 4_"A%F") error stop
+
+!$omp target enter data map(alloc: p4str2)
+!$omp target map(alloc: p4str2)
+ if (.not. associated(p4str2)) error stop
+ if (len(p4str2) /= 5) error stop
+ p4str2 = 4_"9875a"
+!$omp end target
+!$omp target exit data map(from: p4str2)
+if (.not. associated(p4str2)) error stop
+if (len(p4str2) /= 5) error stop
+if (p4str2 /= 4_"9875a") error stop
+
+
+! character(len=:,kind=4), allocatable :: a4str(:), a4str2
+! allocate(character(len=7,kind=4) :: a4str(-2:3))
+! allocate(character(len=9,kind=4) :: a4str2)
+
+! libgomp: Trying to map into device [0x1027ba0..0x251050bb9c9ebba0) object when [0x7ffd026e6708..0x7ffd026e6710) is already mapped
+
+!$omp target enter data map(alloc: a4str)
+!$omp target map(alloc: a4str)
+ if (.not. allocated(a4str)) error stop
+ if (len(a4str) /= 7) error stop
+ if (size(a4str) /= 6) error stop
+ if (lbound(a4str, 1) /= -2) error stop
+ if (ubound(a4str, 1) /= 3) error stop
+ ! See PR fortran/107508 why '(:)' is required
+ a4str(:) = [4_"sf456aq", 4_"3dtzu24", 4_"_4fh7sm", 4_"=ff85s7", 4_"j=8af4d", 4_".,A%Fsz"]
+!$omp end target
+!$omp target exit data map(from: a4str)
+if (.not. allocated(a4str)) error stop
+if (len(a4str) /= 7) error stop
+if (size(a4str) /= 6) error stop
+if (lbound(a4str, 1) /= -2) error stop
+if (ubound(a4str, 1) /= 3) error stop
+if (a4str(-2) /= 4_"sf456aq") error stop
+if (a4str(-1) /= 4_"3dtzu24") error stop
+if (a4str(0) /= 4_"_4fh7sm") error stop
+if (a4str(1) /= 4_"=ff85s7") error stop
+if (a4str(2) /= 4_"j=8af4d") error stop
+if (a4str(3) /= 4_".,A%Fsz") error stop
+
+!$omp target enter data map(alloc: a4str2)
+!$omp target map(alloc: a4str2)
+ if (.not. allocated(a4str2)) error stop
+ if (len(a4str2) /= 9) error stop
+ a4str2 = 4_"98765a23d"
+!$omp end target
+!$omp target exit data map(from: a4str2)
+if (.not. allocated(a4str2)) error stop
+if (len(a4str2) /= 9) error stop
+if (a4str2 /= 4_"98765a23d") error stop
+
+
+deallocate(dt%pc, dt%pc2)
+deallocate(dt%pcstr)
+deallocate(dt%pcstr2)
+
+deallocate(dt%pc4str)
+deallocate(dt%pc4str2)
+
+deallocate(ip, ip2, ia, ia2)
+deallocate(pstr)
+deallocate(pstr2)
+deallocate(astr)
+deallocate(astr2)
+
+deallocate(p4str)
+deallocate(p4str2)
+deallocate(a4str)
+deallocate(a4str2)
+end
diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-5.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-5.f90
new file mode 100644
index 0000000..cf75934
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-5.f90
@@ -0,0 +1,540 @@
+! Check that 'map((to)from:' properly works with
+! - deferred-length character strings
+! - arrays with array descriptors
+! For those, the array descriptor / string length must be mapped with 'to:'
+
+program main
+implicit none
+
+type t
+ integer :: ic(2:5), ic2
+ character(len=11) :: ccstr(3:4), ccstr2
+ character(len=11,kind=4) :: cc4str(3:7), cc4str2
+ integer, pointer :: pc(:), pc2
+ character(len=:), pointer :: pcstr(:), pcstr2
+ character(len=:,kind=4), pointer :: pc4str(:), pc4str2
+end type t
+
+type(t) :: dt
+
+integer :: ii(5), ii2
+character(len=11) :: clstr(-1:1), clstr2
+character(len=11,kind=4) :: cl4str(0:3), cl4str2
+integer, pointer :: ip(:), ip2
+integer, allocatable :: ia(:), ia2
+character(len=:), pointer :: pstr(:), pstr2
+character(len=:), allocatable :: astr(:), astr2
+character(len=:,kind=4), pointer :: p4str(:), p4str2
+character(len=:,kind=4), allocatable :: a4str(:), a4str2
+
+allocate(dt%pc(5), dt%pc2)
+allocate(character(len=2) :: dt%pcstr(2))
+allocate(character(len=4) :: dt%pcstr2)
+
+allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+allocate(character(len=5,kind=4) :: dt%pc4str2)
+
+allocate(ip(5), ip2, ia(8), ia2)
+allocate(character(len=2) :: pstr(-2:0))
+allocate(character(len=4) :: pstr2)
+allocate(character(len=6) :: astr(3:5))
+allocate(character(len=8) :: astr2)
+
+allocate(character(len=3,kind=4) :: p4str(2:4))
+allocate(character(len=5,kind=4) :: p4str2)
+allocate(character(len=7,kind=4) :: a4str(-2:3))
+allocate(character(len=9,kind=4) :: a4str2)
+
+
+! integer :: ic(2:5), ic2
+
+!$omp target enter data map(tofrom: dt%ic)
+!$omp target map(from: dt%ic)
+ if (size(dt%ic) /= 4) error stop
+ if (lbound(dt%ic, 1) /= 2) error stop
+ if (ubound(dt%ic, 1) /= 5) error stop
+ dt%ic = [22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%ic)
+if (size(dt%ic) /= 4) error stop
+if (lbound(dt%ic, 1) /= 2) error stop
+if (ubound(dt%ic, 1) /= 5) error stop
+if (any (dt%ic /= [22, 33, 44, 55])) error stop
+
+!$omp target enter data map(tofrom: dt%ic2)
+!$omp target map(from: dt%ic2)
+ dt%ic2 = 42
+!$omp end target
+!$omp target exit data map(from: dt%ic2)
+if (dt%ic2 /= 42) error stop
+
+
+! character(len=11) :: ccstr(3:4), ccstr2
+
+!$omp target enter data map(tofrom: dt%ccstr)
+!$omp target map(from: dt%ccstr)
+ if (len(dt%ccstr) /= 11) error stop
+ if (size(dt%ccstr) /= 2) error stop
+ if (lbound(dt%ccstr, 1) /= 3) error stop
+ if (ubound(dt%ccstr, 1) /= 4) error stop
+ dt%ccstr = ["12345678901", "abcdefghijk"]
+!$omp end target
+!$omp target exit data map(from: dt%ccstr)
+if (len(dt%ccstr) /= 11) error stop
+if (size(dt%ccstr) /= 2) error stop
+if (lbound(dt%ccstr, 1) /= 3) error stop
+if (ubound(dt%ccstr, 1) /= 4) error stop
+if (any (dt%ccstr /= ["12345678901", "abcdefghijk"])) error stop
+
+!$omp target enter data map(tofrom: dt%ccstr2)
+!$omp target map(from: dt%ccstr2)
+ if (len(dt%ccstr2) /= 11) error stop
+ dt%ccstr2 = "ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: dt%ccstr2)
+if (len(dt%ccstr2) /= 11) error stop
+if (dt%ccstr2 /= "ABCDEFGHIJK") error stop
+
+
+! character(len=11,kind=4) :: cc4str(3:7), cc4str2
+
+! Value check fails
+!$omp target enter data map(tofrom: dt%cc4str)
+!$omp target map(from: dt%cc4str)
+ if (len(dt%cc4str) /= 11) error stop
+ if (size(dt%cc4str) /= 5) error stop
+ if (lbound(dt%cc4str, 1) /= 3) error stop
+ if (ubound(dt%cc4str, 1) /= 7) error stop
+ dt%cc4str = [4_"12345678901", 4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4.", &
+ 4_"45ngwj56sj2"]
+!$omp end target
+!$omp target exit data map(from: dt%cc4str)
+if (len(dt%cc4str) /= 11) error stop
+if (size(dt%cc4str) /= 5) error stop
+if (lbound(dt%cc4str, 1) /= 3) error stop
+if (ubound(dt%cc4str, 1) /= 7) error stop
+if (dt%cc4str(3) /= 4_"12345678901") error stop
+if (dt%cc4str(4) /= 4_"abcdefghijk") error stop
+if (dt%cc4str(5) /= 4_"qerftcea6ds") error stop
+if (dt%cc4str(6) /= 4_"a1f9g37ga4.") error stop
+if (dt%cc4str(7) /= 4_"45ngwj56sj2") error stop
+
+!$omp target enter data map(tofrom: dt%cc4str2)
+!$omp target map(from: dt%cc4str2)
+ if (len(dt%cc4str2) /= 11) error stop
+ dt%cc4str2 = 4_"ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: dt%cc4str2)
+if (len(dt%cc4str2) /= 11) error stop
+if (dt%cc4str2 /= 4_"ABCDEFGHIJK") error stop
+
+
+! integer, pointer :: pc(:), pc2
+! allocate(dt%pc(5), dt%pc2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(tofrom: dt%pc)
+!$omp target map(from: dt%pc)
+ if (.not. associated(dt%pc)) error stop
+ if (size(dt%pc) /= 5) error stop
+ if (lbound(dt%pc, 1) /= 1) error stop
+ if (ubound(dt%pc, 1) /= 5) error stop
+ dt%pc = [11, 22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%pc)
+if (.not. associated(dt%pc)) error stop
+if (size(dt%pc) /= 5) error stop
+if (lbound(dt%pc, 1) /= 1) error stop
+if (ubound(dt%pc, 1) /= 5) error stop
+if (any (dt%pc /= [11, 22, 33, 44, 55])) error stop
+
+!$omp target enter data map(tofrom: dt%pc2)
+!$omp target map(from: dt%pc2)
+ if (.not. associated(dt%pc2)) error stop
+ dt%pc2 = 99
+!$omp end target
+!$omp target exit data map(from: dt%pc2)
+if (dt%pc2 /= 99) error stop
+if (.not. associated(dt%pc2)) error stop
+
+
+! character(len=:), pointer :: pcstr(:), pcstr2
+! allocate(character(len=2) :: dt%pcstr(2))
+! allocate(character(len=4) :: dt%pcstr2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(tofrom: dt%pcstr)
+!$omp target map(from: dt%pcstr)
+ if (.not. associated(dt%pcstr)) error stop
+ if (len(dt%pcstr) /= 2) error stop
+ if (size(dt%pcstr) /= 2) error stop
+ if (lbound(dt%pcstr, 1) /= 1) error stop
+ if (ubound(dt%pcstr, 1) /= 2) error stop
+ dt%pcstr = ["01", "jk"]
+!$omp end target
+!$omp target exit data map(from: dt%pcstr)
+if (.not. associated(dt%pcstr)) error stop
+if (len(dt%pcstr) /= 2) error stop
+if (size(dt%pcstr) /= 2) error stop
+if (lbound(dt%pcstr, 1) /= 1) error stop
+if (ubound(dt%pcstr, 1) /= 2) error stop
+if (any (dt%pcstr /= ["01", "jk"])) error stop
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x01
+
+!$omp target enter data map(tofrom: dt%pcstr2)
+!$omp target map(from: dt%pcstr2)
+ if (.not. associated(dt%pcstr2)) error stop
+ if (len(dt%pcstr2) /= 4) error stop
+ dt%pcstr2 = "HIJK"
+!$omp end target
+!$omp target exit data map(from: dt%pcstr2)
+if (.not. associated(dt%pcstr2)) error stop
+if (len(dt%pcstr2) /= 4) error stop
+if (dt%pcstr2 /= "HIJK") error stop
+
+
+! character(len=:,kind=4), pointer :: pc4str(:), pc4str2
+! allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+! allocate(character(len=5,kind=4) :: dt%pc4str2)
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(tofrom: dt%pc4str)
+!$omp target map(from: dt%pc4str)
+ if (.not. associated(dt%pc4str)) error stop
+ if (len(dt%pc4str) /= 3) error stop
+ if (size(dt%pc4str) /= 2) error stop
+ if (lbound(dt%pc4str, 1) /= 2) error stop
+ if (ubound(dt%pc4str, 1) /= 3) error stop
+ dt%pc4str = [4_"456", 4_"tzu"]
+!$omp end target
+!$omp target exit data map(from: dt%pc4str)
+if (.not. associated(dt%pc4str)) error stop
+if (len(dt%pc4str) /= 3) error stop
+if (size(dt%pc4str) /= 2) error stop
+if (lbound(dt%pc4str, 1) /= 2) error stop
+if (ubound(dt%pc4str, 1) /= 3) error stop
+if (dt%pc4str(2) /= 4_"456") error stop
+if (dt%pc4str(3) /= 4_"tzu") error stop
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x01
+
+!$omp target enter data map(tofrom: dt%pc4str2)
+!$omp target map(from: dt%pc4str2)
+ if (.not. associated(dt%pc4str2)) error stop
+ if (len(dt%pc4str2) /= 5) error stop
+ dt%pc4str2 = 4_"98765"
+!$omp end target
+!$omp target exit data map(from: dt%pc4str2)
+if (.not. associated(dt%pc4str2)) error stop
+if (len(dt%pc4str2) /= 5) error stop
+if (dt%pc4str2 /= 4_"98765") error stop
+
+
+! integer :: ii(5), ii2
+
+!$omp target enter data map(tofrom: ii)
+!$omp target map(from: ii)
+ if (size(ii) /= 5) error stop
+ if (lbound(ii, 1) /= 1) error stop
+ if (ubound(ii, 1) /= 5) error stop
+ ii = [-1, -2, -3, -4, -5]
+!$omp end target
+!$omp target exit data map(from: ii)
+if (size(ii) /= 5) error stop
+if (lbound(ii, 1) /= 1) error stop
+if (ubound(ii, 1) /= 5) error stop
+if (any (ii /= [-1, -2, -3, -4, -5])) error stop
+
+!$omp target enter data map(tofrom: ii2)
+!$omp target map(from: ii2)
+ ii2 = -410
+!$omp end target
+!$omp target exit data map(from: ii2)
+if (ii2 /= -410) error stop
+
+
+! character(len=11) :: clstr(-1:1), clstr2
+
+!$omp target enter data map(tofrom: clstr)
+!$omp target map(from: clstr)
+ if (len(clstr) /= 11) error stop
+ if (size(clstr) /= 3) error stop
+ if (lbound(clstr, 1) /= -1) error stop
+ if (ubound(clstr, 1) /= 1) error stop
+ clstr = ["12345678901", "abcdefghijk", "ABCDEFGHIJK"]
+!$omp end target
+!$omp target exit data map(from: clstr)
+if (len(clstr) /= 11) error stop
+if (size(clstr) /= 3) error stop
+if (lbound(clstr, 1) /= -1) error stop
+if (ubound(clstr, 1) /= 1) error stop
+if (any (clstr /= ["12345678901", "abcdefghijk", "ABCDEFGHIJK"])) error stop
+
+!$omp target enter data map(tofrom: clstr2)
+!$omp target map(from: clstr2)
+ if (len(clstr2) /= 11) error stop
+ clstr2 = "ABCDEFghijk"
+!$omp end target
+!$omp target exit data map(from: clstr2)
+if (len(clstr2) /= 11) error stop
+if (clstr2 /= "ABCDEFghijk") error stop
+
+
+! character(len=11,kind=4) :: cl4str(0:3), cl4str2
+
+!$omp target enter data map(tofrom: cl4str)
+!$omp target map(from: cl4str)
+ if (len(cl4str) /= 11) error stop
+ if (size(cl4str) /= 4) error stop
+ if (lbound(cl4str, 1) /= 0) error stop
+ if (ubound(cl4str, 1) /= 3) error stop
+ cl4str = [4_"12345678901", 4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4."]
+!$omp end target
+!$omp target exit data map(from: cl4str)
+if (len(cl4str) /= 11) error stop
+if (size(cl4str) /= 4) error stop
+if (lbound(cl4str, 1) /= 0) error stop
+if (ubound(cl4str, 1) /= 3) error stop
+if (cl4str(0) /= 4_"12345678901") error stop
+if (cl4str(1) /= 4_"abcdefghijk") error stop
+if (cl4str(2) /= 4_"qerftcea6ds") error stop
+if (cl4str(3) /= 4_"a1f9g37ga4.") error stop
+
+!$omp target enter data map(tofrom: cl4str2)
+!$omp target map(from: cl4str2)
+ if (len(cl4str2) /= 11) error stop
+ cl4str2 = 4_"ABCDEFGHIJK"
+!$omp end target
+!$omp target exit data map(from: cl4str2)
+if (len(cl4str2) /= 11) error stop
+if (cl4str2 /= 4_"ABCDEFGHIJK") error stop
+
+
+! allocate(ip(5), ip2, ia(8), ia2)
+
+!$omp target enter data map(tofrom: ip)
+!$omp target map(from: ip)
+ if (.not. associated(ip)) error stop
+ if (size(ip) /= 5) error stop
+ if (lbound(ip, 1) /= 1) error stop
+ if (ubound(ip, 1) /= 5) error stop
+ ip = [11, 22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: ip)
+if (.not. associated(ip)) error stop
+if (size(ip) /= 5) error stop
+if (lbound(ip, 1) /= 1) error stop
+if (ubound(ip, 1) /= 5) error stop
+if (any (ip /= [11, 22, 33, 44, 55])) error stop
+
+!$omp target enter data map(tofrom: ip2)
+!$omp target map(from: ip2)
+ if (.not. associated(ip2)) error stop
+ ip2 = 99
+!$omp end target
+!$omp target exit data map(from: ip2)
+if (ip2 /= 99) error stop
+if (.not. associated(ip2)) error stop
+
+
+! allocate(ip(5), ip2, ia(8), ia2)
+
+!$omp target enter data map(tofrom: ia)
+!$omp target map(from: ia)
+ if (.not. allocated(ia)) error stop
+ if (size(ia) /= 8) error stop
+ if (lbound(ia, 1) /= 1) error stop
+ if (ubound(ia, 1) /= 8) error stop
+ ia = [1,2,3,4,5,6,7,8]
+!$omp end target
+!$omp target exit data map(from: ia)
+if (.not. allocated(ia)) error stop
+if (size(ia) /= 8) error stop
+if (lbound(ia, 1) /= 1) error stop
+if (ubound(ia, 1) /= 8) error stop
+if (any (ia /= [1,2,3,4,5,6,7,8])) error stop
+
+!$omp target enter data map(tofrom: ia2)
+!$omp target map(from: ia2)
+ if (.not. allocated(ia2)) error stop
+ ia2 = 102
+!$omp end target
+!$omp target exit data map(from: ia2)
+if (ia2 /= 102) error stop
+if (.not. allocated(ia2)) error stop
+
+
+! character(len=:), pointer :: pstr(:), pstr2
+! allocate(character(len=2) :: pstr(-2:0))
+! allocate(character(len=4) :: pstr2)
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(tofrom: pstr)
+!$omp target map(from: pstr)
+ if (.not. associated(pstr)) error stop
+ if (len(pstr) /= 2) error stop
+ if (size(pstr) /= 3) error stop
+ if (lbound(pstr, 1) /= -2) error stop
+ if (ubound(pstr, 1) /= 0) error stop
+ pstr = ["01", "jk", "aq"]
+!$omp end target
+!$omp target exit data map(from: pstr)
+if (.not. associated(pstr)) error stop
+if (len(pstr) /= 2) error stop
+if (size(pstr) /= 3) error stop
+if (lbound(pstr, 1) /= -2) error stop
+if (ubound(pstr, 1) /= 0) error stop
+if (any (pstr /= ["01", "jk", "aq"])) error stop
+
+!$omp target enter data map(tofrom: pstr2)
+!$omp target map(from: pstr2)
+ if (.not. associated(pstr2)) error stop
+ if (len(pstr2) /= 4) error stop
+ pstr2 = "HIJK"
+!$omp end target
+!$omp target exit data map(from: pstr2)
+if (.not. associated(pstr2)) error stop
+if (len(pstr2) /= 4) error stop
+if (pstr2 /= "HIJK") error stop
+
+
+! character(len=:), allocatable :: astr(:), astr2
+! allocate(character(len=6) :: astr(3:5))
+! allocate(character(len=8) :: astr2)
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(tofrom: astr)
+!$omp target map(from: astr)
+ if (.not. allocated(astr)) error stop
+ if (len(astr) /= 6) error stop
+ if (size(astr) /= 3) error stop
+ if (lbound(astr, 1) /= 3) error stop
+ if (ubound(astr, 1) /= 5) error stop
+ astr = ["01db45", "jk$D%S", "zutg47"]
+!$omp end target
+!$omp target exit data map(from: astr)
+if (.not. allocated(astr)) error stop
+if (len(astr) /= 6) error stop
+if (size(astr) /= 3) error stop
+if (lbound(astr, 1) /= 3) error stop
+if (ubound(astr, 1) /= 5) error stop
+if (any (astr /= ["01db45", "jk$D%S", "zutg47"])) error stop
+
+! libgomp: nvptx_alloc error: out of memory
+
+!$omp target enter data map(tofrom: astr2)
+!$omp target map(from: astr2)
+ if (.not. allocated(astr2)) error stop
+ if (len(astr2) /= 8) error stop
+ astr2 = "HIJKhijk"
+!$omp end target
+!$omp target exit data map(from: astr2)
+if (.not. allocated(astr2)) error stop
+if (len(astr2) /= 8) error stop
+if (astr2 /= "HIJKhijk") error stop
+
+
+! character(len=:,kind=4), pointer :: p4str(:), p4str2
+! allocate(character(len=3,kind=4) :: p4str(2:4))
+! allocate(character(len=5,kind=4) :: p4str2)
+
+! FAILS with value check
+
+!$omp target enter data map(tofrom: p4str)
+!$omp target map(from: p4str)
+ if (.not. associated(p4str)) error stop
+ if (len(p4str) /= 3) error stop
+ if (size(p4str) /= 3) error stop
+ if (lbound(p4str, 1) /= 2) error stop
+ if (ubound(p4str, 1) /= 4) error stop
+ p4str(:) = [4_"f85", 4_"8af", 4_"A%F"]
+!$omp end target
+!$omp target exit data map(from: p4str)
+if (.not. associated(p4str)) error stop
+if (len(p4str) /= 3) error stop
+if (size(p4str) /= 3) error stop
+if (lbound(p4str, 1) /= 2) error stop
+if (ubound(p4str, 1) /= 4) error stop
+if (p4str(2) /= 4_"f85") error stop
+if (p4str(3) /= 4_"8af") error stop
+if (p4str(4) /= 4_"A%F") error stop
+
+!$omp target enter data map(tofrom: p4str2)
+!$omp target map(from: p4str2)
+ if (.not. associated(p4str2)) error stop
+ if (len(p4str2) /= 5) error stop
+ p4str2 = 4_"9875a"
+!$omp end target
+!$omp target exit data map(from: p4str2)
+if (.not. associated(p4str2)) error stop
+if (len(p4str2) /= 5) error stop
+if (p4str2 /= 4_"9875a") error stop
+
+
+! character(len=:,kind=4), allocatable :: a4str(:), a4str2
+! allocate(character(len=7,kind=4) :: a4str(-2:3))
+! allocate(character(len=9,kind=4) :: a4str2)
+
+! libgomp: Trying to map into device [0x1027ba0..0x251050bb9c9ebba0) object when [0x7ffd026e6708..0x7ffd026e6710) is already mapped
+
+!$omp target enter data map(tofrom: a4str)
+!$omp target map(from: a4str)
+ if (.not. allocated(a4str)) error stop
+ if (len(a4str) /= 7) error stop
+ if (size(a4str) /= 6) error stop
+ if (lbound(a4str, 1) /= -2) error stop
+ if (ubound(a4str, 1) /= 3) error stop
+ ! See PR fortran/107508 why '(:)' is required
+ a4str(:) = [4_"sf456aq", 4_"3dtzu24", 4_"_4fh7sm", 4_"=ff85s7", 4_"j=8af4d", 4_".,A%Fsz"]
+!$omp end target
+!$omp target exit data map(from: a4str)
+if (.not. allocated(a4str)) error stop
+if (len(a4str) /= 7) error stop
+if (size(a4str) /= 6) error stop
+if (lbound(a4str, 1) /= -2) error stop
+if (ubound(a4str, 1) /= 3) error stop
+if (a4str(-2) /= 4_"sf456aq") error stop
+if (a4str(-1) /= 4_"3dtzu24") error stop
+if (a4str(0) /= 4_"_4fh7sm") error stop
+if (a4str(1) /= 4_"=ff85s7") error stop
+if (a4str(2) /= 4_"j=8af4d") error stop
+if (a4str(3) /= 4_".,A%Fsz") error stop
+
+!$omp target enter data map(tofrom: a4str2)
+!$omp target map(from: a4str2)
+ if (.not. allocated(a4str2)) error stop
+ if (len(a4str2) /= 9) error stop
+ a4str2 = 4_"98765a23d"
+!$omp end target
+!$omp target exit data map(from: a4str2)
+if (.not. allocated(a4str2)) error stop
+if (len(a4str2) /= 9) error stop
+if (a4str2 /= 4_"98765a23d") error stop
+
+
+deallocate(dt%pc, dt%pc2)
+deallocate(dt%pcstr)
+deallocate(dt%pcstr2)
+
+deallocate(dt%pc4str)
+deallocate(dt%pc4str2)
+
+deallocate(ip, ip2, ia, ia2)
+deallocate(pstr)
+deallocate(pstr2)
+deallocate(astr)
+deallocate(astr2)
+
+deallocate(p4str)
+deallocate(p4str2)
+deallocate(a4str)
+deallocate(a4str2)
+end
diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90
new file mode 100644
index 0000000..80d30ed
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-6.f90
@@ -0,0 +1,392 @@
+! Check that 'map(alloc:' properly works with
+! - deferred-length character strings
+! - arrays with array descriptors
+! For those, the array descriptor / string length must be mapped with 'to:'
+
+program main
+implicit none
+
+type t
+ integer :: ic(2:5)
+ character(len=11) :: ccstr(3:4)
+ character(len=11,kind=4) :: cc4str(3:7)
+ integer, pointer :: pc(:)
+ character(len=:), pointer :: pcstr(:)
+ character(len=:,kind=4), pointer :: pc4str(:)
+end type t
+
+type(t) :: dt
+
+integer :: ii(5)
+character(len=11) :: clstr(-1:1)
+character(len=11,kind=4) :: cl4str(0:3)
+integer, pointer :: ip(:)
+integer, allocatable :: ia(:)
+character(len=:), pointer :: pstr(:)
+character(len=:), allocatable :: astr(:)
+character(len=:,kind=4), pointer :: p4str(:)
+character(len=:,kind=4), allocatable :: a4str(:)
+
+allocate(dt%pc(5))
+allocate(character(len=2) :: dt%pcstr(2))
+
+allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+
+allocate(ip(5), ia(8))
+allocate(character(len=2) :: pstr(-2:0))
+allocate(character(len=6) :: astr(3:5))
+
+allocate(character(len=3,kind=4) :: p4str(2:4))
+allocate(character(len=7,kind=4) :: a4str(-2:3))
+
+
+! integer :: ic(2:5)
+
+!$omp target enter data map(alloc: dt%ic(3:5))
+dt%ic(2) = 22
+!$omp target map(alloc: dt%ic(3:5))
+ if (size(dt%ic) /= 4) error stop
+ if (lbound(dt%ic, 1) /= 2) error stop
+ if (ubound(dt%ic, 1) /= 5) error stop
+ dt%ic(3:5) = [33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%ic(3:5))
+if (size(dt%ic) /= 4) error stop
+if (lbound(dt%ic, 1) /= 2) error stop
+if (ubound(dt%ic, 1) /= 5) error stop
+if (any (dt%ic /= [22, 33, 44, 55])) error stop
+
+! character(len=11) :: ccstr(3:4)
+
+!$omp target enter data map(alloc: dt%ccstr(4:4))
+dt%ccstr(3) = "12345678901"
+!$omp target map(alloc: dt%ccstr(4:4))
+ if (len(dt%ccstr) /= 11) error stop
+ if (size(dt%ccstr) /= 2) error stop
+ if (lbound(dt%ccstr, 1) /= 3) error stop
+ if (ubound(dt%ccstr, 1) /= 4) error stop
+ dt%ccstr(4:4) = ["abcdefghijk"]
+!$omp end target
+!$omp target exit data map(from: dt%ccstr(4:4))
+if (len(dt%ccstr) /= 11) error stop
+if (size(dt%ccstr) /= 2) error stop
+if (lbound(dt%ccstr, 1) /= 3) error stop
+if (ubound(dt%ccstr, 1) /= 4) error stop
+if (any (dt%ccstr /= ["12345678901", "abcdefghijk"])) error stop
+
+
+! character(len=11,kind=4) :: cc4str(3:7)
+
+! Value check fails
+!$omp target enter data map(alloc: dt%cc4str(4:7))
+dt%cc4str(3) = 4_"12345678901"
+!$omp target map(alloc: dt%cc4str(4:7))
+ if (len(dt%cc4str) /= 11) error stop
+ if (size(dt%cc4str) /= 5) error stop
+ if (lbound(dt%cc4str, 1) /= 3) error stop
+ if (ubound(dt%cc4str, 1) /= 7) error stop
+ dt%cc4str(4:7) = [4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4.", &
+ 4_"45ngwj56sj2"]
+!$omp end target
+!$omp target exit data map(from: dt%cc4str(4:7))
+if (len(dt%cc4str) /= 11) error stop
+if (size(dt%cc4str) /= 5) error stop
+if (lbound(dt%cc4str, 1) /= 3) error stop
+if (ubound(dt%cc4str, 1) /= 7) error stop
+if (dt%cc4str(3) /= 4_"12345678901") error stop
+if (dt%cc4str(4) /= 4_"abcdefghijk") error stop
+if (dt%cc4str(5) /= 4_"qerftcea6ds") error stop
+if (dt%cc4str(6) /= 4_"a1f9g37ga4.") error stop
+if (dt%cc4str(7) /= 4_"45ngwj56sj2") error stop
+
+! integer, pointer :: pc(:)
+! allocate(dt%pc(5))
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+!$omp target enter data map(alloc: dt%pc(2:5))
+dt%pc(1) = 11
+!$omp target map(alloc: dt%pc(2:5))
+ if (.not. associated(dt%pc)) error stop
+ if (size(dt%pc) /= 5) error stop
+ if (lbound(dt%pc, 1) /= 1) error stop
+ if (ubound(dt%pc, 1) /= 5) error stop
+ dt%pc(2:5) = [22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: dt%pc(2:5))
+if (.not. associated(dt%pc)) error stop
+if (size(dt%pc) /= 5) error stop
+if (lbound(dt%pc, 1) /= 1) error stop
+if (ubound(dt%pc, 1) /= 5) error stop
+if (any (dt%pc /= [11, 22, 33, 44, 55])) error stop
+
+! character(len=:), pointer :: pcstr(:)
+! allocate(character(len=2) :: dt%pcstr(2))
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+
+! FIXME: Disabled befause of PR108837
+!
+!!$omp target enter data map(alloc: dt%pcstr(2:2))
+!dt%pcstr(1) = "01"
+!!$omp target map(alloc: dt%pcstr(2:2))
+! if (.not. associated(dt%pcstr)) error stop
+! if (len(dt%pcstr) /= 2) error stop
+! if (size(dt%pcstr) /= 2) error stop
+! if (lbound(dt%pcstr, 1) /= 1) error stop
+! if (ubound(dt%pcstr, 1) /= 2) error stop
+! dt%pcstr(2:2) = ["jk"]
+!!$omp end target
+!!$omp target exit data map(from: dt%pcstr(2:2))
+!if (.not. associated(dt%pcstr)) error stop
+!if (len(dt%pcstr) /= 2) error stop
+!if (size(dt%pcstr) /= 2) error stop
+!if (lbound(dt%pcstr, 1) /= 1) error stop
+!if (ubound(dt%pcstr, 1) /= 2) error stop
+!if (any (dt%pcstr /= ["01", "jk"])) error stop
+
+
+! character(len=:,kind=4), pointer :: pc4str(:)
+! allocate(character(len=3,kind=4) :: dt%pc4str(2:3))
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x00
+! structure element when other mapped elements from the same structure weren't mapped together with it
+
+! FIXME: Disabled befause of PR108837
+!
+!!$omp target enter data map(alloc: dt%pc4str(3:3))
+!dt%pc4str(2) = 4_"456"
+!!$omp target map(alloc: dt%pc4str(3:3))
+! if (.not. associated(dt%pc4str)) error stop
+! if (len(dt%pc4str) /= 3) error stop
+! if (size(dt%pc4str) /= 2) error stop
+! if (lbound(dt%pc4str, 1) /= 2) error stop
+! if (ubound(dt%pc4str, 1) /= 3) error stop
+! dt%pc4str(3:3) = [4_"tzu"]
+!!$omp end target
+!!$omp target exit data map(from: dt%pc4str(3:3))
+!if (.not. associated(dt%pc4str)) error stop
+!if (len(dt%pc4str) /= 3) error stop
+!if (size(dt%pc4str) /= 2) error stop
+!if (lbound(dt%pc4str, 1) /= 2) error stop
+!if (ubound(dt%pc4str, 1) /= 3) error stop
+!if (dt%pc4str(2) /= 4_"456") error stop
+!if (dt%pc4str(3) /= 4_"tzu") error stop
+
+! libgomp: GOMP_target_enter_exit_data unhandled kind 0x01
+
+! integer :: ii(5)
+
+!$omp target enter data map(alloc: ii(2:5))
+ii(1) = -1
+!$omp target map(alloc: ii(2:5))
+ if (size(ii) /= 5) error stop
+ if (lbound(ii, 1) /= 1) error stop
+ if (ubound(ii, 1) /= 5) error stop
+ ii(2:5) = [-2, -3, -4, -5]
+!$omp end target
+!$omp target exit data map(from: ii(2:5))
+if (size(ii) /= 5) error stop
+if (lbound(ii, 1) /= 1) error stop
+if (ubound(ii, 1) /= 5) error stop
+if (any (ii /= [-1, -2, -3, -4, -5])) error stop
+
+
+! character(len=11) :: clstr(-1:1)
+
+!$omp target enter data map(alloc: clstr(0:1))
+clstr(-1) = "12345678901"
+!$omp target map(alloc: clstr(0:1))
+ if (len(clstr) /= 11) error stop
+ if (size(clstr) /= 3) error stop
+ if (lbound(clstr, 1) /= -1) error stop
+ if (ubound(clstr, 1) /= 1) error stop
+ clstr(0:1) = ["abcdefghijk", "ABCDEFGHIJK"]
+!$omp end target
+!$omp target exit data map(from: clstr(0:1))
+if (len(clstr) /= 11) error stop
+if (size(clstr) /= 3) error stop
+if (lbound(clstr, 1) /= -1) error stop
+if (ubound(clstr, 1) /= 1) error stop
+if (any (clstr /= ["12345678901", "abcdefghijk", "ABCDEFGHIJK"])) error stop
+
+! character(len=11,kind=4) :: cl4str(0:3)
+
+!$omp target enter data map(alloc: cl4str(1:3))
+cl4str(0) = 4_"12345678901"
+!$omp target map(alloc: cl4str(1:3))
+ if (len(cl4str) /= 11) error stop
+ if (size(cl4str) /= 4) error stop
+ if (lbound(cl4str, 1) /= 0) error stop
+ if (ubound(cl4str, 1) /= 3) error stop
+ cl4str(1:3) = [4_"abcdefghijk", &
+ 4_"qerftcea6ds", 4_"a1f9g37ga4."]
+!$omp end target
+!$omp target exit data map(from: cl4str(1:3))
+if (len(cl4str) /= 11) error stop
+if (size(cl4str) /= 4) error stop
+if (lbound(cl4str, 1) /= 0) error stop
+if (ubound(cl4str, 1) /= 3) error stop
+if (cl4str(0) /= 4_"12345678901") error stop
+if (cl4str(1) /= 4_"abcdefghijk") error stop
+if (cl4str(2) /= 4_"qerftcea6ds") error stop
+if (cl4str(3) /= 4_"a1f9g37ga4.") error stop
+
+
+! allocate(ip(5), ia(8))
+
+!$omp target enter data map(alloc: ip(2:5))
+ip(1) = 11
+!$omp target map(alloc: ip(2:5))
+ if (.not. associated(ip)) error stop
+ if (size(ip) /= 5) error stop
+ if (lbound(ip, 1) /= 1) error stop
+ if (ubound(ip, 1) /= 5) error stop
+ ip(2:5) = [22, 33, 44, 55]
+!$omp end target
+!$omp target exit data map(from: ip(2:5))
+if (.not. associated(ip)) error stop
+if (size(ip) /= 5) error stop
+if (lbound(ip, 1) /= 1) error stop
+if (ubound(ip, 1) /= 5) error stop
+if (any (ip /= [11, 22, 33, 44, 55])) error stop
+
+! allocate(ip(5), ia(8))
+
+!$omp target enter data map(alloc: ia(2:8))
+ia(1) = 1
+!$omp target map(alloc: ia(2:8))
+ if (.not. allocated(ia)) error stop
+ if (size(ia) /= 8) error stop
+ if (lbound(ia, 1) /= 1) error stop
+ if (ubound(ia, 1) /= 8) error stop
+ ia(2:8) = [2,3,4,5,6,7,8]
+!$omp end target
+!$omp target exit data map(from: ia(2:8))
+if (.not. allocated(ia)) error stop
+if (size(ia) /= 8) error stop
+if (lbound(ia, 1) /= 1) error stop
+if (ubound(ia, 1) /= 8) error stop
+if (any (ia /= [1,2,3,4,5,6,7,8])) error stop
+
+
+! character(len=:), pointer :: pstr(:)
+! allocate(character(len=2) :: pstr(-2:0))
+
+! libgomp: nvptx_alloc error: out of memory
+
+! FIXME: array offset wrongly calculated as it uses TYPE_SIZE_UNIT, which is a SAVE_EXPR
+!
+!!$omp target enter data map(alloc: pstr(-1:0))
+!pstr(-2) = "01"
+!!$omp target map(alloc: pstr(-1:0))
+! if (.not. associated(pstr)) error stop
+! if (len(pstr) /= 2) error stop
+! if (size(pstr) /= 3) error stop
+! if (lbound(pstr, 1) /= -2) error stop
+! if (ubound(pstr, 1) /= 0) error stop
+! pstr(-1:0) = ["jk", "aq"]
+!!$omp end target
+!!$omp target exit data map(from: pstr(-1:0))
+!if (.not. associated(pstr)) error stop
+!if (len(pstr) /= 2) error stop
+!if (size(pstr) /= 3) error stop
+!if (lbound(pstr, 1) /= -2) error stop
+!if (ubound(pstr, 1) /= 0) error stop
+!if (any (pstr /= ["01", "jk", "aq"])) error stop
+
+
+! character(len=:), allocatable :: astr(:)
+! allocate(character(len=6) :: astr(3:5))
+
+! libgomp: nvptx_alloc error: out of memory
+
+! FIXME
+!!$omp target enter data map(alloc: astr(4:5))
+!astr(3) = "01db45"
+!!$omp target map(alloc: astr(4:5))
+! if (.not. allocated(astr)) error stop
+! if (len(astr) /= 6) error stop
+! if (size(astr) /= 3) error stop
+! if (lbound(astr, 1) /= 3) error stop
+! if (ubound(astr, 1) /= 5) error stop
+!!! astr(4:5) = ["jk$D%S", "zutg47"]
+!!$omp end target
+!!!$omp target exit data map(from: astr(4:5))
+!!if (.not. allocated(astr)) error stop
+!!!if (len(astr) /= 6) error stop
+!if (size(astr) /= 3) error stop
+!if (lbound(astr, 1) /= 3) error stop
+!if (ubound(astr, 1) /= 5) error stop
+!if (any (astr /= ["01db45", "jk$D%S", "zutg47"])) error stop
+!
+
+! character(len=:,kind=4), pointer :: p4str(:)
+! allocate(character(len=3,kind=4) :: p4str(2:4))
+
+! FAILS with value check
+
+! FIXME: array offset wrongly calculated as it uses TYPE_SIZE_UNIT, which is a SAVE_EXPR
+!
+!!$omp target enter data map(alloc: p4str(3:4))
+!p4str(2) = 4_"f85"
+!!$omp target map(alloc: p4str(3:4))
+! if (.not. associated(p4str)) error stop
+! if (len(p4str) /= 3) error stop
+! if (size(p4str) /= 3) error stop
+! if (lbound(p4str, 1) /= 2) error stop
+! if (ubound(p4str, 1) /= 4) error stop
+! p4str(3:4) = [4_"8af", 4_"A%F"]
+!!$omp end target
+!!$omp target exit data map(from: p4str(3:4))
+!if (.not. associated(p4str)) error stop
+!if (len(p4str) /= 3) error stop
+!if (size(p4str) /= 3) error stop
+!if (lbound(p4str, 1) /= 2) error stop
+!if (ubound(p4str, 1) /= 4) error stop
+!if (p4str(2) /= 4_"f85") error stop
+!if (p4str(3) /= 4_"8af") error stop
+!if (p4str(4) /= 4_"A%F") error stop
+
+! character(len=:,kind=4), allocatable :: a4str(:)
+! allocate(character(len=7,kind=4) :: a4str(-2:3))
+
+! libgomp: Trying to map into device [0x1027ba0..0x251050bb9c9ebba0) object when [0x7ffd026e6708..0x7ffd026e6710) is already mapped
+
+! FIXME: Disabled befause of PR108838
+!!$omp target enter data map(alloc: a4str(-1:3))
+!!a4str(-2) = 4_"sf456aq"
+!!$omp target map(alloc: a4str(-1:3))
+! if (.not. allocated(a4str)) error stop
+! if (len(a4str) /= 7) error stop
+! if (size(a4str) /= 6) error stop
+! if (lbound(a4str, 1) /= -2) error stop
+! if (ubound(a4str, 1) /= 3) error stop
+! a4str(-1:3) = [4_"3dtzu24", 4_"_4fh7sm", 4_"=ff85s7", 4_"j=8af4d", 4_".,A%Fsz"]
+!!$omp end target
+!!$omp target exit data map(from: a4str(-1:3))
+!if (.not. allocated(a4str)) error stop
+!if (len(a4str) /= 7) error stop
+!if (size(a4str) /= 6) error stop
+!if (lbound(a4str, 1) /= -2) error stop
+!if (ubound(a4str, 1) /= 3) error stop
+!if (a4str(-2) /= 4_"sf456aq") error stop
+!if (a4str(-1) /= 4_"3dtzu24") error stop
+!if (a4str(0) /= 4_"_4fh7sm") error stop
+!if (a4str(1) /= 4_"=ff85s7") error stop
+!if (a4str(2) /= 4_"j=8af4d") error stop
+!if (a4str(3) /= 4_".,A%Fsz") error stop
+
+deallocate(dt%pc)
+deallocate(dt%pcstr)
+
+deallocate(dt%pc4str)
+
+deallocate(ip, ia)
+deallocate(pstr)
+deallocate(astr)
+
+deallocate(p4str)
+deallocate(a4str)
+end
diff --git a/libgomp/testsuite/libgomp.fortran/target-enter-data-7.f90 b/libgomp/testsuite/libgomp.fortran/target-enter-data-7.f90
new file mode 100644
index 0000000..f129f55
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-enter-data-7.f90
@@ -0,0 +1,78 @@
+module m
+ implicit none
+ character(len=:), allocatable :: strA(:), strA2
+ character(len=:), pointer :: strP(:), strP2
+ !$omp declare target enter(strA,strA2,strP,strP2)
+contains
+ subroutine opt_map(str1, str2, str3)
+ character(len=:), allocatable :: str1, str2, str3, str4
+ optional :: str2, str3
+
+ if (.not.present(str2)) error stop
+ if (present(str3)) error stop
+
+ !$omp target map(str1,str2,str3,str4)
+ if (allocated(str1)) error stop
+ if (allocated(str2)) error stop
+ if (present(str3)) error stop
+ if (allocated(str4)) error stop
+ !$omp end target
+ end
+ subroutine call_opt()
+ character(len=:), allocatable :: str1, str2
+ call opt_map(str1, str2)
+ end
+ subroutine test
+ !$omp declare target
+ if (.not. allocated(strA)) error stop
+ !if (.not. allocated(strA2)) error stop
+ if (.not. associated(strP)) error stop
+ !if (.not. associated(strP2)) error stop
+
+ ! ensure length was updated as well
+ if (len(strA) /= 3) error stop
+ if (len(strA2) /= 5) error stop
+ if (len(strP) /= 4) error stop
+ if (len(strP2) /= 8) error stop
+! if (any (strA /= ['Hav', 'e f', 'un!'])) error stop
+! if (strA2 /= 'Hello') error stop
+! if (any (strP /= ['abcd', 'efgh', 'ijkl'])) error stop
+! if (strP2 /= 'TestCase') error stop
+!
+! strA = ['123', '456', '789']
+! strA2 = 'World'
+! strP = ['ABCD', 'EFGH', 'IJKL']
+! strP2 = 'Passed!!'
+ end
+end
+
+program main
+ use m
+ implicit none
+ call call_opt
+
+ strA = ['Hav', 'e f', 'un!']
+ strA2 = 'Hello'
+ allocate(character(len=4) :: strP(3))
+ strP = ['abcd', 'efgh', 'ijkl']
+ allocate(character(len=8) :: strP2)
+ strP2 = 'TestCase'
+
+ !$omp target enter data map(always, to: strA, strA2)
+ !$omp target enter data map(to: strP, strP2)
+ !$omp target
+ call test()
+ !$omp end target
+ !$omp target exit data map(always, from: strA, strA2, strP, strP2)
+
+ if (len(strA) /= 3) error stop
+ if (len(strA2) /= 5) error stop
+ if (len(strP) /= 4) error stop
+ if (len(strP2) /= 8) error stop
+! if (any (strA /= ['123', '456', '789'])) error stop
+! if (strA2 /= 'World') error stop
+! if (any(strP /= ['ABCD', 'EFGH', 'IJKL'])) error stop
+! if (strP2 /= 'Passed!!') error stop
+
+! deallocate(strP, strP2, strA, strA2)
+end
diff --git a/libgomp/testsuite/libgomp.fortran/target-present-1.f90 b/libgomp/testsuite/libgomp.fortran/target-present-1.f90
new file mode 100644
index 0000000..fc13609
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-present-1.f90
@@ -0,0 +1,31 @@
+program main
+ implicit none
+ integer, parameter :: N = 100
+ integer :: a(N), b(N), c(N), i
+
+ do i = 1, N
+ a(i) = i * 2
+ b(i) = i * 3 + 1
+ end do
+
+ !$omp target enter data map (alloc: a)
+ ! a has already been allocated, so this should be okay.
+ !$omp target map (present, to: a)
+ do i = 1, N
+ c(i) = a(i)
+ end do
+ !$omp end target
+
+ print *, "CheCKpOInT"
+ ! { dg-output "CheCKpOInT(\n|\r\n|\r).*" }
+
+ ! b has not been allocated, so this should result in an error.
+ ! { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } }
+ ! { dg-shouldfail "present error triggered" { offload_device_nonshared_as } }
+ !$omp target map (present, to: b)
+ do i = 1, N
+ c(i) = c(i) + b(i)
+ end do
+ !$omp end target
+ !$omp target exit data map (from: c)
+end program
diff --git a/libgomp/testsuite/libgomp.fortran/target-present-2.f90 b/libgomp/testsuite/libgomp.fortran/target-present-2.f90
new file mode 100644
index 0000000..524d01d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-present-2.f90
@@ -0,0 +1,31 @@
+program main
+ implicit none
+ integer, parameter :: N = 100
+ integer :: a(N), b(N), c(N), i
+
+ do i = 1, N
+ a(i) = i * 2
+ b(i) = i * 3 + 1
+ end do
+
+ !$omp target enter data map (alloc: a, c, i)
+ ! a, c, and i have already been allocated, so this should be okay.
+ !$omp target defaultmap (present)
+ do i = 1, N
+ c(i) = a(i)
+ end do
+ !$omp end target
+
+ print *, "CheCKpOInT"
+ ! { dg-output "CheCKpOInT(\n|\r\n|\r).*" }
+
+ ! b has not been allocated, so this should result in an error.
+ ! { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } }
+ ! { dg-shouldfail "present error triggered" { offload_device_nonshared_as } }
+ !$omp target defaultmap (present)
+ do i = 1, N
+ c(i) = c(i) + b(i)
+ end do
+ !$omp end target
+!$omp target exit data map (from: c)
+end program
diff --git a/libgomp/testsuite/libgomp.fortran/target-present-3.f90 b/libgomp/testsuite/libgomp.fortran/target-present-3.f90
new file mode 100644
index 0000000..dd4af4c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-present-3.f90
@@ -0,0 +1,36 @@
+program main
+ implicit none
+ integer, parameter :: N = 100
+ integer :: a(N), b(N), c(N), i
+
+ do i = 1, N
+ a(i) = i * 2
+ b(i) = i * 3 + 1
+ end do
+
+ !$omp target enter data map (alloc: a, c)
+
+ ! This should work as a has already been allocated.
+ !$omp target update to (present: a)
+
+ !$omp target map(present, alloc: a, c)
+ do i = 1, N
+ if (a(i) /= i * 2) stop 1
+ c(i) = 23 * i
+ end do
+ !$omp end target
+
+ !$omp target update from (present: c)
+ do i = 1, N
+ if (c(i) /= 23 * i) stop 1
+ end do
+
+ print *, "CheCKpOInT"
+ ! { dg-output "CheCKpOInT(\n|\r\n|\r).*" }
+
+ ! This should fail as b has not been allocated.
+ ! { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" { target offload_device_nonshared_as } }
+ ! { dg-shouldfail "present error triggered" { offload_device_nonshared_as } }
+ !$omp target update to (present: b)
+ !$omp target exit data map (from: c)
+end program
diff --git a/libgomp/testsuite/libgomp.graphite/graphite.exp b/libgomp/testsuite/libgomp.graphite/graphite.exp
index 1260dc9..bc3a82d 100644
--- a/libgomp/testsuite/libgomp.graphite/graphite.exp
+++ b/libgomp/testsuite/libgomp.graphite/graphite.exp
@@ -14,17 +14,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-if [info exists lang_library_path] then {
- unset lang_library_path
- unset lang_link_flags
-}
-if [info exists lang_test_file] then {
- unset lang_test_file
-}
-if [info exists lang_include_flags] then {
- unset lang_include_flags
-}
-
load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
@@ -36,6 +25,7 @@ if ![check_effective_target_fgraphite] {
return
}
+lappend ALWAYS_CFLAGS "compiler=$GCC_UNDER_TEST"
# Flags for force-parallel-*.c testcases.
set PARALLEL_CFLAGS "-ansi -pedantic-errors -O2 \
-ftree-parallelize-loops=4 -floop-parallelize-all \
diff --git a/libgomp/testsuite/libgomp.oacc-c++/c++.exp b/libgomp/testsuite/libgomp.oacc-c++/c++.exp
index 42e0395..79df401 100644
--- a/libgomp/testsuite/libgomp.oacc-c++/c++.exp
+++ b/libgomp/testsuite/libgomp.oacc-c++/c++.exp
@@ -11,15 +11,21 @@ proc check_effective_target_c++ { } {
return 1
}
-global shlib_ext
-
-set shlib_ext [get_shlib_extension]
-set lang_link_flags "-lstdc++"
-set lang_test_file_found 0
-set lang_library_path "../libstdc++-v3/src/.libs"
-if [info exists lang_include_flags] then {
- unset lang_include_flags
+if { $blddir != "" } {
+ set libstdc++_library_path "../libstdc++-v3/src/.libs"
+ set shlib_ext [get_shlib_extension]
+ if { ![file exists "${blddir}/${libstdc++_library_path}/libstdc++.a"]
+ && ![file exists "${blddir}/${libstdc++_library_path}/libstdc++.${shlib_ext}"] } {
+ verbose -log "No libstdc++ library found, will not execute c++ tests"
+ unset libstdc++_library_path
+ return
+ }
+ lappend lang_library_paths ${libstdc++_library_path}
+} elseif { ![info exists GXX_UNDER_TEST] } {
+ verbose -log "GXX_UNDER_TEST not defined, will not execute c++ tests"
+ return
}
+lappend ALWAYS_CFLAGS "compiler=$GXX_UNDER_TEST"
# Initialize dg.
dg-init
@@ -28,136 +34,96 @@ torture-init
# Turn on OpenACC.
lappend ALWAYS_CFLAGS "additional_flags=-fopenacc"
-# Switch into C++ mode. Otherwise, the libgomp.oacc-c-c++-common/*.c
-# files would be compiled as C files.
-set SAVE_GCC_UNDER_TEST "$GCC_UNDER_TEST"
-set GCC_UNDER_TEST "$GCC_UNDER_TEST -x c++"
-
-set blddir [lookfor_file [get_multilibs] libgomp]
-
+# Gather a list of all tests.
+set tests [lsort [concat \
+ [find $srcdir/$subdir *.C] \
+ [find $srcdir/$subdir/../libgomp.oacc-c-c++-common *.c]]]
+set ld_library_path $always_ld_library_path
if { $blddir != "" } {
- # Look for a static libstdc++ first.
- if [file exists "${blddir}/${lang_library_path}/libstdc++.a"] {
- set lang_test_file "${lang_library_path}/libstdc++.a"
- set lang_test_file_found 1
- # We may have a shared only build, so look for a shared libstdc++.
- } elseif [file exists "${blddir}/${lang_library_path}/libstdc++.${shlib_ext}"] {
- set lang_test_file "${lang_library_path}/libstdc++.${shlib_ext}"
- set lang_test_file_found 1
- } else {
- puts "No libstdc++ library found, will not execute c++ tests"
- }
-} elseif { [info exists GXX_UNDER_TEST] } {
- set lang_test_file_found 1
- # Needs to exist for libgomp.exp.
- set lang_test_file ""
-} else {
- puts "GXX_UNDER_TEST not defined, will not execute c++ tests"
+ append ld_library_path ":${blddir}/${libstdc++_library_path}"
}
-
-if { $lang_test_file_found } {
- # Gather a list of all tests.
- set tests [lsort [concat \
- [find $srcdir/$subdir *.C] \
- [find $srcdir/$subdir/../libgomp.oacc-c-c++-common *.c]]]
-
- if { $blddir != "" } {
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}"
- } else {
- set ld_library_path "$always_ld_library_path"
- }
- append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
- set_ld_library_path_env_vars
-
- set flags_file "${blddir}/../libstdc++-v3/scripts/testsuite_flags"
- if { [file exists $flags_file] } {
- set libstdcxx_includes [exec sh $flags_file --build-includes]
- } else {
- set libstdcxx_includes ""
- }
-
- # Test with all available offload targets, and with offloading disabled.
- foreach offload_target [concat [split $offload_targets ","] "disable"] {
- global openacc_device_type
- set openacc_device_type [offload_target_to_openacc_device_type $offload_target]
- set tagopt "-DACC_DEVICE_TYPE_$openacc_device_type=1"
-
- switch $openacc_device_type {
- "" {
- unsupported "$subdir $offload_target offloading"
+append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
+set_ld_library_path_env_vars
+
+# Test with all available offload targets, and with offloading disabled.
+foreach offload_target [concat [split $offload_targets ","] "disable"] {
+ global openacc_device_type
+ set openacc_device_type [offload_target_to_openacc_device_type $offload_target]
+ set tagopt "-DACC_DEVICE_TYPE_$openacc_device_type=1"
+
+ switch $openacc_device_type {
+ "" {
+ unsupported "$subdir $offload_target offloading"
+ continue
+ }
+ host {
+ set acc_mem_shared 1
+ }
+ nvidia {
+ if { ![check_effective_target_openacc_nvidia_accel_present] } {
+ # Don't bother; execution testing is going to FAIL.
+ untested "$subdir $offload_target offloading: supported, but hardware not accessible"
continue
}
- host {
- set acc_mem_shared 1
- }
- nvidia {
- if { ![check_effective_target_openacc_nvidia_accel_present] } {
- # Don't bother; execution testing is going to FAIL.
- untested "$subdir $offload_target offloading: supported, but hardware not accessible"
- continue
- }
- # Copy ptx file (TEMPORARY)
- remote_download host $srcdir/libgomp.oacc-c-c++-common/subr.ptx
+ # Copy ptx file (TEMPORARY)
+ remote_download host $srcdir/libgomp.oacc-c-c++-common/subr.ptx
- # Where timer.h lives
- lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/libgomp.oacc-c-c++-common"
+ # Where timer.h lives
+ lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/libgomp.oacc-c-c++-common"
- set acc_mem_shared 0
- }
- radeon {
- if { ![check_effective_target_openacc_radeon_accel_present] } {
- # Don't bother; execution testing is going to FAIL.
- untested "$subdir $offload_target offloading: supported, but hardware not accessible"
- continue
- }
-
- set acc_mem_shared 0
- }
- default {
- error "Unknown OpenACC device type: $openacc_device_type (offload target: $offload_target)"
- }
+ set acc_mem_shared 0
}
- set tagopt "$tagopt -DACC_MEM_SHARED=$acc_mem_shared"
-
- # To avoid compilation overhead, and to keep simple '-foffload=[...]'
- # handling in test cases, by default only build for the offload target
- # that we're actually going to test.
- set tagopt "$tagopt -foffload=$offload_target"
- # Force usage of the corresponding OpenACC device type.
- setenv ACC_DEVICE_TYPE $openacc_device_type
-
- # To get better test coverage for device-specific code that is only
- # ever used in offloading configurations, we'd like more thorough
- # testing for test cases that deal with offloading, which most of all
- # OpenACC test cases are. We enable torture testing, but limit it to
- # -O0 and -O2 only, to avoid testing times exploding too much, under
- # the assumption that between -O0 and -O[something] there is the
- # biggest difference in the overall structure of the generated code.
- switch -glob $offload_target {
- disable {
- set-torture-options [list \
- { -O2 } ]
- }
- default {
- set-torture-options [list \
- { -O0 } \
- { -O2 } ]
+ radeon {
+ if { ![check_effective_target_openacc_radeon_accel_present] } {
+ # Don't bother; execution testing is going to FAIL.
+ untested "$subdir $offload_target offloading: supported, but hardware not accessible"
+ continue
}
- }
- gcc-dg-runtest $tests "$tagopt" "$libstdcxx_includes"
+ set acc_mem_shared 0
+ }
+ default {
+ error "Unknown OpenACC device type: $openacc_device_type (offload target: $offload_target)"
+ }
+ }
+ set tagopt "$tagopt -DACC_MEM_SHARED=$acc_mem_shared"
+
+ # To avoid compilation overhead, and to keep simple '-foffload=[...]'
+ # handling in test cases, by default only build for the offload target
+ # that we're actually going to test.
+ set tagopt "$tagopt -foffload=$offload_target"
+ # Force usage of the corresponding OpenACC device type.
+ setenv ACC_DEVICE_TYPE $openacc_device_type
+
+ # To get better test coverage for device-specific code that is only
+ # ever used in offloading configurations, we'd like more thorough
+ # testing for test cases that deal with offloading, which most of all
+ # OpenACC test cases are. We enable torture testing, but limit it to
+ # -O0 and -O2 only, to avoid testing times exploding too much, under
+ # the assumption that between -O0 and -O[something] there is the
+ # biggest difference in the overall structure of the generated code.
+ switch -glob $offload_target {
+ disable {
+ set-torture-options [list \
+ { -O2 } ]
+ }
+ default {
+ set-torture-options [list \
+ { -O0 } \
+ { -O2 } ]
+ }
}
- unset offload_target
-} else {
- # Call this once, which placates the subsequent torture-finish.
- set-torture-options [list \
- { INVALID } ]
+
+ gcc-dg-runtest $tests "$tagopt" ""
}
+unset offload_target
-# See above.
-set GCC_UNDER_TEST "$SAVE_GCC_UNDER_TEST"
+if { $blddir != "" } {
+ unset libstdc++_library_path
+ unset lang_library_paths
+}
# All done.
torture-finish
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/present-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/present-1.c
index 61c8109..02fbfda 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/present-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/present-1.c
@@ -48,5 +48,5 @@ main (int argc, char **argv)
}
/* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */
-/* { dg-output "present clause: !acc_is_present" } */
+/* { dg-output "libgomp: present clause: not present on the device \\(addr: 0x\[0-9a-f\]+, size: \[0-9\]+ \\(0x\[0-9a-f\]+\\), dev: \[0-9\]+\\\)" } */
/* { dg-shouldfail "" } */
diff --git a/libgomp/testsuite/libgomp.oacc-c/c.exp b/libgomp/testsuite/libgomp.oacc-c/c.exp
index 4bb2b2a..8ca0c81 100644
--- a/libgomp/testsuite/libgomp.oacc-c/c.exp
+++ b/libgomp/testsuite/libgomp.oacc-c/c.exp
@@ -1,16 +1,5 @@
# This whole file adapted from libgomp.c/c.exp.
-if [info exists lang_library_path] then {
- unset lang_library_path
- unset lang_link_flags
-}
-if [info exists lang_test_file] then {
- unset lang_test_file
-}
-if [info exists lang_include_flags] then {
- unset lang_include_flags
-}
-
load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
load_gcc_lib torture-options.exp
@@ -26,6 +15,8 @@ proc check_effective_target_c++ { } {
dg-init
torture-init
+lappend ALWAYS_CFLAGS "compiler=$GCC_UNDER_TEST"
+
# Turn on OpenACC.
lappend ALWAYS_CFLAGS "additional_flags=-fopenacc"
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90 b/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90
new file mode 100644
index 0000000..edc940c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/fortran-torture_execute_math.f90
@@ -0,0 +1,4 @@
+! { dg-do run }
+!TODO { dg-prune-output {using 'vector_length \(32\)', ignoring 1} }
+
+include '../../../gcc/testsuite/gfortran.fortran-torture/execute/math.f90'
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp b/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
index 7365b32..e5844ad 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
+++ b/libgomp/testsuite/libgomp.oacc-fortran/fortran.exp
@@ -4,18 +4,33 @@ load_lib libgomp-dg.exp
load_gcc_lib gcc-dg.exp
load_gcc_lib gfortran-dg.exp
-global shlib_ext
-global ALWAYS_CFLAGS
+if { $blddir != "" } {
+ set libgfortran_library_path "../libgfortran/.libs"
+ set shlib_ext [get_shlib_extension]
+ if { ![file exists "${blddir}/${libgfortran_library_path}/libgfortran.a"]
+ && ![file exists "${blddir}/${libgfortran_library_path}/libgfortran.${shlib_ext}"] } {
+ verbose -log "No libgfortran library found, will not execute fortran tests"
+ unset libgfortran_library_path
+ return
+ }
+ lappend lang_library_paths $libgfortran_library_path
-set shlib_ext [get_shlib_extension]
-set lang_library_path "../libgfortran/.libs"
-set lang_link_flags "-lgfortran -foffload=-lgfortran"
-if [info exists lang_include_flags] then {
- unset lang_include_flags
+ set libquadmath_library_path "../libquadmath/.libs"
+ if { [file exists "${blddir}/${libquadmath_library_path}/libquadmath.a"]
+ || [file exists "${blddir}/${libquadmath_library_path}/libquadmath.${shlib_ext}"] } {
+ lappend lang_library_paths $libquadmath_library_path
+ } else {
+ set libquadmath_library_path ""
+ }
+} elseif { ![info exists GFORTRAN_UNDER_TEST] } {
+ verbose -log "GFORTRAN_UNDER_TEST not defined, will not execute fortran tests"
+ return
}
-set lang_test_file_found 0
-set quadmath_library_path "../libquadmath/.libs"
-
+if { $blddir != "" } {
+ set lang_source_re {^.*\.[fF](|90|95|03|08)$}
+ set lang_include_flags "-fintrinsic-modules-path=${blddir}"
+}
+lappend ALWAYS_CFLAGS "compiler=$GFORTRAN_UNDER_TEST"
# Initialize dg.
dg-init
@@ -23,105 +38,79 @@ dg-init
# Turn on OpenACC.
lappend ALWAYS_CFLAGS "additional_flags=-fopenacc"
+
+# Gather a list of all tests.
+set tests [lsort [find $srcdir/$subdir *.\[fF\]{,90,95,03,08}]]
+
+set ld_library_path $always_ld_library_path
if { $blddir != "" } {
- set lang_source_re {^.*\.[fF](|90|95|03|08)$}
- set lang_include_flags "-fintrinsic-modules-path=${blddir}"
- # Look for a static libgfortran first.
- if [file exists "${blddir}/${lang_library_path}/libgfortran.a"] {
- set lang_test_file "${lang_library_path}/libgfortran.a"
- set lang_test_file_found 1
- # We may have a shared only build, so look for a shared libgfortran.
- } elseif [file exists "${blddir}/${lang_library_path}/libgfortran.${shlib_ext}"] {
- set lang_test_file "${lang_library_path}/libgfortran.${shlib_ext}"
- set lang_test_file_found 1
- } else {
- puts "No libgfortran library found, will not execute fortran tests"
+ append ld_library_path ":${blddir}/${libgfortran_library_path}"
+
+ if { $libquadmath_library_path != "" } {
+ append ld_library_path ":${blddir}/${libquadmath_library_path}"
}
-} elseif [info exists GFORTRAN_UNDER_TEST] {
- set lang_test_file_found 1
- # Needs to exist for libgomp.exp.
- set lang_test_file ""
-} else {
- puts "GFORTRAN_UNDER_TEST not defined, will not execute fortran tests"
}
-
-if { $lang_test_file_found } {
- # Gather a list of all tests.
- set tests [lsort [find $srcdir/$subdir *.\[fF\]{,90,95,03,08}]]
-
- if { $blddir != "" } {
- if { [file exists "${blddir}/${quadmath_library_path}/libquadmath.a"]
- || [file exists "${blddir}/${quadmath_library_path}/libquadmath.${shlib_ext}"] } {
- lappend ALWAYS_CFLAGS "ldflags=-L${blddir}/${quadmath_library_path}/"
- # Allow for spec subsitution.
- lappend ALWAYS_CFLAGS "additional_flags=-B${blddir}/${quadmath_library_path}/"
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}:${blddir}/${quadmath_library_path}"
- append lang_link_flags " -lquadmath"
- } else {
- set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}"
+append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
+set_ld_library_path_env_vars
+
+# Test with all available offload targets, and with offloading disabled.
+foreach offload_target [concat [split $offload_targets ","] "disable"] {
+ global openacc_device_type
+ set openacc_device_type [offload_target_to_openacc_device_type $offload_target]
+ set tagopt "-DACC_DEVICE_TYPE_$openacc_device_type=1"
+
+ switch $openacc_device_type {
+ "" {
+ unsupported "$subdir $offload_target offloading"
+ continue
}
- } else {
- set ld_library_path "$always_ld_library_path"
- if { [check_no_compiler_messages has_libquadmath executable {
- int main() {return 0;}
- } "-lgfortran -lquadmath"] } then {
- append lang_link_flags " -lquadmath"
- }
- }
- append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST]
- set_ld_library_path_env_vars
-
- # Test with all available offload targets, and with offloading disabled.
- foreach offload_target [concat [split $offload_targets ","] "disable"] {
- global openacc_device_type
- set openacc_device_type [offload_target_to_openacc_device_type $offload_target]
- set tagopt "-DACC_DEVICE_TYPE_$openacc_device_type=1"
-
- switch $openacc_device_type {
- "" {
- unsupported "$subdir $offload_target offloading"
+ host {
+ set acc_mem_shared 1
+ }
+ nvidia {
+ if { ![check_effective_target_openacc_nvidia_accel_present] } {
+ # Don't bother; execution testing is going to FAIL.
+ untested "$subdir $offload_target offloading: supported, but hardware not accessible"
continue
}
- host {
- set acc_mem_shared 1
- }
- nvidia {
- if { ![check_effective_target_openacc_nvidia_accel_present] } {
- # Don't bother; execution testing is going to FAIL.
- untested "$subdir $offload_target offloading: supported, but hardware not accessible"
- continue
- }
-
- set acc_mem_shared 0
- }
- radeon {
- if { ![check_effective_target_openacc_radeon_accel_present] } {
- # Don't bother; execution testing is going to FAIL.
- untested "$subdir $offload_target offloading: supported, but hardware not accessible"
- continue
- }
-
- set acc_mem_shared 0
- }
- default {
- error "Unknown OpenACC device type: $openacc_device_type (offload target: $offload_target)"
+
+ set acc_mem_shared 0
+ }
+ radeon {
+ if { ![check_effective_target_openacc_radeon_accel_present] } {
+ # Don't bother; execution testing is going to FAIL.
+ untested "$subdir $offload_target offloading: supported, but hardware not accessible"
+ continue
}
+
+ set acc_mem_shared 0
+ }
+ default {
+ error "Unknown OpenACC device type: $openacc_device_type (offload target: $offload_target)"
}
- set tagopt "$tagopt -DACC_MEM_SHARED=$acc_mem_shared"
-
- # To avoid compilation overhead, and to keep simple '-foffload=[...]'
- # handling in test cases, by default only build for the offload target
- # that we're actually going to test.
- set tagopt "$tagopt -foffload=$offload_target"
- # Force usage of the corresponding OpenACC device type.
- setenv ACC_DEVICE_TYPE $openacc_device_type
-
- # For Fortran we're doing torture testing, as Fortran has far more tests
- # with arrays etc. that testing just -O0 or -O2 is insufficient, that is
- # typically not the case for C/C++.
- gfortran-dg-runtest $tests "$tagopt" ""
}
- unset offload_target
+ set tagopt "$tagopt -DACC_MEM_SHARED=$acc_mem_shared"
+
+ # To avoid compilation overhead, and to keep simple '-foffload=[...]'
+ # handling in test cases, by default only build for the offload target
+ # that we're actually going to test.
+ set tagopt "$tagopt -foffload=$offload_target"
+ # Force usage of the corresponding OpenACC device type.
+ setenv ACC_DEVICE_TYPE $openacc_device_type
+
+ # For Fortran we're doing torture testing, as Fortran has far more tests
+ # with arrays etc. that testing just -O0 or -O2 is insufficient, that is
+ # typically not the case for C/C++.
+ gfortran-dg-runtest $tests "$tagopt" ""
+}
+unset offload_target
+
+if { $blddir != "" } {
+ unset lang_source_re
+ unset lang_include_flags
+ unset libgfortran_library_path
+ unset libquadmath_library_path
+ unset lang_library_paths
}
# All done.
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr109622-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-2.f90
new file mode 100644
index 0000000..d3cbebe
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-2.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+
+implicit none
+
+type t
+integer :: foo
+integer, pointer :: bar
+end type t
+
+type(t) :: var
+integer, target :: tgt
+
+var%bar => tgt
+
+var%foo = 99
+tgt = 199
+
+!$acc enter data copyin(var, tgt)
+
+!$acc enter data attach(var%bar)
+
+!$acc serial
+! { dg-warning "using .vector_length \\(32\\)., ignoring 1" "" { target openacc_nvidia_accel_selected } .-1 }
+var%foo = 5
+var%bar = 7
+!$acc end serial
+
+!$acc exit data detach(var%bar)
+
+!$acc exit data copyout(var, tgt)
+
+if (var%foo.ne.5) stop 1
+if (tgt.ne.7) stop 2
+
+end
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr109622-3.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-3.f90
new file mode 100644
index 0000000..a25b1a8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-3.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+
+implicit none
+
+type t
+integer :: foo
+integer, pointer :: bar(:)
+end type t
+
+type(t) :: var
+integer, target :: tgt(20)
+
+var%bar => tgt
+
+var%foo = 99
+tgt = 199
+
+!$acc enter data copyin(var, tgt)
+
+!$acc enter data attach(var%bar)
+
+!$acc serial
+! { dg-warning "using .vector_length \\(32\\)., ignoring 1" "" { target openacc_nvidia_accel_selected } .-1 }
+var%foo = 5
+var%bar = 7
+!$acc end serial
+
+!$acc exit data detach(var%bar)
+
+!$acc exit data copyout(var, tgt)
+
+if (var%foo.ne.5) stop 1
+if (any(tgt.ne.7)) stop 2
+
+end
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr109622-4.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-4.f90
new file mode 100644
index 0000000..3198a0b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr109622-4.f90
@@ -0,0 +1,47 @@
+! { dg-do run }
+
+use openacc
+implicit none
+
+type t
+integer :: foo
+character(len=8), pointer :: bar
+character(len=4), allocatable :: qux
+end type t
+
+type(t) :: var
+character(len=8), target :: tgt
+
+allocate(var%qux)
+
+var%bar => tgt
+
+var%foo = 99
+tgt = "Octopus!"
+var%qux = "Fish"
+
+!$acc enter data copyin(var, tgt)
+
+! Avoid automatic attach (i.e. with "enter data")
+call acc_copyin (var%qux)
+
+!$acc enter data attach(var%bar, var%qux)
+
+!$acc serial
+! { dg-warning "using .vector_length \\(32\\)., ignoring 1" "" { target openacc_nvidia_accel_selected } .-1 }
+var%foo = 5
+var%bar = "Plankton"
+var%qux = "Pond"
+!$acc end serial
+
+!$acc exit data detach(var%bar, var%qux)
+
+call acc_copyout (var%qux)
+
+!$acc exit data copyout(var, tgt)
+
+if (var%foo.ne.5) stop 1
+if (tgt.ne."Plankton") stop 2
+if (var%qux.ne."Pond") stop 3
+
+end
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr109622.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr109622.f90
new file mode 100644
index 0000000..a17c4f6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr109622.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+
+implicit none
+
+type t
+integer :: value
+type(t), pointer :: chain
+end type t
+
+type(t), target :: var, var2
+
+var%value = 99
+var2%value = 199
+
+var%chain => var2
+nullify(var2%chain)
+
+!$acc enter data copyin(var, var2)
+
+!$acc enter data attach(var%chain)
+
+!$acc serial
+! { dg-warning "using .vector_length \\(32\\)., ignoring 1" "" { target openacc_nvidia_accel_selected } .-1 }
+var%value = 5
+var%chain%value = 7
+!$acc end serial
+
+!$acc exit data detach(var%chain)
+
+!$acc exit data copyout(var, var2)
+
+if (var%value.ne.5) stop 1
+if (var2%value.ne.7) stop 2
+
+end