diff --git a/.gcc.metadata b/.gcc.metadata
new file mode 100644
index 0000000..03b4cd9
--- /dev/null
+++ b/.gcc.metadata
@@ -0,0 +1,3 @@
+8ee669ee60997110e6251c72dac66bf69bbe13c7 SOURCES/gcc-8.3.1-20190507.tar.xz
+3bdb3cc01fa7690a0e20ea5cfffcbe690f7665eb SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz
+ce8eb83be0ac37fb5d5388df455a980fe37b4f13 SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb2c952
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+SOURCES/gcc-8.3.1-20190507.tar.xz
+SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz
+SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz
diff --git a/SOURCES/gcc8-Wno-format-security.patch b/SOURCES/gcc8-Wno-format-security.patch
new file mode 100644
index 0000000..cb21e5d
--- /dev/null
+++ b/SOURCES/gcc8-Wno-format-security.patch
@@ -0,0 +1,27 @@
+2017-02-25 Jakub Jelinek
+
+ * configure.ac: When adding -Wno-format, also add -Wno-format-security.
+ * configure: Regenerated.
+
+--- gcc/configure.ac.jj 2017-02-13 12:20:53.000000000 +0100
++++ gcc/configure.ac 2017-02-25 12:42:32.859175403 +0100
+@@ -481,7 +481,7 @@ AC_ARG_ENABLE(build-format-warnings,
+ AS_HELP_STRING([--disable-build-format-warnings],[don't use -Wformat while building GCC]),
+ [],[enable_build_format_warnings=yes])
+ AS_IF([test $enable_build_format_warnings = no],
+- [wf_opt=-Wno-format],[wf_opt=])
++ [wf_opt="-Wno-format -Wno-format-security"],[wf_opt=])
+ ACX_PROG_CXX_WARNING_OPTS(
+ m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ],
+ [-Wcast-qual $wf_opt])), [loose_warn])
+--- gcc/configure.jj 2017-02-13 12:20:52.000000000 +0100
++++ gcc/configure 2017-02-25 12:42:50.041946391 +0100
+@@ -6647,7 +6647,7 @@ else
+ fi
+
+ if test $enable_build_format_warnings = no; then :
+- wf_opt=-Wno-format
++ wf_opt="-Wno-format -Wno-format-security"
+ else
+ wf_opt=
+ fi
diff --git a/SOURCES/gcc8-foffload-default.patch b/SOURCES/gcc8-foffload-default.patch
new file mode 100644
index 0000000..771e1e0
--- /dev/null
+++ b/SOURCES/gcc8-foffload-default.patch
@@ -0,0 +1,117 @@
+2017-01-20 Jakub Jelinek
+
+ * gcc.c (offload_targets_default): New variable.
+ (process_command): Set it if -foffload is defaulted.
+ (driver::maybe_putenv_OFFLOAD_TARGETS): Add OFFLOAD_TARGET_DEFAULT=1
+ into environment if -foffload has been defaulted.
+ * lto-wrapper.c (OFFLOAD_TARGET_DEFAULT_ENV): Define.
+ (compile_images_for_offload_targets): If OFFLOAD_TARGET_DEFAULT
+ is in the environment, don't fail if corresponding mkoffload
+ can't be found. Free and clear offload_names if no valid offload
+ is found.
+libgomp/
+ * target.c (gomp_load_plugin_for_device): If a plugin can't be
+ dlopened, assume it has no devices silently.
+
+--- gcc/gcc.c.jj 2017-01-17 10:28:40.000000000 +0100
++++ gcc/gcc.c 2017-01-20 16:26:29.649962902 +0100
+@@ -290,6 +290,10 @@ static const char *spec_host_machine = D
+
+ static char *offload_targets = NULL;
+
++/* Set to true if -foffload has not been used and offload_targets
++ is set to the configured in default. */
++static bool offload_targets_default;
++
+ /* Nonzero if cross-compiling.
+ When -b is used, the value comes from the `specs' file. */
+
+@@ -4457,7 +4461,10 @@ process_command (unsigned int decoded_op
+ /* If the user didn't specify any, default to all configured offload
+ targets. */
+ if (ENABLE_OFFLOADING && offload_targets == NULL)
+- handle_foffload_option (OFFLOAD_TARGETS);
++ {
++ handle_foffload_option (OFFLOAD_TARGETS);
++ offload_targets_default = true;
++ }
+
+ if (output_file
+ && strcmp (output_file, "-") != 0
+@@ -7693,6 +7700,8 @@ driver::maybe_putenv_OFFLOAD_TARGETS ()
+ obstack_grow (&collect_obstack, offload_targets,
+ strlen (offload_targets) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
++ if (offload_targets_default)
++ xputenv ("OFFLOAD_TARGET_DEFAULT=1");
+ }
+
+ free (offload_targets);
+--- gcc/lto-wrapper.c.jj 2017-01-01 12:45:34.000000000 +0100
++++ gcc/lto-wrapper.c 2017-01-20 16:34:18.294016997 +0100
+@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.
+ /* Environment variable, used for passing the names of offload targets from GCC
+ driver to lto-wrapper. */
+ #define OFFLOAD_TARGET_NAMES_ENV "OFFLOAD_TARGET_NAMES"
++#define OFFLOAD_TARGET_DEFAULT_ENV "OFFLOAD_TARGET_DEFAULT"
+
+ enum lto_mode_d {
+ LTO_MODE_NONE, /* Not doing LTO. */
+@@ -790,8 +791,10 @@ compile_images_for_offload_targets (unsi
+ if (!target_names)
+ return;
+ unsigned num_targets = parse_env_var (target_names, &names, NULL);
++ const char *target_names_default = getenv (OFFLOAD_TARGET_DEFAULT_ENV);
+
+ int next_name_entry = 0;
++ bool hsa_seen = false;
+ const char *compiler_path = getenv ("COMPILER_PATH");
+ if (!compiler_path)
+ goto out;
+@@ -804,18 +807,32 @@ compile_images_for_offload_targets (unsi
+ /* HSA does not use LTO-like streaming and a different compiler, skip
+ it. */
+ if (strcmp (names[i], "hsa") == 0)
+- continue;
++ {
++ hsa_seen = true;
++ continue;
++ }
+
+ offload_names[next_name_entry]
+ = compile_offload_image (names[i], compiler_path, in_argc, in_argv,
+ compiler_opts, compiler_opt_count,
+ linker_opts, linker_opt_count);
+ if (!offload_names[next_name_entry])
+- fatal_error (input_location,
+- "problem with building target image for %s\n", names[i]);
++ {
++ if (target_names_default != NULL)
++ continue;
++ fatal_error (input_location,
++ "problem with building target image for %s\n",
++ names[i]);
++ }
+ next_name_entry++;
+ }
+
++ if (next_name_entry == 0 && !hsa_seen)
++ {
++ free (offload_names);
++ offload_names = NULL;
++ }
++
+ out:
+ free_array_of_ptrs ((void **) names, num_targets);
+ }
+--- libgomp/target.c.jj 2017-01-01 12:45:52.000000000 +0100
++++ libgomp/target.c 2017-01-20 20:12:13.756710875 +0100
+@@ -2356,7 +2356,7 @@ gomp_load_plugin_for_device (struct gomp
+
+ void *plugin_handle = dlopen (plugin_name, RTLD_LAZY);
+ if (!plugin_handle)
+- goto dl_fail;
++ return 0;
+
+ /* Check if all required functions are available in the plugin and store
+ their handlers. None of the symbols can legitimately be NULL,
diff --git a/SOURCES/gcc8-hack.patch b/SOURCES/gcc8-hack.patch
new file mode 100644
index 0000000..515173f
--- /dev/null
+++ b/SOURCES/gcc8-hack.patch
@@ -0,0 +1,124 @@
+--- libada/Makefile.in.jj 2009-01-14 12:07:35.000000000 +0100
++++ libada/Makefile.in 2009-01-15 14:25:33.000000000 +0100
+@@ -66,18 +66,40 @@ libsubdir := $(libdir)/gcc/$(target_nonc
+ ADA_RTS_DIR=$(GCC_DIR)/ada/rts$(subst /,_,$(MULTISUBDIR))
+ ADA_RTS_SUBDIR=./rts$(subst /,_,$(MULTISUBDIR))
+
++DEFAULTMULTIFLAGS :=
++ifeq ($(MULTISUBDIR),)
++targ:=$(subst -, ,$(target))
++arch:=$(word 1,$(targ))
++ifeq ($(words $(targ)),2)
++osys:=$(word 2,$(targ))
++else
++osys:=$(word 3,$(targ))
++endif
++ifeq ($(strip $(filter-out i%86 x86_64 powerpc% ppc% s390% sparc% linux%, $(arch) $(osys))),)
++ifeq ($(shell $(CC) $(CFLAGS) -print-multi-os-directory),../lib64)
++DEFAULTMULTIFLAGS := -m64
++else
++ifeq ($(strip $(filter-out s390%, $(arch))),)
++DEFAULTMULTIFLAGS := -m31
++else
++DEFAULTMULTIFLAGS := -m32
++endif
++endif
++endif
++endif
++
+ # exeext should not be used because it's the *host* exeext. We're building
+ # a *target* library, aren't we?!? Likewise for CC. Still, provide bogus
+ # definitions just in case something slips through the safety net provided
+ # by recursive make invocations in gcc/ada/Makefile.in
+ LIBADA_FLAGS_TO_PASS = \
+ "MAKEOVERRIDES=" \
+- "LDFLAGS=$(LDFLAGS)" \
++ "LDFLAGS=$(LDFLAGS) $(DEFAULTMULTIFLAGS)" \
+ "LN_S=$(LN_S)" \
+ "SHELL=$(SHELL)" \
+- "GNATLIBFLAGS=$(GNATLIBFLAGS) $(MULTIFLAGS)" \
+- "GNATLIBCFLAGS=$(GNATLIBCFLAGS) $(MULTIFLAGS)" \
+- "GNATLIBCFLAGS_FOR_C=$(GNATLIBCFLAGS_FOR_C) $(MULTIFLAGS)" \
++ "GNATLIBFLAGS=$(GNATLIBFLAGS) $(MULTIFLAGS) $(DEFAULTMULTIFLAGS)" \
++ "GNATLIBCFLAGS=$(GNATLIBCFLAGS) $(MULTIFLAGS) $(DEFAULTMULTIFLAGS)" \
++ "GNATLIBCFLAGS_FOR_C=$(GNATLIBCFLAGS_FOR_C) $(MULTIFLAGS) $(DEFAULTMULTIFLAGS)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG)" \
+ "THREAD_KIND=$(THREAD_KIND)" \
+ "TRACE=$(TRACE)" \
+@@ -88,7 +110,7 @@ LIBADA_FLAGS_TO_PASS = \
+ "exeext=.exeext.should.not.be.used " \
+ 'CC=the.host.compiler.should.not.be.needed' \
+ "GCC_FOR_TARGET=$(CC)" \
+- "CFLAGS=$(CFLAGS)"
++ "CFLAGS=$(CFLAGS) $(DEFAULTMULTIFLAGS)"
+
+ # Rules to build gnatlib.
+ .PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared osconstool
+--- config-ml.in.jj 2010-06-30 09:50:44.000000000 +0200
++++ config-ml.in 2010-07-02 21:24:17.994211151 +0200
+@@ -511,6 +511,8 @@ multi-do:
+ ADAFLAGS="$(ADAFLAGS) $${flags}" \
+ prefix="$(prefix)" \
+ exec_prefix="$(exec_prefix)" \
++ mandir="$(mandir)" \
++ infodir="$(infodir)" \
+ GOCFLAGS="$(GOCFLAGS) $${flags}" \
+ CXXFLAGS="$(CXXFLAGS) $${flags}" \
+ LIBCFLAGS="$(LIBCFLAGS) $${flags}" \
+--- libcpp/macro.c.jj 2015-01-14 11:01:34.000000000 +0100
++++ libcpp/macro.c 2015-01-14 14:22:19.286949884 +0100
+@@ -2947,8 +2947,6 @@ create_iso_definition (cpp_reader *pfile
+ cpp_token *token;
+ const cpp_token *ctoken;
+ bool following_paste_op = false;
+- const char *paste_op_error_msg =
+- N_("'##' cannot appear at either end of a macro expansion");
+ unsigned int num_extra_tokens = 0;
+
+ /* Get the first token of the expansion (or the '(' of a
+@@ -3059,7 +3057,8 @@ create_iso_definition (cpp_reader *pfile
+ function-like macros, but not at the end. */
+ if (following_paste_op)
+ {
+- cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
++ cpp_error (pfile, CPP_DL_ERROR,
++ "'##' cannot appear at either end of a macro expansion");
+ return false;
+ }
+ break;
+@@ -3072,7 +3071,8 @@ create_iso_definition (cpp_reader *pfile
+ function-like macros, but not at the beginning. */
+ if (macro->count == 1)
+ {
+- cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
++ cpp_error (pfile, CPP_DL_ERROR,
++ "'##' cannot appear at either end of a macro expansion");
+ return false;
+ }
+
+--- libcpp/expr.c.jj 2015-01-14 11:01:34.000000000 +0100
++++ libcpp/expr.c 2015-01-14 14:35:52.851002344 +0100
+@@ -672,16 +672,17 @@ cpp_classify_number (cpp_reader *pfile,
+ if ((result & CPP_N_WIDTH) == CPP_N_LARGE
+ && CPP_OPTION (pfile, cpp_warn_long_long))
+ {
+- const char *message = CPP_OPTION (pfile, cplusplus)
+- ? N_("use of C++11 long long integer constant")
+- : N_("use of C99 long long integer constant");
+-
+ if (CPP_OPTION (pfile, c99))
+ cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
+- 0, message);
++ 0, CPP_OPTION (pfile, cplusplus)
++ ? N_("use of C++11 long long integer constant")
++ : N_("use of C99 long long integer constant"));
+ else
+ cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
+- virtual_location, 0, message);
++ virtual_location, 0,
++ CPP_OPTION (pfile, cplusplus)
++ ? N_("use of C++11 long long integer constant")
++ : N_("use of C99 long long integer constant"));
+ }
+
+ result |= CPP_N_INTEGER;
diff --git a/SOURCES/gcc8-i386-libgomp.patch b/SOURCES/gcc8-i386-libgomp.patch
new file mode 100644
index 0000000..520561e
--- /dev/null
+++ b/SOURCES/gcc8-i386-libgomp.patch
@@ -0,0 +1,11 @@
+--- libgomp/configure.tgt.jj 2008-01-10 20:53:48.000000000 +0100
++++ libgomp/configure.tgt 2008-03-27 12:44:51.000000000 +0100
+@@ -67,7 +67,7 @@ if test $enable_linux_futex = yes; then
+ ;;
+ *)
+ if test -z "$with_arch"; then
+- XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}"
++ XCFLAGS="${XCFLAGS} -march=i486 -mtune=generic"
+ fi
+ esac
+ ;;
diff --git a/SOURCES/gcc8-isl-dl.patch b/SOURCES/gcc8-isl-dl.patch
new file mode 100644
index 0000000..46d3b0d
--- /dev/null
+++ b/SOURCES/gcc8-isl-dl.patch
@@ -0,0 +1,715 @@
+--- gcc/Makefile.in.jj 2015-06-06 10:00:25.000000000 +0200
++++ gcc/Makefile.in 2015-11-04 14:56:02.643536437 +0100
+@@ -1046,7 +1046,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
+ # and the system's installed libraries.
+ LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBBACKTRACE) \
+ $(LIBIBERTY) $(LIBDECNUMBER) $(HOST_LIBS)
+-BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
++BACKENDLIBS = $(if $(ISLLIBS),-ldl) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
+ $(ZLIB)
+ # Any system libraries needed just for GNAT.
+ SYSLIBS = @GNAT_LIBEXC@
+@@ -2196,6 +2196,15 @@ $(out_object_file): $(out_file)
+ $(common_out_object_file): $(common_out_file)
+ $(COMPILE) $<
+ $(POSTCOMPILE)
++
++graphite%.o : \
++ ALL_CFLAGS := -O $(filter-out -fkeep-inline-functions, $(ALL_CFLAGS))
++graphite.o : \
++ ALL_CFLAGS := -O $(filter-out -fkeep-inline-functions, $(ALL_CFLAGS))
++graphite%.o : \
++ ALL_CXXFLAGS := -O $(filter-out -fkeep-inline-functions, $(ALL_CXXFLAGS))
++graphite.o : \
++ ALL_CXXFLAGS := -O $(filter-out -fkeep-inline-functions, $(ALL_CXXFLAGS))
+ #
+ # Generate header and source files from the machine description,
+ # and compile them.
+--- gcc/graphite.h.jj 2016-01-27 12:44:06.000000000 +0100
++++ gcc/graphite.h 2016-01-27 13:26:38.309876856 +0100
+@@ -39,6 +39,590 @@ along with GCC; see the file COPYING3.
+ #include
+ #include
+ #include
++#include
++#include
++
++#define DYNSYMS \
++ DYNSYM (isl_aff_add_coefficient_si); \
++ DYNSYM (isl_aff_free); \
++ DYNSYM (isl_aff_get_space); \
++ DYNSYM (isl_aff_set_coefficient_si); \
++ DYNSYM (isl_aff_set_constant_si); \
++ DYNSYM (isl_aff_zero_on_domain); \
++ DYNSYM (isl_band_free); \
++ DYNSYM (isl_band_get_children); \
++ DYNSYM (isl_band_get_partial_schedule); \
++ DYNSYM (isl_band_has_children); \
++ DYNSYM (isl_band_list_free); \
++ DYNSYM (isl_band_list_get_band); \
++ DYNSYM (isl_band_list_get_ctx); \
++ DYNSYM (isl_band_list_n_band); \
++ DYNSYM (isl_band_n_member); \
++ DYNSYM (isl_basic_map_add_constraint); \
++ DYNSYM (isl_basic_map_project_out); \
++ DYNSYM (isl_basic_map_universe); \
++ DYNSYM (isl_constraint_set_coefficient_si); \
++ DYNSYM (isl_constraint_set_constant_si); \
++ DYNSYM (isl_ctx_alloc); \
++ DYNSYM (isl_ctx_free); \
++ DYNSYM (isl_equality_alloc); \
++ DYNSYM (isl_id_alloc); \
++ DYNSYM (isl_id_copy); \
++ DYNSYM (isl_id_free); \
++ DYNSYM (isl_inequality_alloc); \
++ DYNSYM (isl_local_space_copy); \
++ DYNSYM (isl_local_space_free); \
++ DYNSYM (isl_local_space_from_space); \
++ DYNSYM (isl_local_space_range); \
++ DYNSYM (isl_map_add_constraint); \
++ DYNSYM (isl_map_add_dims); \
++ DYNSYM (isl_map_align_params); \
++ DYNSYM (isl_map_apply_range); \
++ DYNSYM (isl_map_copy); \
++ DYNSYM (isl_map_dim); \
++ DYNSYM (isl_map_dump); \
++ DYNSYM (isl_map_equate); \
++ DYNSYM (isl_map_fix_si); \
++ DYNSYM (isl_map_flat_product); \
++ DYNSYM (isl_map_flat_range_product); \
++ DYNSYM (isl_map_free); \
++ DYNSYM (isl_map_from_basic_map); \
++ DYNSYM (isl_map_from_pw_aff); \
++ DYNSYM (isl_map_from_union_map); \
++ DYNSYM (isl_map_get_ctx); \
++ DYNSYM (isl_map_get_space); \
++ DYNSYM (isl_map_get_tuple_id); \
++ DYNSYM (isl_map_insert_dims); \
++ DYNSYM (isl_map_intersect); \
++ DYNSYM (isl_map_intersect_domain); \
++ DYNSYM (isl_map_intersect_range); \
++ DYNSYM (isl_map_is_empty); \
++ DYNSYM (isl_map_lex_ge); \
++ DYNSYM (isl_map_lex_le); \
++ DYNSYM (isl_map_n_out); \
++ DYNSYM (isl_map_range); \
++ DYNSYM (isl_map_set_tuple_id); \
++ DYNSYM (isl_map_universe); \
++ DYNSYM (isl_options_set_on_error); \
++ DYNSYM (isl_options_set_schedule_serialize_sccs); \
++ DYNSYM (isl_printer_set_yaml_style); \
++ DYNSYM (isl_options_set_schedule_max_constant_term); \
++ DYNSYM (isl_options_set_schedule_maximize_band_depth); \
++ DYNSYM (isl_printer_free); \
++ DYNSYM (isl_printer_print_aff); \
++ DYNSYM (isl_printer_print_constraint); \
++ DYNSYM (isl_printer_print_map); \
++ DYNSYM (isl_printer_print_set); \
++ DYNSYM (isl_printer_to_file); \
++ DYNSYM (isl_pw_aff_add); \
++ DYNSYM (isl_pw_aff_alloc); \
++ DYNSYM (isl_pw_aff_copy); \
++ DYNSYM (isl_pw_aff_eq_set); \
++ DYNSYM (isl_pw_aff_free); \
++ DYNSYM (isl_pw_aff_from_aff); \
++ DYNSYM (isl_pw_aff_ge_set); \
++ DYNSYM (isl_pw_aff_gt_set); \
++ DYNSYM (isl_pw_aff_is_cst); \
++ DYNSYM (isl_pw_aff_le_set); \
++ DYNSYM (isl_pw_aff_lt_set); \
++ DYNSYM (isl_pw_aff_mul); \
++ DYNSYM (isl_pw_aff_ne_set); \
++ DYNSYM (isl_pw_aff_nonneg_set); \
++ DYNSYM (isl_pw_aff_set_tuple_id); \
++ DYNSYM (isl_pw_aff_sub); \
++ DYNSYM (isl_pw_aff_zero_set); \
++ DYNSYM (isl_schedule_free); \
++ DYNSYM (isl_schedule_get_band_forest); \
++ DYNSYM (isl_set_add_constraint); \
++ DYNSYM (isl_set_add_dims); \
++ DYNSYM (isl_set_apply); \
++ DYNSYM (isl_set_coalesce); \
++ DYNSYM (isl_set_copy); \
++ DYNSYM (isl_set_dim); \
++ DYNSYM (isl_set_fix_si); \
++ DYNSYM (isl_set_free); \
++ DYNSYM (isl_set_get_space); \
++ DYNSYM (isl_set_get_tuple_id); \
++ DYNSYM (isl_set_intersect); \
++ DYNSYM (isl_set_is_empty); \
++ DYNSYM (isl_set_n_dim); \
++ DYNSYM (isl_set_nat_universe); \
++ DYNSYM (isl_set_project_out); \
++ DYNSYM (isl_set_set_tuple_id); \
++ DYNSYM (isl_set_universe); \
++ DYNSYM (isl_space_add_dims); \
++ DYNSYM (isl_space_alloc); \
++ DYNSYM (isl_space_copy); \
++ DYNSYM (isl_space_dim); \
++ DYNSYM (isl_space_domain); \
++ DYNSYM (isl_space_find_dim_by_id); \
++ DYNSYM (isl_space_free); \
++ DYNSYM (isl_space_from_domain); \
++ DYNSYM (isl_space_get_tuple_id); \
++ DYNSYM (isl_space_params_alloc); \
++ DYNSYM (isl_space_range); \
++ DYNSYM (isl_space_set_alloc); \
++ DYNSYM (isl_space_set_dim_id); \
++ DYNSYM (isl_space_set_tuple_id); \
++ DYNSYM (isl_union_map_add_map); \
++ DYNSYM (isl_union_map_align_params); \
++ DYNSYM (isl_union_map_apply_domain); \
++ DYNSYM (isl_union_map_apply_range); \
++ DYNSYM (isl_union_map_compute_flow); \
++ DYNSYM (isl_union_map_copy); \
++ DYNSYM (isl_union_map_empty); \
++ DYNSYM (isl_union_map_flat_range_product); \
++ DYNSYM (isl_union_map_foreach_map); \
++ DYNSYM (isl_union_map_free); \
++ DYNSYM (isl_union_map_from_map); \
++ DYNSYM (isl_union_map_get_ctx); \
++ DYNSYM (isl_union_map_get_space); \
++ DYNSYM (isl_union_map_gist_domain); \
++ DYNSYM (isl_union_map_gist_range); \
++ DYNSYM (isl_union_map_intersect_domain); \
++ DYNSYM (isl_union_map_is_empty); \
++ DYNSYM (isl_union_map_subtract); \
++ DYNSYM (isl_union_map_union); \
++ DYNSYM (isl_union_set_add_set); \
++ DYNSYM (isl_union_set_compute_schedule); \
++ DYNSYM (isl_union_set_copy); \
++ DYNSYM (isl_union_set_empty); \
++ DYNSYM (isl_union_set_from_set); \
++ DYNSYM (isl_aff_add_constant_val); \
++ DYNSYM (isl_aff_get_coefficient_val); \
++ DYNSYM (isl_aff_get_ctx); \
++ DYNSYM (isl_aff_mod_val); \
++ DYNSYM (isl_ast_build_ast_from_schedule); \
++ DYNSYM (isl_ast_build_free); \
++ DYNSYM (isl_ast_build_from_context); \
++ DYNSYM (isl_ast_build_get_ctx); \
++ DYNSYM (isl_ast_build_get_schedule); \
++ DYNSYM (isl_ast_build_get_schedule_space); \
++ DYNSYM (isl_ast_build_set_before_each_for); \
++ DYNSYM (isl_ast_build_set_options); \
++ DYNSYM (isl_ast_expr_free); \
++ DYNSYM (isl_ast_expr_from_val); \
++ DYNSYM (isl_ast_expr_get_ctx); \
++ DYNSYM (isl_ast_expr_get_id); \
++ DYNSYM (isl_ast_expr_get_op_arg); \
++ DYNSYM (isl_ast_expr_get_op_n_arg); \
++ DYNSYM (isl_ast_expr_get_op_type); \
++ DYNSYM (isl_ast_expr_get_type); \
++ DYNSYM (isl_ast_expr_get_val); \
++ DYNSYM (isl_ast_expr_sub); \
++ DYNSYM (isl_ast_node_block_get_children); \
++ DYNSYM (isl_ast_node_for_get_body); \
++ DYNSYM (isl_ast_node_for_get_cond); \
++ DYNSYM (isl_ast_node_for_get_inc); \
++ DYNSYM (isl_ast_node_for_get_init); \
++ DYNSYM (isl_ast_node_for_get_iterator); \
++ DYNSYM (isl_ast_node_free); \
++ DYNSYM (isl_ast_node_get_annotation); \
++ DYNSYM (isl_ast_node_get_type); \
++ DYNSYM (isl_ast_node_if_get_cond); \
++ DYNSYM (isl_ast_node_if_get_else); \
++ DYNSYM (isl_ast_node_if_get_then); \
++ DYNSYM (isl_ast_node_list_free); \
++ DYNSYM (isl_ast_node_list_get_ast_node); \
++ DYNSYM (isl_ast_node_list_n_ast_node); \
++ DYNSYM (isl_ast_node_user_get_expr); \
++ DYNSYM (isl_constraint_set_coefficient_val); \
++ DYNSYM (isl_constraint_set_constant_val); \
++ DYNSYM (isl_id_get_user); \
++ DYNSYM (isl_local_space_get_ctx); \
++ DYNSYM (isl_map_fix_val); \
++ DYNSYM (isl_options_set_ast_build_atomic_upper_bound); \
++ DYNSYM (isl_printer_print_ast_node); \
++ DYNSYM (isl_printer_print_str); \
++ DYNSYM (isl_printer_set_output_format); \
++ DYNSYM (isl_pw_aff_mod_val); \
++ DYNSYM (isl_schedule_constraints_compute_schedule); \
++ DYNSYM (isl_schedule_constraints_on_domain); \
++ DYNSYM (isl_schedule_constraints_set_coincidence); \
++ DYNSYM (isl_schedule_constraints_set_proximity); \
++ DYNSYM (isl_schedule_constraints_set_validity); \
++ DYNSYM (isl_set_get_dim_id); \
++ DYNSYM (isl_set_max_val); \
++ DYNSYM (isl_set_min_val); \
++ DYNSYM (isl_set_params); \
++ DYNSYM (isl_space_align_params); \
++ DYNSYM (isl_space_map_from_domain_and_range); \
++ DYNSYM (isl_space_set_tuple_name); \
++ DYNSYM (isl_space_wrap); \
++ DYNSYM (isl_union_map_from_domain_and_range); \
++ DYNSYM (isl_union_map_range); \
++ DYNSYM (isl_union_set_union); \
++ DYNSYM (isl_union_set_universe); \
++ DYNSYM (isl_val_2exp); \
++ DYNSYM (isl_val_add_ui); \
++ DYNSYM (isl_val_copy); \
++ DYNSYM (isl_val_free); \
++ DYNSYM (isl_val_int_from_si); \
++ DYNSYM (isl_val_int_from_ui); \
++ DYNSYM (isl_val_mul); \
++ DYNSYM (isl_val_neg); \
++ DYNSYM (isl_val_sub); \
++ DYNSYM (isl_printer_print_union_map); \
++ DYNSYM (isl_pw_aff_get_ctx); \
++ DYNSYM (isl_val_is_int); \
++ DYNSYM (isl_ctx_get_max_operations); \
++ DYNSYM (isl_ctx_set_max_operations); \
++ DYNSYM (isl_ctx_last_error); \
++ DYNSYM (isl_ctx_reset_operations); \
++ DYNSYM (isl_map_coalesce); \
++ DYNSYM (isl_printer_print_schedule); \
++ DYNSYM (isl_set_set_dim_id); \
++ DYNSYM (isl_union_map_coalesce); \
++ DYNSYM (isl_multi_val_set_val); \
++ DYNSYM (isl_multi_val_zero); \
++ DYNSYM (isl_options_set_schedule_max_coefficient); \
++ DYNSYM (isl_options_set_tile_scale_tile_loops); \
++ DYNSYM (isl_schedule_copy); \
++ DYNSYM (isl_schedule_get_map); \
++ DYNSYM (isl_schedule_map_schedule_node_bottom_up); \
++ DYNSYM (isl_schedule_node_band_get_permutable); \
++ DYNSYM (isl_schedule_node_band_get_space); \
++ DYNSYM (isl_schedule_node_band_tile); \
++ DYNSYM (isl_schedule_node_child); \
++ DYNSYM (isl_schedule_node_free); \
++ DYNSYM (isl_schedule_node_get_child); \
++ DYNSYM (isl_schedule_node_get_ctx); \
++ DYNSYM (isl_schedule_node_get_type); \
++ DYNSYM (isl_schedule_node_n_children); \
++ DYNSYM (isl_union_map_is_equal); \
++ DYNSYM (isl_union_access_info_compute_flow); \
++ DYNSYM (isl_union_access_info_from_sink); \
++ DYNSYM (isl_union_access_info_set_may_source); \
++ DYNSYM (isl_union_access_info_set_must_source); \
++ DYNSYM (isl_union_access_info_set_schedule); \
++ DYNSYM (isl_union_flow_free); \
++ DYNSYM (isl_union_flow_get_may_dependence); \
++ DYNSYM (isl_union_flow_get_must_dependence); \
++ DYNSYM (isl_aff_var_on_domain); \
++ DYNSYM (isl_multi_aff_from_aff); \
++ DYNSYM (isl_schedule_get_ctx); \
++ DYNSYM (isl_multi_aff_set_tuple_id); \
++ DYNSYM (isl_multi_aff_dim); \
++ DYNSYM (isl_schedule_get_domain); \
++ DYNSYM (isl_union_set_is_empty); \
++ DYNSYM (isl_union_set_get_space); \
++ DYNSYM (isl_union_pw_multi_aff_empty); \
++ DYNSYM (isl_union_set_foreach_set); \
++ DYNSYM (isl_union_set_free); \
++ DYNSYM (isl_multi_union_pw_aff_from_union_pw_multi_aff); \
++ DYNSYM (isl_multi_union_pw_aff_apply_multi_aff); \
++ DYNSYM (isl_schedule_insert_partial_schedule); \
++ DYNSYM (isl_union_pw_multi_aff_free); \
++ DYNSYM (isl_pw_multi_aff_project_out_map); \
++ DYNSYM (isl_union_pw_multi_aff_add_pw_multi_aff); \
++ DYNSYM (isl_schedule_from_domain); \
++ DYNSYM (isl_schedule_sequence); \
++ DYNSYM (isl_ast_build_node_from_schedule); \
++ DYNSYM (isl_ast_node_mark_get_node); \
++ DYNSYM (isl_schedule_node_band_member_get_ast_loop_type); \
++ DYNSYM (isl_schedule_node_band_member_set_ast_loop_type); \
++ DYNSYM (isl_val_n_abs_num_chunks); \
++ DYNSYM (isl_val_get_abs_num_chunks); \
++ DYNSYM (isl_val_int_from_chunks); \
++ DYNSYM (isl_val_is_neg); \
++ DYNSYM (isl_version); \
++ DYNSYM (isl_options_get_on_error); \
++ DYNSYM (isl_ctx_reset_error);
++
++extern struct isl_pointers_s__
++{
++ bool inited;
++ void *h;
++#define DYNSYM(x) __typeof (x) *p_##x
++ DYNSYMS
++#undef DYNSYM
++} isl_pointers__;
++
++#define isl_aff_add_coefficient_si (*isl_pointers__.p_isl_aff_add_coefficient_si)
++#define isl_aff_free (*isl_pointers__.p_isl_aff_free)
++#define isl_aff_get_space (*isl_pointers__.p_isl_aff_get_space)
++#define isl_aff_set_coefficient_si (*isl_pointers__.p_isl_aff_set_coefficient_si)
++#define isl_aff_set_constant_si (*isl_pointers__.p_isl_aff_set_constant_si)
++#define isl_aff_zero_on_domain (*isl_pointers__.p_isl_aff_zero_on_domain)
++#define isl_band_free (*isl_pointers__.p_isl_band_free)
++#define isl_band_get_children (*isl_pointers__.p_isl_band_get_children)
++#define isl_band_get_partial_schedule (*isl_pointers__.p_isl_band_get_partial_schedule)
++#define isl_band_has_children (*isl_pointers__.p_isl_band_has_children)
++#define isl_band_list_free (*isl_pointers__.p_isl_band_list_free)
++#define isl_band_list_get_band (*isl_pointers__.p_isl_band_list_get_band)
++#define isl_band_list_get_ctx (*isl_pointers__.p_isl_band_list_get_ctx)
++#define isl_band_list_n_band (*isl_pointers__.p_isl_band_list_n_band)
++#define isl_band_n_member (*isl_pointers__.p_isl_band_n_member)
++#define isl_basic_map_add_constraint (*isl_pointers__.p_isl_basic_map_add_constraint)
++#define isl_basic_map_project_out (*isl_pointers__.p_isl_basic_map_project_out)
++#define isl_basic_map_universe (*isl_pointers__.p_isl_basic_map_universe)
++#define isl_constraint_set_coefficient_si (*isl_pointers__.p_isl_constraint_set_coefficient_si)
++#define isl_constraint_set_constant_si (*isl_pointers__.p_isl_constraint_set_constant_si)
++#define isl_ctx_alloc (*isl_pointers__.p_isl_ctx_alloc)
++#define isl_ctx_free (*isl_pointers__.p_isl_ctx_free)
++#define isl_equality_alloc (*isl_pointers__.p_isl_equality_alloc)
++#define isl_id_alloc (*isl_pointers__.p_isl_id_alloc)
++#define isl_id_copy (*isl_pointers__.p_isl_id_copy)
++#define isl_id_free (*isl_pointers__.p_isl_id_free)
++#define isl_inequality_alloc (*isl_pointers__.p_isl_inequality_alloc)
++#define isl_local_space_copy (*isl_pointers__.p_isl_local_space_copy)
++#define isl_local_space_free (*isl_pointers__.p_isl_local_space_free)
++#define isl_local_space_from_space (*isl_pointers__.p_isl_local_space_from_space)
++#define isl_local_space_range (*isl_pointers__.p_isl_local_space_range)
++#define isl_map_add_constraint (*isl_pointers__.p_isl_map_add_constraint)
++#define isl_map_add_dims (*isl_pointers__.p_isl_map_add_dims)
++#define isl_map_align_params (*isl_pointers__.p_isl_map_align_params)
++#define isl_map_apply_range (*isl_pointers__.p_isl_map_apply_range)
++#define isl_map_copy (*isl_pointers__.p_isl_map_copy)
++#define isl_map_dim (*isl_pointers__.p_isl_map_dim)
++#define isl_map_dump (*isl_pointers__.p_isl_map_dump)
++#define isl_map_equate (*isl_pointers__.p_isl_map_equate)
++#define isl_map_fix_si (*isl_pointers__.p_isl_map_fix_si)
++#define isl_map_flat_product (*isl_pointers__.p_isl_map_flat_product)
++#define isl_map_flat_range_product (*isl_pointers__.p_isl_map_flat_range_product)
++#define isl_map_free (*isl_pointers__.p_isl_map_free)
++#define isl_map_from_basic_map (*isl_pointers__.p_isl_map_from_basic_map)
++#define isl_map_from_pw_aff (*isl_pointers__.p_isl_map_from_pw_aff)
++#define isl_map_from_union_map (*isl_pointers__.p_isl_map_from_union_map)
++#define isl_map_get_ctx (*isl_pointers__.p_isl_map_get_ctx)
++#define isl_map_get_space (*isl_pointers__.p_isl_map_get_space)
++#define isl_map_get_tuple_id (*isl_pointers__.p_isl_map_get_tuple_id)
++#define isl_map_insert_dims (*isl_pointers__.p_isl_map_insert_dims)
++#define isl_map_intersect (*isl_pointers__.p_isl_map_intersect)
++#define isl_map_intersect_domain (*isl_pointers__.p_isl_map_intersect_domain)
++#define isl_map_intersect_range (*isl_pointers__.p_isl_map_intersect_range)
++#define isl_map_is_empty (*isl_pointers__.p_isl_map_is_empty)
++#define isl_map_lex_ge (*isl_pointers__.p_isl_map_lex_ge)
++#define isl_map_lex_le (*isl_pointers__.p_isl_map_lex_le)
++#define isl_map_n_out (*isl_pointers__.p_isl_map_n_out)
++#define isl_map_range (*isl_pointers__.p_isl_map_range)
++#define isl_map_set_tuple_id (*isl_pointers__.p_isl_map_set_tuple_id)
++#define isl_map_universe (*isl_pointers__.p_isl_map_universe)
++#define isl_options_set_on_error (*isl_pointers__.p_isl_options_set_on_error)
++#define isl_options_set_schedule_serialize_sccs (*isl_pointers__.p_isl_options_set_schedule_serialize_sccs)
++#define isl_printer_set_yaml_style (*isl_pointers__.p_isl_printer_set_yaml_style)
++#define isl_options_set_schedule_max_constant_term (*isl_pointers__.p_isl_options_set_schedule_max_constant_term)
++#define isl_options_set_schedule_maximize_band_depth (*isl_pointers__.p_isl_options_set_schedule_maximize_band_depth)
++#define isl_printer_free (*isl_pointers__.p_isl_printer_free)
++#define isl_printer_print_aff (*isl_pointers__.p_isl_printer_print_aff)
++#define isl_printer_print_constraint (*isl_pointers__.p_isl_printer_print_constraint)
++#define isl_printer_print_map (*isl_pointers__.p_isl_printer_print_map)
++#define isl_printer_print_set (*isl_pointers__.p_isl_printer_print_set)
++#define isl_printer_to_file (*isl_pointers__.p_isl_printer_to_file)
++#define isl_pw_aff_add (*isl_pointers__.p_isl_pw_aff_add)
++#define isl_pw_aff_alloc (*isl_pointers__.p_isl_pw_aff_alloc)
++#define isl_pw_aff_copy (*isl_pointers__.p_isl_pw_aff_copy)
++#define isl_pw_aff_eq_set (*isl_pointers__.p_isl_pw_aff_eq_set)
++#define isl_pw_aff_free (*isl_pointers__.p_isl_pw_aff_free)
++#define isl_pw_aff_from_aff (*isl_pointers__.p_isl_pw_aff_from_aff)
++#define isl_pw_aff_ge_set (*isl_pointers__.p_isl_pw_aff_ge_set)
++#define isl_pw_aff_gt_set (*isl_pointers__.p_isl_pw_aff_gt_set)
++#define isl_pw_aff_is_cst (*isl_pointers__.p_isl_pw_aff_is_cst)
++#define isl_pw_aff_le_set (*isl_pointers__.p_isl_pw_aff_le_set)
++#define isl_pw_aff_lt_set (*isl_pointers__.p_isl_pw_aff_lt_set)
++#define isl_pw_aff_mul (*isl_pointers__.p_isl_pw_aff_mul)
++#define isl_pw_aff_ne_set (*isl_pointers__.p_isl_pw_aff_ne_set)
++#define isl_pw_aff_nonneg_set (*isl_pointers__.p_isl_pw_aff_nonneg_set)
++#define isl_pw_aff_set_tuple_id (*isl_pointers__.p_isl_pw_aff_set_tuple_id)
++#define isl_pw_aff_sub (*isl_pointers__.p_isl_pw_aff_sub)
++#define isl_pw_aff_zero_set (*isl_pointers__.p_isl_pw_aff_zero_set)
++#define isl_schedule_free (*isl_pointers__.p_isl_schedule_free)
++#define isl_schedule_get_band_forest (*isl_pointers__.p_isl_schedule_get_band_forest)
++#define isl_set_add_constraint (*isl_pointers__.p_isl_set_add_constraint)
++#define isl_set_add_dims (*isl_pointers__.p_isl_set_add_dims)
++#define isl_set_apply (*isl_pointers__.p_isl_set_apply)
++#define isl_set_coalesce (*isl_pointers__.p_isl_set_coalesce)
++#define isl_set_copy (*isl_pointers__.p_isl_set_copy)
++#define isl_set_dim (*isl_pointers__.p_isl_set_dim)
++#define isl_set_fix_si (*isl_pointers__.p_isl_set_fix_si)
++#define isl_set_free (*isl_pointers__.p_isl_set_free)
++#define isl_set_get_space (*isl_pointers__.p_isl_set_get_space)
++#define isl_set_get_tuple_id (*isl_pointers__.p_isl_set_get_tuple_id)
++#define isl_set_intersect (*isl_pointers__.p_isl_set_intersect)
++#define isl_set_is_empty (*isl_pointers__.p_isl_set_is_empty)
++#define isl_set_n_dim (*isl_pointers__.p_isl_set_n_dim)
++#define isl_set_nat_universe (*isl_pointers__.p_isl_set_nat_universe)
++#define isl_set_project_out (*isl_pointers__.p_isl_set_project_out)
++#define isl_set_set_tuple_id (*isl_pointers__.p_isl_set_set_tuple_id)
++#define isl_set_universe (*isl_pointers__.p_isl_set_universe)
++#define isl_space_add_dims (*isl_pointers__.p_isl_space_add_dims)
++#define isl_space_alloc (*isl_pointers__.p_isl_space_alloc)
++#define isl_space_copy (*isl_pointers__.p_isl_space_copy)
++#define isl_space_dim (*isl_pointers__.p_isl_space_dim)
++#define isl_space_domain (*isl_pointers__.p_isl_space_domain)
++#define isl_space_find_dim_by_id (*isl_pointers__.p_isl_space_find_dim_by_id)
++#define isl_space_free (*isl_pointers__.p_isl_space_free)
++#define isl_space_from_domain (*isl_pointers__.p_isl_space_from_domain)
++#define isl_space_get_tuple_id (*isl_pointers__.p_isl_space_get_tuple_id)
++#define isl_space_params_alloc (*isl_pointers__.p_isl_space_params_alloc)
++#define isl_space_range (*isl_pointers__.p_isl_space_range)
++#define isl_space_set_alloc (*isl_pointers__.p_isl_space_set_alloc)
++#define isl_space_set_dim_id (*isl_pointers__.p_isl_space_set_dim_id)
++#define isl_space_set_tuple_id (*isl_pointers__.p_isl_space_set_tuple_id)
++#define isl_union_map_add_map (*isl_pointers__.p_isl_union_map_add_map)
++#define isl_union_map_align_params (*isl_pointers__.p_isl_union_map_align_params)
++#define isl_union_map_apply_domain (*isl_pointers__.p_isl_union_map_apply_domain)
++#define isl_union_map_apply_range (*isl_pointers__.p_isl_union_map_apply_range)
++#define isl_union_map_compute_flow (*isl_pointers__.p_isl_union_map_compute_flow)
++#define isl_union_map_copy (*isl_pointers__.p_isl_union_map_copy)
++#define isl_union_map_empty (*isl_pointers__.p_isl_union_map_empty)
++#define isl_union_map_flat_range_product (*isl_pointers__.p_isl_union_map_flat_range_product)
++#define isl_union_map_foreach_map (*isl_pointers__.p_isl_union_map_foreach_map)
++#define isl_union_map_free (*isl_pointers__.p_isl_union_map_free)
++#define isl_union_map_from_map (*isl_pointers__.p_isl_union_map_from_map)
++#define isl_union_map_get_ctx (*isl_pointers__.p_isl_union_map_get_ctx)
++#define isl_union_map_get_space (*isl_pointers__.p_isl_union_map_get_space)
++#define isl_union_map_gist_domain (*isl_pointers__.p_isl_union_map_gist_domain)
++#define isl_union_map_gist_range (*isl_pointers__.p_isl_union_map_gist_range)
++#define isl_union_map_intersect_domain (*isl_pointers__.p_isl_union_map_intersect_domain)
++#define isl_union_map_is_empty (*isl_pointers__.p_isl_union_map_is_empty)
++#define isl_union_map_subtract (*isl_pointers__.p_isl_union_map_subtract)
++#define isl_union_map_union (*isl_pointers__.p_isl_union_map_union)
++#define isl_union_set_add_set (*isl_pointers__.p_isl_union_set_add_set)
++#define isl_union_set_compute_schedule (*isl_pointers__.p_isl_union_set_compute_schedule)
++#define isl_union_set_copy (*isl_pointers__.p_isl_union_set_copy)
++#define isl_union_set_empty (*isl_pointers__.p_isl_union_set_empty)
++#define isl_union_set_from_set (*isl_pointers__.p_isl_union_set_from_set)
++#define isl_aff_add_constant_val (*isl_pointers__.p_isl_aff_add_constant_val)
++#define isl_aff_get_coefficient_val (*isl_pointers__.p_isl_aff_get_coefficient_val)
++#define isl_aff_get_ctx (*isl_pointers__.p_isl_aff_get_ctx)
++#define isl_aff_mod_val (*isl_pointers__.p_isl_aff_mod_val)
++#define isl_ast_build_ast_from_schedule (*isl_pointers__.p_isl_ast_build_ast_from_schedule)
++#define isl_ast_build_free (*isl_pointers__.p_isl_ast_build_free)
++#define isl_ast_build_from_context (*isl_pointers__.p_isl_ast_build_from_context)
++#define isl_ast_build_get_ctx (*isl_pointers__.p_isl_ast_build_get_ctx)
++#define isl_ast_build_get_schedule (*isl_pointers__.p_isl_ast_build_get_schedule)
++#define isl_ast_build_get_schedule_space (*isl_pointers__.p_isl_ast_build_get_schedule_space)
++#define isl_ast_build_set_before_each_for (*isl_pointers__.p_isl_ast_build_set_before_each_for)
++#define isl_ast_build_set_options (*isl_pointers__.p_isl_ast_build_set_options)
++#define isl_ast_expr_free (*isl_pointers__.p_isl_ast_expr_free)
++#define isl_ast_expr_from_val (*isl_pointers__.p_isl_ast_expr_from_val)
++#define isl_ast_expr_get_ctx (*isl_pointers__.p_isl_ast_expr_get_ctx)
++#define isl_ast_expr_get_id (*isl_pointers__.p_isl_ast_expr_get_id)
++#define isl_ast_expr_get_op_arg (*isl_pointers__.p_isl_ast_expr_get_op_arg)
++#define isl_ast_expr_get_op_n_arg (*isl_pointers__.p_isl_ast_expr_get_op_n_arg)
++#define isl_ast_expr_get_op_type (*isl_pointers__.p_isl_ast_expr_get_op_type)
++#define isl_ast_expr_get_type (*isl_pointers__.p_isl_ast_expr_get_type)
++#define isl_ast_expr_get_val (*isl_pointers__.p_isl_ast_expr_get_val)
++#define isl_ast_expr_sub (*isl_pointers__.p_isl_ast_expr_sub)
++#define isl_ast_node_block_get_children (*isl_pointers__.p_isl_ast_node_block_get_children)
++#define isl_ast_node_for_get_body (*isl_pointers__.p_isl_ast_node_for_get_body)
++#define isl_ast_node_for_get_cond (*isl_pointers__.p_isl_ast_node_for_get_cond)
++#define isl_ast_node_for_get_inc (*isl_pointers__.p_isl_ast_node_for_get_inc)
++#define isl_ast_node_for_get_init (*isl_pointers__.p_isl_ast_node_for_get_init)
++#define isl_ast_node_for_get_iterator (*isl_pointers__.p_isl_ast_node_for_get_iterator)
++#define isl_ast_node_free (*isl_pointers__.p_isl_ast_node_free)
++#define isl_ast_node_get_annotation (*isl_pointers__.p_isl_ast_node_get_annotation)
++#define isl_ast_node_get_type (*isl_pointers__.p_isl_ast_node_get_type)
++#define isl_ast_node_if_get_cond (*isl_pointers__.p_isl_ast_node_if_get_cond)
++#define isl_ast_node_if_get_else (*isl_pointers__.p_isl_ast_node_if_get_else)
++#define isl_ast_node_if_get_then (*isl_pointers__.p_isl_ast_node_if_get_then)
++#define isl_ast_node_list_free (*isl_pointers__.p_isl_ast_node_list_free)
++#define isl_ast_node_list_get_ast_node (*isl_pointers__.p_isl_ast_node_list_get_ast_node)
++#define isl_ast_node_list_n_ast_node (*isl_pointers__.p_isl_ast_node_list_n_ast_node)
++#define isl_ast_node_user_get_expr (*isl_pointers__.p_isl_ast_node_user_get_expr)
++#define isl_constraint_set_coefficient_val (*isl_pointers__.p_isl_constraint_set_coefficient_val)
++#define isl_constraint_set_constant_val (*isl_pointers__.p_isl_constraint_set_constant_val)
++#define isl_id_get_user (*isl_pointers__.p_isl_id_get_user)
++#define isl_local_space_get_ctx (*isl_pointers__.p_isl_local_space_get_ctx)
++#define isl_map_fix_val (*isl_pointers__.p_isl_map_fix_val)
++#define isl_options_set_ast_build_atomic_upper_bound (*isl_pointers__.p_isl_options_set_ast_build_atomic_upper_bound)
++#define isl_printer_print_ast_node (*isl_pointers__.p_isl_printer_print_ast_node)
++#define isl_printer_print_str (*isl_pointers__.p_isl_printer_print_str)
++#define isl_printer_set_output_format (*isl_pointers__.p_isl_printer_set_output_format)
++#define isl_pw_aff_mod_val (*isl_pointers__.p_isl_pw_aff_mod_val)
++#define isl_schedule_constraints_compute_schedule (*isl_pointers__.p_isl_schedule_constraints_compute_schedule)
++#define isl_schedule_constraints_on_domain (*isl_pointers__.p_isl_schedule_constraints_on_domain)
++#define isl_schedule_constraints_set_coincidence (*isl_pointers__.p_isl_schedule_constraints_set_coincidence)
++#define isl_schedule_constraints_set_proximity (*isl_pointers__.p_isl_schedule_constraints_set_proximity)
++#define isl_schedule_constraints_set_validity (*isl_pointers__.p_isl_schedule_constraints_set_validity)
++#define isl_set_get_dim_id (*isl_pointers__.p_isl_set_get_dim_id)
++#define isl_set_max_val (*isl_pointers__.p_isl_set_max_val)
++#define isl_set_min_val (*isl_pointers__.p_isl_set_min_val)
++#define isl_set_params (*isl_pointers__.p_isl_set_params)
++#define isl_space_align_params (*isl_pointers__.p_isl_space_align_params)
++#define isl_space_map_from_domain_and_range (*isl_pointers__.p_isl_space_map_from_domain_and_range)
++#define isl_space_set_tuple_name (*isl_pointers__.p_isl_space_set_tuple_name)
++#define isl_space_wrap (*isl_pointers__.p_isl_space_wrap)
++#define isl_union_map_from_domain_and_range (*isl_pointers__.p_isl_union_map_from_domain_and_range)
++#define isl_union_map_range (*isl_pointers__.p_isl_union_map_range)
++#define isl_union_set_union (*isl_pointers__.p_isl_union_set_union)
++#define isl_union_set_universe (*isl_pointers__.p_isl_union_set_universe)
++#define isl_val_2exp (*isl_pointers__.p_isl_val_2exp)
++#define isl_val_add_ui (*isl_pointers__.p_isl_val_add_ui)
++#define isl_val_copy (*isl_pointers__.p_isl_val_copy)
++#define isl_val_free (*isl_pointers__.p_isl_val_free)
++#define isl_val_int_from_si (*isl_pointers__.p_isl_val_int_from_si)
++#define isl_val_int_from_ui (*isl_pointers__.p_isl_val_int_from_ui)
++#define isl_val_mul (*isl_pointers__.p_isl_val_mul)
++#define isl_val_neg (*isl_pointers__.p_isl_val_neg)
++#define isl_val_sub (*isl_pointers__.p_isl_val_sub)
++#define isl_printer_print_union_map (*isl_pointers__.p_isl_printer_print_union_map)
++#define isl_pw_aff_get_ctx (*isl_pointers__.p_isl_pw_aff_get_ctx)
++#define isl_val_is_int (*isl_pointers__.p_isl_val_is_int)
++#define isl_ctx_get_max_operations (*isl_pointers__.p_isl_ctx_get_max_operations)
++#define isl_ctx_set_max_operations (*isl_pointers__.p_isl_ctx_set_max_operations)
++#define isl_ctx_last_error (*isl_pointers__.p_isl_ctx_last_error)
++#define isl_ctx_reset_operations (*isl_pointers__.p_isl_ctx_reset_operations)
++#define isl_map_coalesce (*isl_pointers__.p_isl_map_coalesce)
++#define isl_printer_print_schedule (*isl_pointers__.p_isl_printer_print_schedule)
++#define isl_set_set_dim_id (*isl_pointers__.p_isl_set_set_dim_id)
++#define isl_union_map_coalesce (*isl_pointers__.p_isl_union_map_coalesce)
++#define isl_multi_val_set_val (*isl_pointers__.p_isl_multi_val_set_val)
++#define isl_multi_val_zero (*isl_pointers__.p_isl_multi_val_zero)
++#define isl_options_set_schedule_max_coefficient (*isl_pointers__.p_isl_options_set_schedule_max_coefficient)
++#define isl_options_set_tile_scale_tile_loops (*isl_pointers__.p_isl_options_set_tile_scale_tile_loops)
++#define isl_schedule_copy (*isl_pointers__.p_isl_schedule_copy)
++#define isl_schedule_get_map (*isl_pointers__.p_isl_schedule_get_map)
++#define isl_schedule_map_schedule_node_bottom_up (*isl_pointers__.p_isl_schedule_map_schedule_node_bottom_up)
++#define isl_schedule_node_band_get_permutable (*isl_pointers__.p_isl_schedule_node_band_get_permutable)
++#define isl_schedule_node_band_get_space (*isl_pointers__.p_isl_schedule_node_band_get_space)
++#define isl_schedule_node_band_tile (*isl_pointers__.p_isl_schedule_node_band_tile)
++#define isl_schedule_node_child (*isl_pointers__.p_isl_schedule_node_child)
++#define isl_schedule_node_free (*isl_pointers__.p_isl_schedule_node_free)
++#define isl_schedule_node_get_child (*isl_pointers__.p_isl_schedule_node_get_child)
++#define isl_schedule_node_get_ctx (*isl_pointers__.p_isl_schedule_node_get_ctx)
++#define isl_schedule_node_get_type (*isl_pointers__.p_isl_schedule_node_get_type)
++#define isl_schedule_node_n_children (*isl_pointers__.p_isl_schedule_node_n_children)
++#define isl_union_map_is_equal (*isl_pointers__.p_isl_union_map_is_equal)
++#define isl_union_access_info_compute_flow (*isl_pointers__.p_isl_union_access_info_compute_flow)
++#define isl_union_access_info_from_sink (*isl_pointers__.p_isl_union_access_info_from_sink)
++#define isl_union_access_info_set_may_source (*isl_pointers__.p_isl_union_access_info_set_may_source)
++#define isl_union_access_info_set_must_source (*isl_pointers__.p_isl_union_access_info_set_must_source)
++#define isl_union_access_info_set_schedule (*isl_pointers__.p_isl_union_access_info_set_schedule)
++#define isl_union_flow_free (*isl_pointers__.p_isl_union_flow_free)
++#define isl_union_flow_get_may_dependence (*isl_pointers__.p_isl_union_flow_get_may_dependence)
++#define isl_union_flow_get_must_dependence (*isl_pointers__.p_isl_union_flow_get_must_dependence)
++#define isl_aff_var_on_domain (*isl_pointers__.p_isl_aff_var_on_domain)
++#define isl_multi_aff_from_aff (*isl_pointers__.p_isl_multi_aff_from_aff)
++#define isl_schedule_get_ctx (*isl_pointers__.p_isl_schedule_get_ctx)
++#define isl_multi_aff_set_tuple_id (*isl_pointers__.p_isl_multi_aff_set_tuple_id)
++#define isl_multi_aff_dim (*isl_pointers__.p_isl_multi_aff_dim)
++#define isl_schedule_get_domain (*isl_pointers__.p_isl_schedule_get_domain)
++#define isl_union_set_is_empty (*isl_pointers__.p_isl_union_set_is_empty)
++#define isl_union_set_get_space (*isl_pointers__.p_isl_union_set_get_space)
++#define isl_union_pw_multi_aff_empty (*isl_pointers__.p_isl_union_pw_multi_aff_empty)
++#define isl_union_set_foreach_set (*isl_pointers__.p_isl_union_set_foreach_set)
++#define isl_union_set_free (*isl_pointers__.p_isl_union_set_free)
++#define isl_multi_union_pw_aff_from_union_pw_multi_aff (*isl_pointers__.p_isl_multi_union_pw_aff_from_union_pw_multi_aff)
++#define isl_multi_union_pw_aff_apply_multi_aff (*isl_pointers__.p_isl_multi_union_pw_aff_apply_multi_aff)
++#define isl_schedule_insert_partial_schedule (*isl_pointers__.p_isl_schedule_insert_partial_schedule)
++#define isl_union_pw_multi_aff_free (*isl_pointers__.p_isl_union_pw_multi_aff_free)
++#define isl_pw_multi_aff_project_out_map (*isl_pointers__.p_isl_pw_multi_aff_project_out_map)
++#define isl_union_pw_multi_aff_add_pw_multi_aff (*isl_pointers__.p_isl_union_pw_multi_aff_add_pw_multi_aff)
++#define isl_schedule_from_domain (*isl_pointers__.p_isl_schedule_from_domain)
++#define isl_schedule_sequence (*isl_pointers__.p_isl_schedule_sequence)
++#define isl_ast_build_node_from_schedule (*isl_pointers__.p_isl_ast_build_node_from_schedule)
++#define isl_ast_node_mark_get_node (*isl_pointers__.p_isl_ast_node_mark_get_node)
++#define isl_schedule_node_band_member_get_ast_loop_type (*isl_pointers__.p_isl_schedule_node_band_member_get_ast_loop_type)
++#define isl_schedule_node_band_member_set_ast_loop_type (*isl_pointers__.p_isl_schedule_node_band_member_set_ast_loop_type)
++#define isl_val_n_abs_num_chunks (*isl_pointers__.p_isl_val_n_abs_num_chunks)
++#define isl_val_get_abs_num_chunks (*isl_pointers__.p_isl_val_get_abs_num_chunks)
++#define isl_val_int_from_chunks (*isl_pointers__.p_isl_val_int_from_chunks)
++#define isl_val_is_neg (*isl_pointers__.p_isl_val_is_neg)
++#define isl_version (*isl_pointers__.p_isl_version)
++#define isl_options_get_on_error (*isl_pointers__.p_isl_options_get_on_error)
++#define isl_ctx_reset_error (*isl_pointers__.p_isl_ctx_reset_error)
+
+ typedef struct poly_dr *poly_dr_p;
+
+@@ -461,5 +1045,6 @@ extern void build_scops (vec *);
+ extern void dot_all_sese (FILE *, vec &);
+ extern void dot_sese (sese_l &);
+ extern void dot_cfg ();
++extern const char *get_isl_version (bool);
+
+ #endif
+--- gcc/graphite.c.jj 2015-11-04 14:15:32.000000000 +0100
++++ gcc/graphite.c 2015-11-04 14:56:02.645536409 +0100
+@@ -60,6 +60,35 @@ along with GCC; see the file COPYING3.
+ #include "tree-into-ssa.h"
+ #include "graphite.h"
+
++__typeof (isl_pointers__) isl_pointers__;
++
++static bool
++init_isl_pointers (void)
++{
++ void *h;
++
++ if (isl_pointers__.inited)
++ return isl_pointers__.h != NULL;
++ h = dlopen ("libisl.so.15", RTLD_LAZY);
++ isl_pointers__.h = h;
++ if (h == NULL)
++ return false;
++#define DYNSYM(x) \
++ do \
++ { \
++ union { __typeof (isl_pointers__.p_##x) p; void *q; } u; \
++ u.q = dlsym (h, #x); \
++ if (u.q == NULL) \
++ return false; \
++ isl_pointers__.p_##x = u.p; \
++ } \
++ while (0)
++ DYNSYMS
++#undef DYNSYM
++ isl_pointers__.inited = true;
++ return true;
++}
++
+ /* Print global statistics to FILE. */
+
+ static void
+@@ -365,6 +394,15 @@ graphite_transform_loops (void)
+ if (parallelized_function_p (cfun->decl))
+ return;
+
++ if (number_of_loops (cfun) <= 1)
++ return;
++
++ if (!init_isl_pointers ())
++ {
++ sorry ("Graphite loop optimizations cannot be used");
++ return;
++ }
++
+ calculate_dominance_info (CDI_DOMINATORS);
+
+ /* We rely on post-dominators during merging of SESE regions so those
+@@ -455,6 +493,14 @@ graphite_transform_loops (void)
+ }
+ }
+
++const char *
++get_isl_version (bool force)
++{
++ if (force)
++ init_isl_pointers ();
++ return (isl_pointers__.inited && isl_version) ? isl_version () : "none";
++}
++
+ #else /* If isl is not available: #ifndef HAVE_isl. */
+
+ static void
+--- gcc/toplev.c.jj 2017-02-19 13:02:31.000000000 +0100
++++ gcc/toplev.c 2017-02-19 16:50:25.536301350 +0100
+@@ -94,6 +94,7 @@ along with GCC; see the file COPYING3.
+
+ #ifdef HAVE_isl
+ #include
++extern const char *get_isl_version (bool);
+ #endif
+
+ static void general_init (const char *, bool);
+@@ -683,7 +684,7 @@ print_version (FILE *file, const char *i
+ #ifndef HAVE_isl
+ "none"
+ #else
+- isl_version ()
++ get_isl_version (*indent == 0)
+ #endif
+ );
+ if (strcmp (GCC_GMP_STRINGIFY_VERSION, gmp_version))
diff --git a/SOURCES/gcc8-libgcc-hardened.patch b/SOURCES/gcc8-libgcc-hardened.patch
new file mode 100644
index 0000000..51f6c39
--- /dev/null
+++ b/SOURCES/gcc8-libgcc-hardened.patch
@@ -0,0 +1,14 @@
+--- libgcc/config/t-slibgcc.mp 2018-10-03 16:07:00.336990246 -0400
++++ libgcc/config/t-slibgcc 2018-10-03 16:06:26.719946740 -0400
+@@ -30,9 +30,10 @@ SHLIB_LC = -lc
+ SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
+ SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \
+ $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
++SHLIB_EXTRA_LDFLAGS = -Wl,-z,relro -Wl,-z,now
+
+ SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+- $(SHLIB_LDFLAGS) \
++ $(SHLIB_LDFLAGS) $(SHLIB_EXTRA_LDFLAGS) \
+ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
+ $(SHLIB_OBJS) $(SHLIB_LC) && \
+ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
diff --git a/SOURCES/gcc8-libgomp-20190503.patch b/SOURCES/gcc8-libgomp-20190503.patch
new file mode 100644
index 0000000..caa13f2
--- /dev/null
+++ b/SOURCES/gcc8-libgomp-20190503.patch
@@ -0,0 +1,10060 @@
+--- libgomp/loop.c.jj 2018-04-25 09:40:31.870655561 +0200
++++ libgomp/loop.c 2019-05-07 18:46:36.526109736 +0200
+@@ -27,9 +27,13 @@
+
+ #include
+ #include
++#include
+ #include "libgomp.h"
+
+
++ialias (GOMP_loop_runtime_next)
++ialias_redirect (GOMP_taskgroup_reduction_register)
++
+ /* Initialize the given work share construct from the given arguments. */
+
+ static inline void
+@@ -79,12 +83,12 @@ gomp_loop_init (struct gomp_work_share *
+ }
+
+ /* The *_start routines are called when first encountering a loop construct
+- that is not bound directly to a parallel construct. The first thread
++ that is not bound directly to a parallel construct. The first thread
+ that arrives will create the work-share construct; subsequent threads
+ will see the construct exists and allocate work from it.
+
+ START, END, INCR are the bounds of the loop; due to the restrictions of
+- OpenMP, these values must be the same in every thread. This is not
++ OpenMP, these values must be the same in every thread. This is not
+ verified (nor is it entirely verifiable, since START is not necessarily
+ retained intact in the work-share data structure). CHUNK_SIZE is the
+ scheduling parameter; again this must be identical in all threads.
+@@ -101,7 +105,7 @@ gomp_loop_static_start (long start, long
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_STATIC, chunk_size);
+@@ -123,7 +127,7 @@ gomp_loop_dynamic_start (long start, lon
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_DYNAMIC, chunk_size);
+@@ -151,7 +155,7 @@ gomp_loop_guided_start (long start, long
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_GUIDED, chunk_size);
+@@ -174,7 +178,7 @@ GOMP_loop_runtime_start (long start, lon
+ long *istart, long *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_static_start (start, end, incr,
+@@ -197,6 +201,100 @@ GOMP_loop_runtime_start (long start, lon
+ }
+ }
+
++static long
++gomp_adjust_sched (long sched, long *chunk_size)
++{
++ sched &= ~GFS_MONOTONIC;
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_DYNAMIC:
++ case GFS_GUIDED:
++ return sched;
++ /* GFS_RUNTIME is used for runtime schedule without monotonic
++ or nonmonotonic modifiers on the clause.
++ GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic
++ modifier. */
++ case GFS_RUNTIME:
++ /* GFS_AUTO is used for runtime schedule with nonmonotonic
++ modifier. */
++ case GFS_AUTO:
++ {
++ struct gomp_task_icv *icv = gomp_icv (false);
++ sched = icv->run_sched_var & ~GFS_MONOTONIC;
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_DYNAMIC:
++ case GFS_GUIDED:
++ *chunk_size = icv->run_sched_chunk_size;
++ break;
++ case GFS_AUTO:
++ sched = GFS_STATIC;
++ *chunk_size = 0;
++ break;
++ default:
++ abort ();
++ }
++ return sched;
++ }
++ default:
++ abort ();
++ }
++}
++
++bool
++GOMP_loop_start (long start, long end, long incr, long sched,
++ long chunk_size, long *istart, long *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (gomp_work_share_start (0))
++ {
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_init (thr->ts.work_share, start, end, incr,
++ sched, chunk_size);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ if (mem)
++ {
++ uintptr_t size = (uintptr_t) *mem;
++ if (size > (sizeof (struct gomp_work_share)
++ - offsetof (struct gomp_work_share,
++ inline_ordered_team_ids)))
++ thr->ts.work_share->ordered_team_ids
++ = gomp_malloc_cleared (size);
++ else
++ memset (thr->ts.work_share->ordered_team_ids, '\0', size);
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ if (mem)
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++
++ if (!istart)
++ return true;
++ return ialias_call (GOMP_loop_runtime_next) (istart, iend);
++}
++
+ /* The *_ordered_*_start routines are similar. The only difference is that
+ this work-share construct is initialized to expect an ORDERED section. */
+
+@@ -207,7 +305,7 @@ gomp_loop_ordered_static_start (long sta
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_STATIC, chunk_size);
+@@ -225,7 +323,7 @@ gomp_loop_ordered_dynamic_start (long st
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_DYNAMIC, chunk_size);
+@@ -250,7 +348,7 @@ gomp_loop_ordered_guided_start (long sta
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_init (thr->ts.work_share, start, end, incr,
+ GFS_GUIDED, chunk_size);
+@@ -273,7 +371,7 @@ GOMP_loop_ordered_runtime_start (long st
+ long *istart, long *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_ordered_static_start (start, end, incr,
+@@ -297,6 +395,81 @@ GOMP_loop_ordered_runtime_start (long st
+ }
+ }
+
++bool
++GOMP_loop_ordered_start (long start, long end, long incr, long sched,
++ long chunk_size, long *istart, long *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ size_t ordered = 1;
++ bool ret;
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (mem)
++ ordered += (uintptr_t) *mem;
++ if (gomp_work_share_start (ordered))
++ {
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_init (thr->ts.work_share, start, end, incr,
++ sched, chunk_size);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ if (sched == GFS_STATIC)
++ gomp_ordered_static_init ();
++ else
++ gomp_mutex_lock (&thr->ts.work_share->lock);
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ sched = thr->ts.work_share->sched;
++ if (sched != GFS_STATIC)
++ gomp_mutex_lock (&thr->ts.work_share->lock);
++ }
++
++ if (mem)
++ {
++ uintptr_t p
++ = (uintptr_t) (thr->ts.work_share->ordered_team_ids
++ + (thr->ts.team ? thr->ts.team->nthreads : 1));
++ p += __alignof__ (long long) - 1;
++ p &= ~(__alignof__ (long long) - 1);
++ *mem = (void *) p;
++ }
++
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_AUTO:
++ return !gomp_iter_static_next (istart, iend);
++ case GFS_DYNAMIC:
++ ret = gomp_iter_dynamic_next_locked (istart, iend);
++ break;
++ case GFS_GUIDED:
++ ret = gomp_iter_guided_next_locked (istart, iend);
++ break;
++ default:
++ abort ();
++ }
++
++ if (ret)
++ gomp_ordered_first ();
++ gomp_mutex_unlock (&thr->ts.work_share->lock);
++ return ret;
++}
++
+ /* The *_doacross_*_start routines are similar. The only difference is that
+ this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
+ section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
+@@ -310,11 +483,11 @@ gomp_loop_doacross_static_start (unsigne
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
+ GFS_STATIC, chunk_size);
+- gomp_doacross_init (ncounts, counts, chunk_size);
++ gomp_doacross_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -328,11 +501,11 @@ gomp_loop_doacross_dynamic_start (unsign
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
+ GFS_DYNAMIC, chunk_size);
+- gomp_doacross_init (ncounts, counts, chunk_size);
++ gomp_doacross_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -354,11 +527,11 @@ gomp_loop_doacross_guided_start (unsigne
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
+ GFS_GUIDED, chunk_size);
+- gomp_doacross_init (ncounts, counts, chunk_size);
++ gomp_doacross_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -378,7 +551,7 @@ GOMP_loop_doacross_runtime_start (unsign
+ long *istart, long *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_doacross_static_start (ncounts, counts,
+@@ -402,8 +575,52 @@ GOMP_loop_doacross_runtime_start (unsign
+ }
+ }
+
+-/* The *_next routines are called when the thread completes processing of
+- the iteration block currently assigned to it. If the work-share
++bool
++GOMP_loop_doacross_start (unsigned ncounts, long *counts, long sched,
++ long chunk_size, long *istart, long *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (gomp_work_share_start (0))
++ {
++ size_t extra = 0;
++ if (mem)
++ extra = (uintptr_t) *mem;
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_init (thr->ts.work_share, 0, counts[0], 1,
++ sched, chunk_size);
++ gomp_doacross_init (ncounts, counts, chunk_size, extra);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ sched = thr->ts.work_share->sched;
++ }
++
++ if (mem)
++ *mem = thr->ts.work_share->doacross->extra;
++
++ return ialias_call (GOMP_loop_runtime_next) (istart, iend);
++}
++
++/* The *_next routines are called when the thread completes processing of
++ the iteration block currently assigned to it. If the work-share
+ construct is bound directly to a parallel construct, then the iteration
+ bounds may have been set up before the parallel. In which case, this
+ may be the first iteration for the thread.
+@@ -456,7 +673,7 @@ bool
+ GOMP_loop_runtime_next (long *istart, long *iend)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+-
++
+ switch (thr->ts.work_share->sched)
+ {
+ case GFS_STATIC:
+@@ -534,7 +751,7 @@ bool
+ GOMP_loop_ordered_runtime_next (long *istart, long *iend)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+-
++
+ switch (thr->ts.work_share->sched)
+ {
+ case GFS_STATIC:
+@@ -563,7 +780,7 @@ gomp_parallel_loop_start (void (*fn) (vo
+ num_threads = gomp_resolve_num_threads (num_threads, 0);
+ team = gomp_new_team (num_threads);
+ gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size);
+- gomp_team_start (fn, data, num_threads, flags, team);
++ gomp_team_start (fn, data, num_threads, flags, team, NULL);
+ }
+
+ void
+@@ -600,7 +817,8 @@ GOMP_parallel_loop_runtime_start (void (
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+- icv->run_sched_var, icv->run_sched_chunk_size, 0);
++ icv->run_sched_var & ~GFS_MONOTONIC,
++ icv->run_sched_chunk_size, 0);
+ }
+
+ ialias_redirect (GOMP_parallel_end)
+@@ -638,11 +856,28 @@ GOMP_parallel_loop_guided (void (*fn) (v
+ GOMP_parallel_end ();
+ }
+
++void
++GOMP_parallel_loop_runtime (void (*fn) (void *), void *data,
++ unsigned num_threads, long start, long end,
++ long incr, unsigned flags)
++{
++ struct gomp_task_icv *icv = gomp_icv (false);
++ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
++ icv->run_sched_var & ~GFS_MONOTONIC,
++ icv->run_sched_chunk_size, flags);
++ fn (data);
++ GOMP_parallel_end ();
++}
++
+ #ifdef HAVE_ATTRIBUTE_ALIAS
+ extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic
+ __attribute__((alias ("GOMP_parallel_loop_dynamic")));
+ extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided
+ __attribute__((alias ("GOMP_parallel_loop_guided")));
++extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_nonmonotonic_runtime
++ __attribute__((alias ("GOMP_parallel_loop_runtime")));
++extern __typeof(GOMP_parallel_loop_runtime) GOMP_parallel_loop_maybe_nonmonotonic_runtime
++ __attribute__((alias ("GOMP_parallel_loop_runtime")));
+ #else
+ void
+ GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data,
+@@ -667,21 +902,35 @@ GOMP_parallel_loop_nonmonotonic_guided (
+ fn (data);
+ GOMP_parallel_end ();
+ }
+-#endif
+
+ void
+-GOMP_parallel_loop_runtime (void (*fn) (void *), void *data,
+- unsigned num_threads, long start, long end,
+- long incr, unsigned flags)
++GOMP_parallel_loop_nonmonotonic_runtime (void (*fn) (void *), void *data,
++ unsigned num_threads, long start,
++ long end, long incr, unsigned flags)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+- icv->run_sched_var, icv->run_sched_chunk_size,
+- flags);
++ icv->run_sched_var & ~GFS_MONOTONIC,
++ icv->run_sched_chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+ }
+
++void
++GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*fn) (void *), void *data,
++ unsigned num_threads, long start,
++ long end, long incr,
++ unsigned flags)
++{
++ struct gomp_task_icv *icv = gomp_icv (false);
++ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
++ icv->run_sched_var & ~GFS_MONOTONIC,
++ icv->run_sched_chunk_size, flags);
++ fn (data);
++ GOMP_parallel_end ();
++}
++#endif
++
+ /* The GOMP_loop_end* routines are called after the thread is told that
+ all loop iterations are complete. The first two versions synchronize
+ all threads; the nowait version does not. */
+@@ -721,6 +970,10 @@ extern __typeof(gomp_loop_dynamic_start)
+ __attribute__((alias ("gomp_loop_dynamic_start")));
+ extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start
+ __attribute__((alias ("gomp_loop_guided_start")));
++extern __typeof(GOMP_loop_runtime_start) GOMP_loop_nonmonotonic_runtime_start
++ __attribute__((alias ("GOMP_loop_runtime_start")));
++extern __typeof(GOMP_loop_runtime_start) GOMP_loop_maybe_nonmonotonic_runtime_start
++ __attribute__((alias ("GOMP_loop_runtime_start")));
+
+ extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start
+ __attribute__((alias ("gomp_loop_ordered_static_start")));
+@@ -746,6 +999,10 @@ extern __typeof(gomp_loop_dynamic_next)
+ __attribute__((alias ("gomp_loop_dynamic_next")));
+ extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next
+ __attribute__((alias ("gomp_loop_guided_next")));
++extern __typeof(GOMP_loop_runtime_next) GOMP_loop_nonmonotonic_runtime_next
++ __attribute__((alias ("GOMP_loop_runtime_next")));
++extern __typeof(GOMP_loop_runtime_next) GOMP_loop_maybe_nonmonotonic_runtime_next
++ __attribute__((alias ("GOMP_loop_runtime_next")));
+
+ extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next
+ __attribute__((alias ("gomp_loop_ordered_static_next")));
+@@ -791,6 +1048,20 @@ GOMP_loop_nonmonotonic_guided_start (lon
+ }
+
+ bool
++GOMP_loop_nonmonotonic_runtime_start (long start, long end, long incr,
++ long *istart, long *iend)
++{
++ return GOMP_loop_runtime_start (start, end, incr, istart, iend);
++}
++
++bool
++GOMP_loop_maybe_nonmonotonic_runtime_start (long start, long end, long incr,
++ long *istart, long *iend)
++{
++ return GOMP_loop_runtime_start (start, end, incr, istart, iend);
++}
++
++bool
+ GOMP_loop_ordered_static_start (long start, long end, long incr,
+ long chunk_size, long *istart, long *iend)
+ {
+@@ -869,6 +1140,18 @@ GOMP_loop_nonmonotonic_guided_next (long
+ }
+
+ bool
++GOMP_loop_nonmonotonic_runtime_next (long *istart, long *iend)
++{
++ return GOMP_loop_runtime_next (istart, iend);
++}
++
++bool
++GOMP_loop_maybe_nonmonotonic_runtime_next (long *istart, long *iend)
++{
++ return GOMP_loop_runtime_next (istart, iend);
++}
++
++bool
+ GOMP_loop_ordered_static_next (long *istart, long *iend)
+ {
+ return gomp_loop_ordered_static_next (istart, iend);
+--- libgomp/oacc-plugin.c.jj 2018-04-25 09:40:31.322655307 +0200
++++ libgomp/oacc-plugin.c 2019-05-07 18:46:36.531109656 +0200
+@@ -49,3 +49,14 @@ GOMP_PLUGIN_acc_thread (void)
+ struct goacc_thread *thr = goacc_thread ();
+ return thr ? thr->target_tls : NULL;
+ }
++
++int
++GOMP_PLUGIN_acc_default_dim (unsigned int i)
++{
++ if (i >= GOMP_DIM_MAX)
++ {
++ gomp_fatal ("invalid dimension argument: %d", i);
++ return -1;
++ }
++ return goacc_default_dims[i];
++}
+--- libgomp/libgomp_g.h.jj 2018-04-25 09:40:31.320655306 +0200
++++ libgomp/libgomp_g.h 2019-05-07 18:46:36.513109943 +0200
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
++/* Copyright (C) 2005-2019 Free Software Foundation, Inc.
+ Contributed by Richard Henderson .
+
+ This file is part of the GNU Offloading and Multi Processing Library
+@@ -31,6 +31,7 @@
+
+ #include
+ #include
++#include "gstdint.h"
+
+ /* barrier.c */
+
+@@ -56,6 +57,12 @@ extern bool GOMP_loop_nonmonotonic_dynam
+ long *, long *);
+ extern bool GOMP_loop_nonmonotonic_guided_start (long, long, long, long,
+ long *, long *);
++extern bool GOMP_loop_nonmonotonic_runtime_start (long, long, long,
++ long *, long *);
++extern bool GOMP_loop_maybe_nonmonotonic_runtime_start (long, long, long,
++ long *, long *);
++extern bool GOMP_loop_start (long, long, long, long, long, long *, long *,
++ uintptr_t *, void **);
+
+ extern bool GOMP_loop_ordered_static_start (long, long, long, long,
+ long *, long *);
+@@ -64,6 +71,8 @@ extern bool GOMP_loop_ordered_dynamic_st
+ extern bool GOMP_loop_ordered_guided_start (long, long, long, long,
+ long *, long *);
+ extern bool GOMP_loop_ordered_runtime_start (long, long, long, long *, long *);
++extern bool GOMP_loop_ordered_start (long, long, long, long, long, long *,
++ long *, uintptr_t *, void **);
+
+ extern bool GOMP_loop_static_next (long *, long *);
+ extern bool GOMP_loop_dynamic_next (long *, long *);
+@@ -71,6 +80,8 @@ extern bool GOMP_loop_guided_next (long
+ extern bool GOMP_loop_runtime_next (long *, long *);
+ extern bool GOMP_loop_nonmonotonic_dynamic_next (long *, long *);
+ extern bool GOMP_loop_nonmonotonic_guided_next (long *, long *);
++extern bool GOMP_loop_nonmonotonic_runtime_next (long *, long *);
++extern bool GOMP_loop_maybe_nonmonotonic_runtime_next (long *, long *);
+
+ extern bool GOMP_loop_ordered_static_next (long *, long *);
+ extern bool GOMP_loop_ordered_dynamic_next (long *, long *);
+@@ -85,6 +96,8 @@ extern bool GOMP_loop_doacross_guided_st
+ long *);
+ extern bool GOMP_loop_doacross_runtime_start (unsigned, long *, long *,
+ long *);
++extern bool GOMP_loop_doacross_start (unsigned, long *, long, long, long *,
++ long *, uintptr_t *, void **);
+
+ extern void GOMP_parallel_loop_static_start (void (*)(void *), void *,
+ unsigned, long, long, long, long);
+@@ -112,6 +125,13 @@ extern void GOMP_parallel_loop_nonmonoto
+ extern void GOMP_parallel_loop_nonmonotonic_guided (void (*)(void *), void *,
+ unsigned, long, long,
+ long, long, unsigned);
++extern void GOMP_parallel_loop_nonmonotonic_runtime (void (*)(void *), void *,
++ unsigned, long, long,
++ long, unsigned);
++extern void GOMP_parallel_loop_maybe_nonmonotonic_runtime (void (*)(void *),
++ void *, unsigned,
++ long, long,
++ long, unsigned);
+
+ extern void GOMP_loop_end (void);
+ extern void GOMP_loop_end_nowait (void);
+@@ -154,6 +174,21 @@ extern bool GOMP_loop_ull_nonmonotonic_g
+ unsigned long long,
+ unsigned long long *,
+ unsigned long long *);
++extern bool GOMP_loop_ull_nonmonotonic_runtime_start (bool, unsigned long long,
++ unsigned long long,
++ unsigned long long,
++ unsigned long long *,
++ unsigned long long *);
++extern bool GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool,
++ unsigned long long,
++ unsigned long long,
++ unsigned long long,
++ unsigned long long *,
++ unsigned long long *);
++extern bool GOMP_loop_ull_start (bool, unsigned long long, unsigned long long,
++ unsigned long long, long, unsigned long long,
++ unsigned long long *, unsigned long long *,
++ uintptr_t *, void **);
+
+ extern bool GOMP_loop_ull_ordered_static_start (bool, unsigned long long,
+ unsigned long long,
+@@ -178,6 +213,13 @@ extern bool GOMP_loop_ull_ordered_runtim
+ unsigned long long,
+ unsigned long long *,
+ unsigned long long *);
++extern bool GOMP_loop_ull_ordered_start (bool, unsigned long long,
++ unsigned long long,
++ unsigned long long, long,
++ unsigned long long,
++ unsigned long long *,
++ unsigned long long *,
++ uintptr_t *, void **);
+
+ extern bool GOMP_loop_ull_static_next (unsigned long long *,
+ unsigned long long *);
+@@ -191,6 +233,10 @@ extern bool GOMP_loop_ull_nonmonotonic_d
+ unsigned long long *);
+ extern bool GOMP_loop_ull_nonmonotonic_guided_next (unsigned long long *,
+ unsigned long long *);
++extern bool GOMP_loop_ull_nonmonotonic_runtime_next (unsigned long long *,
++ unsigned long long *);
++extern bool GOMP_loop_ull_maybe_nonmonotonic_runtime_next (unsigned long long *,
++ unsigned long long *);
+
+ extern bool GOMP_loop_ull_ordered_static_next (unsigned long long *,
+ unsigned long long *);
+@@ -220,6 +266,11 @@ extern bool GOMP_loop_ull_doacross_runti
+ unsigned long long *,
+ unsigned long long *,
+ unsigned long long *);
++extern bool GOMP_loop_ull_doacross_start (unsigned, unsigned long long *,
++ long, unsigned long long,
++ unsigned long long *,
++ unsigned long long *,
++ uintptr_t *, void **);
+
+ /* ordered.c */
+
+@@ -235,6 +286,8 @@ extern void GOMP_doacross_ull_wait (unsi
+ extern void GOMP_parallel_start (void (*) (void *), void *, unsigned);
+ extern void GOMP_parallel_end (void);
+ extern void GOMP_parallel (void (*) (void *), void *, unsigned, unsigned);
++extern unsigned GOMP_parallel_reductions (void (*) (void *), void *, unsigned,
++ unsigned);
+ extern bool GOMP_cancel (int, bool);
+ extern bool GOMP_cancellation_point (int);
+
+@@ -251,13 +304,19 @@ extern void GOMP_taskloop_ull (void (*)
+ unsigned long long, unsigned long long,
+ unsigned long long);
+ extern void GOMP_taskwait (void);
++extern void GOMP_taskwait_depend (void **);
+ extern void GOMP_taskyield (void);
+ extern void GOMP_taskgroup_start (void);
+ extern void GOMP_taskgroup_end (void);
++extern void GOMP_taskgroup_reduction_register (uintptr_t *);
++extern void GOMP_taskgroup_reduction_unregister (uintptr_t *);
++extern void GOMP_task_reduction_remap (size_t, size_t, void **);
++extern void GOMP_workshare_task_reduction_unregister (bool);
+
+ /* sections.c */
+
+ extern unsigned GOMP_sections_start (unsigned);
++extern unsigned GOMP_sections2_start (unsigned, uintptr_t *, void **);
+ extern unsigned GOMP_sections_next (void);
+ extern void GOMP_parallel_sections_start (void (*) (void *), void *,
+ unsigned, unsigned);
+@@ -293,6 +352,11 @@ extern void GOMP_target_enter_exit_data
+ void **);
+ extern void GOMP_teams (unsigned int, unsigned int);
+
++/* teams.c */
++
++extern void GOMP_teams_reg (void (*) (void *), void *, unsigned, unsigned,
++ unsigned);
++
+ /* oacc-parallel.c */
+
+ extern void GOACC_parallel_keyed (int, void (*) (void *), size_t,
+--- libgomp/affinity.c.jj 2018-04-25 09:40:31.913655581 +0200
++++ libgomp/affinity.c 2019-05-07 18:46:36.254114081 +0200
+@@ -26,6 +26,8 @@
+ /* This is a generic stub implementation of a CPU affinity setting. */
+
+ #include "libgomp.h"
++#include
++#include
+
+ void
+ gomp_init_affinity (void)
+@@ -138,5 +140,17 @@ gomp_get_place_proc_ids_8 (int place_num
+ (void) ids;
+ }
+
++void
++gomp_display_affinity_place (char *buffer, size_t size, size_t *ret,
++ int place)
++{
++ char buf[sizeof (long) * 3 + 4];
++ if (gomp_available_cpus > 1)
++ sprintf (buf, "0-%lu", gomp_available_cpus - 1);
++ else
++ strcpy (buf, "0");
++ gomp_display_string (buffer, size, ret, buf, strlen (buf));
++}
++
+ ialias(omp_get_place_num_procs)
+ ialias(omp_get_place_proc_ids)
+--- libgomp/sections.c.jj 2018-04-25 09:40:31.924655586 +0200
++++ libgomp/sections.c 2019-05-07 18:46:36.535109592 +0200
+@@ -26,8 +26,11 @@
+ /* This file handles the SECTIONS construct. */
+
+ #include "libgomp.h"
++#include
+
+
++ialias_redirect (GOMP_taskgroup_reduction_register)
++
+ /* Initialize the given work share construct from the given arguments. */
+
+ static inline void
+@@ -72,7 +75,7 @@ GOMP_sections_start (unsigned count)
+ struct gomp_thread *thr = gomp_thread ();
+ long s, e, ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_sections_init (thr->ts.work_share, count);
+ gomp_work_share_init_done ();
+@@ -95,6 +98,66 @@ GOMP_sections_start (unsigned count)
+ return ret;
+ }
+
++unsigned
++GOMP_sections2_start (unsigned count, uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ long s, e, ret;
++
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (gomp_work_share_start (0))
++ {
++ gomp_sections_init (thr->ts.work_share, count);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ if (mem)
++ {
++ uintptr_t size = (uintptr_t) *mem;
++ if (size > (sizeof (struct gomp_work_share)
++ - offsetof (struct gomp_work_share,
++ inline_ordered_team_ids)))
++ thr->ts.work_share->ordered_team_ids
++ = gomp_malloc_cleared (size);
++ else
++ memset (thr->ts.work_share->ordered_team_ids, '\0', size);
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ if (mem)
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++
++#ifdef HAVE_SYNC_BUILTINS
++ if (gomp_iter_dynamic_next (&s, &e))
++ ret = s;
++ else
++ ret = 0;
++#else
++ gomp_mutex_lock (&thr->ts.work_share->lock);
++ if (gomp_iter_dynamic_next_locked (&s, &e))
++ ret = s;
++ else
++ ret = 0;
++ gomp_mutex_unlock (&thr->ts.work_share->lock);
++#endif
++
++ return ret;
++}
++
+ /* This routine is called when the thread completes processing of the
+ section currently assigned to it. If the work-share construct is
+ bound directly to a parallel construct, then the construct may have
+@@ -140,7 +203,7 @@ GOMP_parallel_sections_start (void (*fn)
+ num_threads = gomp_resolve_num_threads (num_threads, count);
+ team = gomp_new_team (num_threads);
+ gomp_sections_init (&team->work_shares[0], count);
+- gomp_team_start (fn, data, num_threads, 0, team);
++ gomp_team_start (fn, data, num_threads, 0, team, NULL);
+ }
+
+ ialias_redirect (GOMP_parallel_end)
+@@ -154,7 +217,7 @@ GOMP_parallel_sections (void (*fn) (void
+ num_threads = gomp_resolve_num_threads (num_threads, count);
+ team = gomp_new_team (num_threads);
+ gomp_sections_init (&team->work_shares[0], count);
+- gomp_team_start (fn, data, num_threads, flags, team);
++ gomp_team_start (fn, data, num_threads, flags, team, NULL);
+ fn (data);
+ GOMP_parallel_end ();
+ }
+--- libgomp/config/linux/affinity.c.jj 2018-04-25 09:40:31.875655563 +0200
++++ libgomp/config/linux/affinity.c 2019-05-07 18:46:36.344112642 +0200
+@@ -396,6 +396,56 @@ gomp_get_place_proc_ids_8 (int place_num
+ *ids++ = i;
+ }
+
++void
++gomp_display_affinity_place (char *buffer, size_t size, size_t *ret,
++ int place)
++{
++ cpu_set_t *cpusetp;
++ char buf[sizeof (long) * 3 + 4];
++ if (place >= 0 && place < gomp_places_list_len)
++ cpusetp = (cpu_set_t *) gomp_places_list[place];
++ else if (gomp_cpusetp)
++ cpusetp = gomp_cpusetp;
++ else
++ {
++ if (gomp_available_cpus > 1)
++ sprintf (buf, "0-%lu", gomp_available_cpus - 1);
++ else
++ strcpy (buf, "0");
++ gomp_display_string (buffer, size, ret, buf, strlen (buf));
++ return;
++ }
++
++ unsigned long i, max = 8 * gomp_cpuset_size, start;
++ bool prev_set = false;
++ start = max;
++ for (i = 0; i <= max; i++)
++ {
++ bool this_set;
++ if (i == max)
++ this_set = false;
++ else
++ this_set = CPU_ISSET_S (i, gomp_cpuset_size, cpusetp);
++ if (this_set != prev_set)
++ {
++ prev_set = this_set;
++ if (this_set)
++ {
++ char *p = buf;
++ if (start != max)
++ *p++ = ',';
++ sprintf (p, "%lu", i);
++ start = i;
++ }
++ else if (i == start + 1)
++ continue;
++ else
++ sprintf (buf, "-%lu", i - 1);
++ gomp_display_string (buffer, size, ret, buf, strlen (buf));
++ }
++ }
++}
++
+ ialias(omp_get_place_num_procs)
+ ialias(omp_get_place_proc_ids)
+
+--- libgomp/config/linux/ia64/futex.h.jj 2018-04-25 09:40:31.877655564 +0200
++++ libgomp/config/linux/ia64/futex.h 2019-05-07 18:46:36.344112642 +0200
+@@ -45,8 +45,8 @@ sys_futex0(int *addr, int op, int val)
+ "=r"(r8), "=r"(r10)
+ : "r"(r15), "r"(out0), "r"(out1), "r"(out2), "r"(out3)
+ : "memory", "out4", "out5", "out6", "out7",
+- /* Non-stacked integer registers, minus r8, r10, r15. */
+- "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",
++ /* Non-stacked integer registers, minus r8, r10, r12, r15. */
++ "r2", "r3", "r9", "r11", "r13", "r14", "r16", "r17", "r18",
+ "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",
+ "r28", "r29", "r30", "r31",
+ /* Predicate registers. */
+--- libgomp/config/nvptx/teams.c.jj 2019-05-07 18:46:36.459110805 +0200
++++ libgomp/config/nvptx/teams.c 2019-05-07 18:46:36.459110805 +0200
+@@ -0,0 +1,57 @@
++/* Copyright (C) 2015-2019 Free Software Foundation, Inc.
++ Contributed by Alexander Monakov
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++/* This file defines OpenMP API entry points that accelerator targets are
++ expected to replace. */
++
++#include "libgomp.h"
++
++void
++GOMP_teams_reg (void (*fn) (void *), void *data, unsigned int num_teams,
++ unsigned int thread_limit, unsigned int flags)
++{
++ (void) fn;
++ (void) data;
++ (void) flags;
++ (void) num_teams;
++ (void) thread_limit;
++}
++
++int
++omp_get_num_teams (void)
++{
++ return gomp_num_teams_var + 1;
++}
++
++int
++omp_get_team_num (void)
++{
++ int ctaid;
++ asm ("mov.u32 %0, %%ctaid.x;" : "=r" (ctaid));
++ return ctaid;
++}
++
++ialias (omp_get_num_teams)
++ialias (omp_get_team_num)
+--- libgomp/config/nvptx/team.c.jj 2018-04-25 09:40:31.890655570 +0200
++++ libgomp/config/nvptx/team.c 2019-05-07 18:46:36.459110805 +0200
+@@ -116,7 +116,8 @@ gomp_thread_start (struct gomp_thread_po
+
+ void
+ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
+- unsigned flags, struct gomp_team *team)
++ unsigned flags, struct gomp_team *team,
++ struct gomp_taskgroup *taskgroup)
+ {
+ struct gomp_thread *thr, *nthr;
+ struct gomp_task *task;
+@@ -147,6 +148,7 @@ gomp_team_start (void (*fn) (void *), vo
+ nthreads_var = icv->nthreads_var;
+ gomp_init_task (thr->task, task, icv);
+ team->implicit_task[0].icv.nthreads_var = nthreads_var;
++ team->implicit_task[0].taskgroup = taskgroup;
+
+ if (nthreads == 1)
+ return;
+@@ -166,6 +168,7 @@ gomp_team_start (void (*fn) (void *), vo
+ nthr->task = &team->implicit_task[i];
+ gomp_init_task (nthr->task, task, icv);
+ team->implicit_task[i].icv.nthreads_var = nthreads_var;
++ team->implicit_task[i].taskgroup = taskgroup;
+ nthr->fn = fn;
+ nthr->data = data;
+ team->ordered_release[i] = &nthr->release;
+@@ -174,5 +177,11 @@ gomp_team_start (void (*fn) (void *), vo
+ gomp_simple_barrier_wait (&pool->threads_dock);
+ }
+
++int
++gomp_pause_host (void)
++{
++ return -1;
++}
++
+ #include "../../team.c"
+ #endif
+--- libgomp/config/nvptx/oacc-parallel.c.jj 2018-04-25 09:40:31.887655569 +0200
++++ libgomp/config/nvptx/oacc-parallel.c 2019-05-07 18:46:36.453110901 +0200
+@@ -1,358 +0,0 @@
+-/* OpenACC constructs
+-
+- Copyright (C) 2014-2018 Free Software Foundation, Inc.
+-
+- Contributed by Mentor Embedded.
+-
+- This file is part of the GNU Offloading and Multi Processing Library
+- (libgomp).
+-
+- Libgomp is free software; you can redistribute it and/or modify it
+- under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 3, or (at your option)
+- any later version.
+-
+- Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+- FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- more details.
+-
+- Under Section 7 of GPL version 3, you are granted additional
+- permissions described in the GCC Runtime Library Exception, version
+- 3.1, as published by the Free Software Foundation.
+-
+- You should have received a copy of the GNU General Public License and
+- a copy of the GCC Runtime Library Exception along with this program;
+- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+- . */
+-
+-#include "libgomp_g.h"
+-
+-__asm__ (".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1);\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1);\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1);\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1);\n"
+- "// BEGIN GLOBAL FUNCTION DECL: GOACC_get_num_threads\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_get_num_threads;\n"
+- "// BEGIN GLOBAL FUNCTION DECL: GOACC_get_thread_num\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_get_thread_num;\n"
+- "// BEGIN GLOBAL FUNCTION DECL: abort\n"
+- ".extern .func abort;\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1)\n"
+- "{\n"
+- ".reg .u32 %ar1;\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- ".reg .pred %r30;\n"
+- ".reg .u32 %r31;\n"
+- ".reg .pred %r32;\n"
+- ".reg .u32 %r33;\n"
+- ".reg .pred %r34;\n"
+- ".local .align 8 .b8 %frame[4];\n"
+- "ld.param.u32 %ar1,[%in_ar1];\n"
+- "mov.u32 %r27,%ar1;\n"
+- "st.local.u32 [%frame],%r27;\n"
+- "ld.local.u32 %r28,[%frame];\n"
+- "mov.u32 %r29,1;\n"
+- "setp.eq.u32 %r30,%r28,%r29;\n"
+- "@%r30 bra $L4;\n"
+- "mov.u32 %r31,2;\n"
+- "setp.eq.u32 %r32,%r28,%r31;\n"
+- "@%r32 bra $L5;\n"
+- "mov.u32 %r33,0;\n"
+- "setp.eq.u32 %r34,%r28,%r33;\n"
+- "@!%r34 bra $L8;\n"
+- "mov.u32 %r23,%tid.x;\n"
+- "mov.u32 %r22,%r23;\n"
+- "bra $L7;\n"
+- "$L4:\n"
+- "mov.u32 %r24,%tid.y;\n"
+- "mov.u32 %r22,%r24;\n"
+- "bra $L7;\n"
+- "$L5:\n"
+- "mov.u32 %r25,%tid.z;\n"
+- "mov.u32 %r22,%r25;\n"
+- "bra $L7;\n"
+- "$L8:\n"
+- "{\n"
+- "{\n"
+- "call abort;\n"
+- "}\n"
+- "}\n"
+- "$L7:\n"
+- "mov.u32 %r26,%r22;\n"
+- "mov.u32 %retval,%r26;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1)\n"
+- "{\n"
+- ".reg .u32 %ar1;\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- ".reg .pred %r30;\n"
+- ".reg .u32 %r31;\n"
+- ".reg .pred %r32;\n"
+- ".reg .u32 %r33;\n"
+- ".reg .pred %r34;\n"
+- ".local .align 8 .b8 %frame[4];\n"
+- "ld.param.u32 %ar1,[%in_ar1];\n"
+- "mov.u32 %r27,%ar1;\n"
+- "st.local.u32 [%frame],%r27;\n"
+- "ld.local.u32 %r28,[%frame];\n"
+- "mov.u32 %r29,1;\n"
+- "setp.eq.u32 %r30,%r28,%r29;\n"
+- "@%r30 bra $L11;\n"
+- "mov.u32 %r31,2;\n"
+- "setp.eq.u32 %r32,%r28,%r31;\n"
+- "@%r32 bra $L12;\n"
+- "mov.u32 %r33,0;\n"
+- "setp.eq.u32 %r34,%r28,%r33;\n"
+- "@!%r34 bra $L15;\n"
+- "mov.u32 %r23,%ntid.x;\n"
+- "mov.u32 %r22,%r23;\n"
+- "bra $L14;\n"
+- "$L11:\n"
+- "mov.u32 %r24,%ntid.y;\n"
+- "mov.u32 %r22,%r24;\n"
+- "bra $L14;\n"
+- "$L12:\n"
+- "mov.u32 %r25,%ntid.z;\n"
+- "mov.u32 %r22,%r25;\n"
+- "bra $L14;\n"
+- "$L15:\n"
+- "{\n"
+- "{\n"
+- "call abort;\n"
+- "}\n"
+- "}\n"
+- "$L14:\n"
+- "mov.u32 %r26,%r22;\n"
+- "mov.u32 %retval,%r26;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1)\n"
+- "{\n"
+- ".reg .u32 %ar1;\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- ".reg .pred %r30;\n"
+- ".reg .u32 %r31;\n"
+- ".reg .pred %r32;\n"
+- ".reg .u32 %r33;\n"
+- ".reg .pred %r34;\n"
+- ".local .align 8 .b8 %frame[4];\n"
+- "ld.param.u32 %ar1,[%in_ar1];\n"
+- "mov.u32 %r27,%ar1;\n"
+- "st.local.u32 [%frame],%r27;\n"
+- "ld.local.u32 %r28,[%frame];\n"
+- "mov.u32 %r29,1;\n"
+- "setp.eq.u32 %r30,%r28,%r29;\n"
+- "@%r30 bra $L18;\n"
+- "mov.u32 %r31,2;\n"
+- "setp.eq.u32 %r32,%r28,%r31;\n"
+- "@%r32 bra $L19;\n"
+- "mov.u32 %r33,0;\n"
+- "setp.eq.u32 %r34,%r28,%r33;\n"
+- "@!%r34 bra $L22;\n"
+- "mov.u32 %r23,%ctaid.x;\n"
+- "mov.u32 %r22,%r23;\n"
+- "bra $L21;\n"
+- "$L18:\n"
+- "mov.u32 %r24,%ctaid.y;\n"
+- "mov.u32 %r22,%r24;\n"
+- "bra $L21;\n"
+- "$L19:\n"
+- "mov.u32 %r25,%ctaid.z;\n"
+- "mov.u32 %r22,%r25;\n"
+- "bra $L21;\n"
+- "$L22:\n"
+- "{\n"
+- "{\n"
+- "call abort;\n"
+- "}\n"
+- "}\n"
+- "$L21:\n"
+- "mov.u32 %r26,%r22;\n"
+- "mov.u32 %retval,%r26;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1)\n"
+- "{\n"
+- ".reg .u32 %ar1;\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- ".reg .pred %r30;\n"
+- ".reg .u32 %r31;\n"
+- ".reg .pred %r32;\n"
+- ".reg .u32 %r33;\n"
+- ".reg .pred %r34;\n"
+- ".local .align 8 .b8 %frame[4];\n"
+- "ld.param.u32 %ar1,[%in_ar1];\n"
+- "mov.u32 %r27,%ar1;\n"
+- "st.local.u32 [%frame],%r27;\n"
+- "ld.local.u32 %r28,[%frame];\n"
+- "mov.u32 %r29,1;\n"
+- "setp.eq.u32 %r30,%r28,%r29;\n"
+- "@%r30 bra $L25;\n"
+- "mov.u32 %r31,2;\n"
+- "setp.eq.u32 %r32,%r28,%r31;\n"
+- "@%r32 bra $L26;\n"
+- "mov.u32 %r33,0;\n"
+- "setp.eq.u32 %r34,%r28,%r33;\n"
+- "@!%r34 bra $L29;\n"
+- "mov.u32 %r23,%nctaid.x;\n"
+- "mov.u32 %r22,%r23;\n"
+- "bra $L28;\n"
+- "$L25:\n"
+- "mov.u32 %r24,%nctaid.y;\n"
+- "mov.u32 %r22,%r24;\n"
+- "bra $L28;\n"
+- "$L26:\n"
+- "mov.u32 %r25,%nctaid.z;\n"
+- "mov.u32 %r22,%r25;\n"
+- "bra $L28;\n"
+- "$L29:\n"
+- "{\n"
+- "{\n"
+- "call abort;\n"
+- "}\n"
+- "}\n"
+- "$L28:\n"
+- "mov.u32 %r26,%r22;\n"
+- "mov.u32 %retval,%r26;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n"
+- "// BEGIN GLOBAL FUNCTION DEF: GOACC_get_num_threads\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_get_num_threads\n"
+- "{\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- "mov.u32 %r26,0;\n"
+- "{\n"
+- ".param .u32 %retval_in;\n"
+- "{\n"
+- ".param .u32 %out_arg0;\n"
+- "st.param.u32 [%out_arg0],%r26;\n"
+- "call (%retval_in),GOACC_ntid,(%out_arg0);\n"
+- "}\n"
+- "ld.param.u32 %r27,[%retval_in];\n"
+- "}\n"
+- "mov.u32 %r22,%r27;\n"
+- "mov.u32 %r28,0;\n"
+- "{\n"
+- ".param .u32 %retval_in;\n"
+- "{\n"
+- ".param .u32 %out_arg0;\n"
+- "st.param.u32 [%out_arg0],%r28;\n"
+- "call (%retval_in),GOACC_nctaid,(%out_arg0);\n"
+- "}\n"
+- "ld.param.u32 %r29,[%retval_in];\n"
+- "}\n"
+- "mov.u32 %r23,%r29;\n"
+- "mul.lo.u32 %r24,%r22,%r23;\n"
+- "mov.u32 %r25,%r24;\n"
+- "mov.u32 %retval,%r25;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n"
+- "// BEGIN GLOBAL FUNCTION DEF: GOACC_get_thread_num\n"
+- ".visible .func (.param .u32 %out_retval) GOACC_get_thread_num\n"
+- "{\n"
+- ".reg .u32 %retval;\n"
+- ".reg .u64 %hr10;\n"
+- ".reg .u32 %r22;\n"
+- ".reg .u32 %r23;\n"
+- ".reg .u32 %r24;\n"
+- ".reg .u32 %r25;\n"
+- ".reg .u32 %r26;\n"
+- ".reg .u32 %r27;\n"
+- ".reg .u32 %r28;\n"
+- ".reg .u32 %r29;\n"
+- ".reg .u32 %r30;\n"
+- ".reg .u32 %r31;\n"
+- ".reg .u32 %r32;\n"
+- ".reg .u32 %r33;\n"
+- "mov.u32 %r28,0;\n"
+- "{\n"
+- ".param .u32 %retval_in;\n"
+- "{\n"
+- ".param .u32 %out_arg0;\n"
+- "st.param.u32 [%out_arg0],%r28;\n"
+- "call (%retval_in),GOACC_ntid,(%out_arg0);\n"
+- "}\n"
+- "ld.param.u32 %r29,[%retval_in];\n"
+- "}\n"
+- "mov.u32 %r22,%r29;\n"
+- "mov.u32 %r30,0;\n"
+- "{\n"
+- ".param .u32 %retval_in;\n"
+- "{\n"
+- ".param .u32 %out_arg0;\n"
+- "st.param.u32 [%out_arg0],%r30;\n"
+- "call (%retval_in),GOACC_ctaid,(%out_arg0);\n"
+- "}\n"
+- "ld.param.u32 %r31,[%retval_in];\n"
+- "}\n"
+- "mov.u32 %r23,%r31;\n"
+- "mul.lo.u32 %r24,%r22,%r23;\n"
+- "mov.u32 %r32,0;\n"
+- "{\n"
+- ".param .u32 %retval_in;\n"
+- "{\n"
+- ".param .u32 %out_arg0;\n"
+- "st.param.u32 [%out_arg0],%r32;\n"
+- "call (%retval_in),GOACC_tid,(%out_arg0);\n"
+- "}\n"
+- "ld.param.u32 %r33,[%retval_in];\n"
+- "}\n"
+- "mov.u32 %r25,%r33;\n"
+- "add.u32 %r26,%r24,%r25;\n"
+- "mov.u32 %r27,%r26;\n"
+- "mov.u32 %retval,%r27;\n"
+- "st.param.u32 [%out_retval],%retval;\n"
+- "ret;\n"
+- "}\n");
+--- libgomp/config/nvptx/target.c.jj 2018-04-25 09:40:31.890655570 +0200
++++ libgomp/config/nvptx/target.c 2019-05-07 18:46:36.453110901 +0200
+@@ -47,3 +47,21 @@ GOMP_teams (unsigned int num_teams, unsi
+ }
+ gomp_num_teams_var = num_teams - 1;
+ }
++
++int
++omp_pause_resource (omp_pause_resource_t kind, int device_num)
++{
++ (void) kind;
++ (void) device_num;
++ return -1;
++}
++
++int
++omp_pause_resource_all (omp_pause_resource_t kind)
++{
++ (void) kind;
++ return -1;
++}
++
++ialias (omp_pause_resource)
++ialias (omp_pause_resource_all)
+--- libgomp/config/nvptx/icv-device.c.jj 2018-04-25 09:40:31.889655570 +0200
++++ libgomp/config/nvptx/icv-device.c 2019-05-07 18:46:36.453110901 +0200
+@@ -46,20 +46,6 @@ omp_get_num_devices (void)
+ }
+
+ int
+-omp_get_num_teams (void)
+-{
+- return gomp_num_teams_var + 1;
+-}
+-
+-int
+-omp_get_team_num (void)
+-{
+- int ctaid;
+- asm ("mov.u32 %0, %%ctaid.x;" : "=r" (ctaid));
+- return ctaid;
+-}
+-
+-int
+ omp_is_initial_device (void)
+ {
+ /* NVPTX is an accelerator-only target. */
+@@ -69,6 +55,4 @@ omp_is_initial_device (void)
+ ialias (omp_set_default_device)
+ ialias (omp_get_default_device)
+ ialias (omp_get_num_devices)
+-ialias (omp_get_num_teams)
+-ialias (omp_get_team_num)
+ ialias (omp_is_initial_device)
+--- libgomp/config/nvptx/affinity-fmt.c.jj 2019-05-07 18:46:36.358112419 +0200
++++ libgomp/config/nvptx/affinity-fmt.c 2019-05-07 18:46:36.358112419 +0200
+@@ -0,0 +1,51 @@
++/* Copyright (C) 2018-2019 Free Software Foundation, Inc.
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++#include "libgomp.h"
++#include
++#include
++#include
++#ifdef HAVE_UNISTD_H
++#include
++#endif
++#ifdef HAVE_INTTYPES_H
++# include /* For PRIx64. */
++#endif
++#ifdef HAVE_UNAME
++#include
++#endif
++
++/* The HAVE_GETPID and HAVE_GETHOSTNAME configure tests are passing for nvptx,
++ while the nvptx newlib implementation does not support those functions.
++ Override the configure test results here. */
++#undef HAVE_GETPID
++#undef HAVE_GETHOSTNAME
++
++/* The nvptx newlib implementation does not support fwrite, but it does support
++ write. Map fwrite to write. */
++#undef fwrite
++#define fwrite(ptr, size, nmemb, stream) write (1, (ptr), (nmemb) * (size))
++
++#include "../../affinity-fmt.c"
++
+--- libgomp/config/mingw32/affinity-fmt.c.jj 2019-05-07 18:46:36.344112642 +0200
++++ libgomp/config/mingw32/affinity-fmt.c 2019-05-07 18:46:36.344112642 +0200
+@@ -0,0 +1,68 @@
++/* Copyright (C) 2018-2019 Free Software Foundation, Inc.
++ Contributed by Jakub Jelinek .
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++#include "libgomp.h"
++#include
++#include
++#include
++#ifdef HAVE_UNISTD_H
++#include
++#endif
++#ifdef HAVE_INTTYPES_H
++# include /* For PRIx64. */
++#endif
++#define WIN32_LEAN_AND_MEAN
++#include
++#include
++
++static int
++gomp_gethostname (char *name, size_t len)
++{
++ /* On Win9x GetComputerName fails if the input size is less
++ than MAX_COMPUTERNAME_LENGTH + 1. */
++ char buffer[MAX_COMPUTERNAME_LENGTH + 1];
++ DWORD size = sizeof (buffer);
++ int ret = 0;
++
++ if (!GetComputerName (buffer, &size))
++ return -1;
++
++ if ((size = strlen (buffer) + 1) > len)
++ {
++ errno = EINVAL;
++ /* Truncate as per POSIX spec. We do not NUL-terminate. */
++ size = len;
++ ret = -1;
++ }
++ memcpy (name, buffer, (size_t) size);
++
++ return ret;
++}
++
++#undef gethostname
++#define gethostname gomp_gethostname
++#define HAVE_GETHOSTNAME 1
++
++#include "../../affinity-fmt.c"
+--- libgomp/config/rtems/bar.c.jj 2018-04-25 09:40:31.902655576 +0200
++++ libgomp/config/rtems/bar.c 2019-05-07 18:46:36.460110789 +0200
+@@ -72,184 +72,5 @@ do_wait (int *addr, int val)
+ futex_wait (addr, val);
+ }
+
+-/* Everything below this point should be identical to the Linux
+- implementation. */
+-
+-void
+-gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+-{
+- if (__builtin_expect (state & BAR_WAS_LAST, 0))
+- {
+- /* Next time we'll be awaiting TOTAL threads again. */
+- bar->awaited = bar->total;
+- __atomic_store_n (&bar->generation, bar->generation + BAR_INCR,
+- MEMMODEL_RELEASE);
+- futex_wake ((int *) &bar->generation, INT_MAX);
+- }
+- else
+- {
+- do
+- do_wait ((int *) &bar->generation, state);
+- while (__atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) == state);
+- }
+-}
+-
+-void
+-gomp_barrier_wait (gomp_barrier_t *bar)
+-{
+- gomp_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+-}
+-
+-/* Like gomp_barrier_wait, except that if the encountering thread
+- is not the last one to hit the barrier, it returns immediately.
+- The intended usage is that a thread which intends to gomp_barrier_destroy
+- this barrier calls gomp_barrier_wait, while all other threads
+- call gomp_barrier_wait_last. When gomp_barrier_wait returns,
+- the barrier can be safely destroyed. */
+-
+-void
+-gomp_barrier_wait_last (gomp_barrier_t *bar)
+-{
+- gomp_barrier_state_t state = gomp_barrier_wait_start (bar);
+- if (state & BAR_WAS_LAST)
+- gomp_barrier_wait_end (bar, state);
+-}
+-
+-void
+-gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
+-{
+- futex_wake ((int *) &bar->generation, count == 0 ? INT_MAX : count);
+-}
+-
+-void
+-gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+-{
+- unsigned int generation, gen;
+-
+- if (__builtin_expect (state & BAR_WAS_LAST, 0))
+- {
+- /* Next time we'll be awaiting TOTAL threads again. */
+- struct gomp_thread *thr = gomp_thread ();
+- struct gomp_team *team = thr->ts.team;
+-
+- bar->awaited = bar->total;
+- team->work_share_cancelled = 0;
+- if (__builtin_expect (team->task_count, 0))
+- {
+- gomp_barrier_handle_tasks (state);
+- state &= ~BAR_WAS_LAST;
+- }
+- else
+- {
+- state &= ~BAR_CANCELLED;
+- state += BAR_INCR - BAR_WAS_LAST;
+- __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
+- futex_wake ((int *) &bar->generation, INT_MAX);
+- return;
+- }
+- }
+-
+- generation = state;
+- state &= ~BAR_CANCELLED;
+- do
+- {
+- do_wait ((int *) &bar->generation, generation);
+- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+- if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
+- {
+- gomp_barrier_handle_tasks (state);
+- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+- }
+- generation |= gen & BAR_WAITING_FOR_TASK;
+- }
+- while (gen != state + BAR_INCR);
+-}
+-
+-void
+-gomp_team_barrier_wait (gomp_barrier_t *bar)
+-{
+- gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+-}
+-
+-void
+-gomp_team_barrier_wait_final (gomp_barrier_t *bar)
+-{
+- gomp_barrier_state_t state = gomp_barrier_wait_final_start (bar);
+- if (__builtin_expect (state & BAR_WAS_LAST, 0))
+- bar->awaited_final = bar->total;
+- gomp_team_barrier_wait_end (bar, state);
+-}
+-
+-bool
+-gomp_team_barrier_wait_cancel_end (gomp_barrier_t *bar,
+- gomp_barrier_state_t state)
+-{
+- unsigned int generation, gen;
+-
+- if (__builtin_expect (state & BAR_WAS_LAST, 0))
+- {
+- /* Next time we'll be awaiting TOTAL threads again. */
+- /* BAR_CANCELLED should never be set in state here, because
+- cancellation means that at least one of the threads has been
+- cancelled, thus on a cancellable barrier we should never see
+- all threads to arrive. */
+- struct gomp_thread *thr = gomp_thread ();
+- struct gomp_team *team = thr->ts.team;
+-
+- bar->awaited = bar->total;
+- team->work_share_cancelled = 0;
+- if (__builtin_expect (team->task_count, 0))
+- {
+- gomp_barrier_handle_tasks (state);
+- state &= ~BAR_WAS_LAST;
+- }
+- else
+- {
+- state += BAR_INCR - BAR_WAS_LAST;
+- __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
+- futex_wake ((int *) &bar->generation, INT_MAX);
+- return false;
+- }
+- }
+-
+- if (__builtin_expect (state & BAR_CANCELLED, 0))
+- return true;
+-
+- generation = state;
+- do
+- {
+- do_wait ((int *) &bar->generation, generation);
+- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+- if (__builtin_expect (gen & BAR_CANCELLED, 0))
+- return true;
+- if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
+- {
+- gomp_barrier_handle_tasks (state);
+- gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+- }
+- generation |= gen & BAR_WAITING_FOR_TASK;
+- }
+- while (gen != state + BAR_INCR);
+-
+- return false;
+-}
+-
+-bool
+-gomp_team_barrier_wait_cancel (gomp_barrier_t *bar)
+-{
+- return gomp_team_barrier_wait_cancel_end (bar, gomp_barrier_wait_start (bar));
+-}
+-
+-void
+-gomp_team_barrier_cancel (struct gomp_team *team)
+-{
+- gomp_mutex_lock (&team->task_lock);
+- if (team->barrier.generation & BAR_CANCELLED)
+- {
+- gomp_mutex_unlock (&team->task_lock);
+- return;
+- }
+- team->barrier.generation |= BAR_CANCELLED;
+- gomp_mutex_unlock (&team->task_lock);
+- futex_wake ((int *) &team->barrier.generation, INT_MAX);
+-}
++#define GOMP_WAIT_H 1
++#include "../linux/bar.c"
+--- libgomp/config/rtems/affinity-fmt.c.jj 2019-05-07 18:46:36.459110805 +0200
++++ libgomp/config/rtems/affinity-fmt.c 2019-05-07 18:46:36.459110805 +0200
+@@ -0,0 +1,49 @@
++/* Copyright (C) 2018-2019 Free Software Foundation, Inc.
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++#include "libgomp.h"
++#include
++#include
++#include
++#ifdef HAVE_UNISTD_H
++#include
++#endif
++#ifdef HAVE_INTTYPES_H
++# include /* For PRIx64. */
++#endif
++#ifdef HAVE_UNAME
++#include
++#endif
++
++/* The HAVE_GETPID and HAVE_GETHOSTNAME configure tests are passing for RTEMS,
++ but the extra information they give are of little value for the user.
++ Override the configure test results here. */
++#undef HAVE_GETPID
++#undef HAVE_GETHOSTNAME
++
++/* Avoid the complex fwrite() in favour of the simple write(). */
++#undef fwrite
++#define fwrite(ptr, size, nmemb, stream) write (1, (ptr), (nmemb) * (size))
++
++#include "../../affinity-fmt.c"
+--- libgomp/config.h.in.jj 2018-04-25 09:40:31.870655561 +0200
++++ libgomp/config.h.in 2019-05-07 18:46:36.465110710 +0200
+@@ -1,5 +1,8 @@
+ /* config.h.in. Generated from configure.ac by autoheader. */
+
++/* Define to 1 if you have the `aligned_alloc' function. */
++#undef HAVE_ALIGNED_ALLOC
++
+ /* Define to 1 if the target assembler supports .symver directive. */
+ #undef HAVE_AS_SYMVER_DIRECTIVE
+
+@@ -33,9 +36,15 @@
+ /* Define to 1 if you have the `getgid' function. */
+ #undef HAVE_GETGID
+
++/* Define if gethostname is supported. */
++#undef HAVE_GETHOSTNAME
++
+ /* Define to 1 if you have the `getloadavg' function. */
+ #undef HAVE_GETLOADAVG
+
++/* Define if getpid is supported. */
++#undef HAVE_GETPID
++
+ /* Define to 1 if you have the `getuid' function. */
+ #undef HAVE_GETUID
+
+@@ -45,9 +54,15 @@
+ /* Define to 1 if you have the `dl' library (-ldl). */
+ #undef HAVE_LIBDL
+
++/* Define to 1 if you have the `memalign' function. */
++#undef HAVE_MEMALIGN
++
+ /* Define to 1 if you have the header file. */
+ #undef HAVE_MEMORY_H
+
++/* Define to 1 if you have the `posix_memalign' function. */
++#undef HAVE_POSIX_MEMALIGN
++
+ /* Define if pthread_{,attr_}{g,s}etaffinity_np is supported. */
+ #undef HAVE_PTHREAD_AFFINITY_NP
+
+@@ -103,9 +118,15 @@
+ /* Define to 1 if the target supports thread-local storage. */
+ #undef HAVE_TLS
+
++/* Define if uname is supported and struct utsname has nodename field. */
++#undef HAVE_UNAME
++
+ /* Define to 1 if you have the header file. */
+ #undef HAVE_UNISTD_H
+
++/* Define to 1 if you have the `_aligned_malloc' function. */
++#undef HAVE__ALIGNED_MALLOC
++
+ /* Define to 1 if you have the `__secure_getenv' function. */
+ #undef HAVE___SECURE_GETENV
+
+@@ -125,8 +146,8 @@
+ */
+ #undef LT_OBJDIR
+
+-/* Define to offload targets, separated by commas. */
+-#undef OFFLOAD_TARGETS
++/* Define to offload plugins, separated by commas. */
++#undef OFFLOAD_PLUGINS
+
+ /* Name of package */
+ #undef PACKAGE
+--- libgomp/teams.c.jj 2019-05-07 18:46:36.548109384 +0200
++++ libgomp/teams.c 2019-05-07 18:46:36.548109384 +0200
+@@ -0,0 +1,74 @@
++/* Copyright (C) 2018-2019 Free Software Foundation, Inc.
++ Contributed by Jakub Jelinek .
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++/* This file handles the host TEAMS construct. */
++
++#include "libgomp.h"
++#include
++
++static unsigned gomp_num_teams = 1, gomp_team_num = 0;
++
++void
++GOMP_teams_reg (void (*fn) (void *), void *data, unsigned int num_teams,
++ unsigned int thread_limit, unsigned int flags)
++{
++ (void) flags;
++ (void) num_teams;
++ unsigned old_thread_limit_var = 0;
++ if (thread_limit)
++ {
++ struct gomp_task_icv *icv = gomp_icv (true);
++ old_thread_limit_var = icv->thread_limit_var;
++ icv->thread_limit_var
++ = thread_limit > INT_MAX ? UINT_MAX : thread_limit;
++ }
++ if (num_teams == 0)
++ num_teams = 3;
++ gomp_num_teams = num_teams;
++ for (gomp_team_num = 0; gomp_team_num < num_teams; gomp_team_num++)
++ fn (data);
++ gomp_num_teams = 1;
++ gomp_team_num = 0;
++ if (thread_limit)
++ {
++ struct gomp_task_icv *icv = gomp_icv (true);
++ icv->thread_limit_var = old_thread_limit_var;
++ }
++}
++
++int
++omp_get_num_teams (void)
++{
++ return gomp_num_teams;
++}
++
++int
++omp_get_team_num (void)
++{
++ return gomp_team_num;
++}
++
++ialias (omp_get_num_teams)
++ialias (omp_get_team_num)
+--- libgomp/libgomp.map.jj 2018-04-25 09:40:31.321655307 +0200
++++ libgomp/libgomp.map 2019-05-07 18:46:36.525109751 +0200
+@@ -164,6 +164,22 @@ OMP_4.5 {
+ omp_target_disassociate_ptr;
+ } OMP_4.0;
+
++OMP_5.0 {
++ global:
++ omp_capture_affinity;
++ omp_capture_affinity_;
++ omp_display_affinity;
++ omp_display_affinity_;
++ omp_get_affinity_format;
++ omp_get_affinity_format_;
++ omp_set_affinity_format;
++ omp_set_affinity_format_;
++ omp_pause_resource;
++ omp_pause_resource_;
++ omp_pause_resource_all;
++ omp_pause_resource_all_;
++} OMP_4.5;
++
+ GOMP_1.0 {
+ global:
+ GOMP_atomic_end;
+@@ -298,6 +314,34 @@ GOMP_4.5 {
+ GOMP_parallel_loop_nonmonotonic_guided;
+ } GOMP_4.0.1;
+
++GOMP_5.0 {
++ global:
++ GOMP_loop_doacross_start;
++ GOMP_loop_maybe_nonmonotonic_runtime_next;
++ GOMP_loop_maybe_nonmonotonic_runtime_start;
++ GOMP_loop_nonmonotonic_runtime_next;
++ GOMP_loop_nonmonotonic_runtime_start;
++ GOMP_loop_ordered_start;
++ GOMP_loop_start;
++ GOMP_loop_ull_doacross_start;
++ GOMP_loop_ull_maybe_nonmonotonic_runtime_next;
++ GOMP_loop_ull_maybe_nonmonotonic_runtime_start;
++ GOMP_loop_ull_nonmonotonic_runtime_next;
++ GOMP_loop_ull_nonmonotonic_runtime_start;
++ GOMP_loop_ull_ordered_start;
++ GOMP_loop_ull_start;
++ GOMP_parallel_loop_maybe_nonmonotonic_runtime;
++ GOMP_parallel_loop_nonmonotonic_runtime;
++ GOMP_parallel_reductions;
++ GOMP_sections2_start;
++ GOMP_taskgroup_reduction_register;
++ GOMP_taskgroup_reduction_unregister;
++ GOMP_task_reduction_remap;
++ GOMP_taskwait_depend;
++ GOMP_teams_reg;
++ GOMP_workshare_task_reduction_unregister;
++} GOMP_4.5;
++
+ OACC_2.0 {
+ global:
+ acc_get_num_devices;
+@@ -386,6 +430,52 @@ OACC_2.0.1 {
+ acc_pcreate;
+ } OACC_2.0;
+
++OACC_2.5 {
++ global:
++ acc_copyin_async;
++ acc_copyin_async_32_h_;
++ acc_copyin_async_64_h_;
++ acc_copyin_async_array_h_;
++ acc_copyout_async;
++ acc_copyout_async_32_h_;
++ acc_copyout_async_64_h_;
++ acc_copyout_async_array_h_;
++ acc_copyout_finalize;
++ acc_copyout_finalize_32_h_;
++ acc_copyout_finalize_64_h_;
++ acc_copyout_finalize_array_h_;
++ acc_copyout_finalize_async;
++ acc_copyout_finalize_async_32_h_;
++ acc_copyout_finalize_async_64_h_;
++ acc_copyout_finalize_async_array_h_;
++ acc_create_async;
++ acc_create_async_32_h_;
++ acc_create_async_64_h_;
++ acc_create_async_array_h_;
++ acc_delete_async;
++ acc_delete_async_32_h_;
++ acc_delete_async_64_h_;
++ acc_delete_async_array_h_;
++ acc_delete_finalize;
++ acc_delete_finalize_32_h_;
++ acc_delete_finalize_64_h_;
++ acc_delete_finalize_array_h_;
++ acc_delete_finalize_async;
++ acc_delete_finalize_async_32_h_;
++ acc_delete_finalize_async_64_h_;
++ acc_delete_finalize_async_array_h_;
++ acc_memcpy_from_device_async;
++ acc_memcpy_to_device_async;
++ acc_update_device_async;
++ acc_update_device_async_32_h_;
++ acc_update_device_async_64_h_;
++ acc_update_device_async_array_h_;
++ acc_update_self_async;
++ acc_update_self_async_32_h_;
++ acc_update_self_async_64_h_;
++ acc_update_self_async_array_h_;
++} OACC_2.0.1;
++
+ GOACC_2.0 {
+ global:
+ GOACC_data_end;
+@@ -420,3 +510,8 @@ GOMP_PLUGIN_1.1 {
+ global:
+ GOMP_PLUGIN_target_task_completion;
+ } GOMP_PLUGIN_1.0;
++
++GOMP_PLUGIN_1.2 {
++ global:
++ GOMP_PLUGIN_acc_default_dim;
++} GOMP_PLUGIN_1.1;
+--- libgomp/oacc-async.c.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/oacc-async.c 2019-05-07 18:46:36.528109704 +0200
+@@ -34,7 +34,7 @@
+ int
+ acc_async_test (int async)
+ {
+- if (async < acc_async_sync)
++ if (!async_valid_p (async))
+ gomp_fatal ("invalid async argument: %d", async);
+
+ struct goacc_thread *thr = goacc_thread ();
+@@ -59,7 +59,7 @@ acc_async_test_all (void)
+ void
+ acc_wait (int async)
+ {
+- if (async < acc_async_sync)
++ if (!async_valid_p (async))
+ gomp_fatal ("invalid async argument: %d", async);
+
+ struct goacc_thread *thr = goacc_thread ();
+@@ -117,7 +117,7 @@ acc_async_wait_all (void)
+ void
+ acc_wait_all_async (int async)
+ {
+- if (async < acc_async_sync)
++ if (!async_valid_p (async))
+ gomp_fatal ("invalid async argument: %d", async);
+
+ struct goacc_thread *thr = goacc_thread ();
+--- libgomp/loop_ull.c.jj 2018-04-25 09:40:31.912655580 +0200
++++ libgomp/loop_ull.c 2019-05-07 18:46:36.527109719 +0200
+@@ -27,8 +27,12 @@
+
+ #include
+ #include
++#include
+ #include "libgomp.h"
+
++ialias (GOMP_loop_ull_runtime_next)
++ialias_redirect (GOMP_taskgroup_reduction_register)
++
+ typedef unsigned long long gomp_ull;
+
+ /* Initialize the given work share construct from the given arguments. */
+@@ -104,7 +108,7 @@ gomp_loop_ull_static_start (bool up, gom
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_STATIC, chunk_size);
+@@ -122,7 +126,7 @@ gomp_loop_ull_dynamic_start (bool up, go
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_DYNAMIC, chunk_size);
+@@ -148,7 +152,7 @@ gomp_loop_ull_guided_start (bool up, gom
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_GUIDED, chunk_size);
+@@ -171,7 +175,7 @@ GOMP_loop_ull_runtime_start (bool up, go
+ gomp_ull incr, gomp_ull *istart, gomp_ull *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_ull_static_start (up, start, end, incr,
+@@ -195,6 +199,99 @@ GOMP_loop_ull_runtime_start (bool up, go
+ }
+ }
+
++static long
++gomp_adjust_sched (long sched, gomp_ull *chunk_size)
++{
++ sched &= ~GFS_MONOTONIC;
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_DYNAMIC:
++ case GFS_GUIDED:
++ return sched;
++ /* GFS_RUNTIME is used for runtime schedule without monotonic
++ or nonmonotonic modifiers on the clause.
++ GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic
++ modifier. */
++ case GFS_RUNTIME:
++ /* GFS_AUTO is used for runtime schedule with nonmonotonic
++ modifier. */
++ case GFS_AUTO:
++ {
++ struct gomp_task_icv *icv = gomp_icv (false);
++ sched = icv->run_sched_var & ~GFS_MONOTONIC;
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_DYNAMIC:
++ case GFS_GUIDED:
++ *chunk_size = icv->run_sched_chunk_size;
++ break;
++ case GFS_AUTO:
++ sched = GFS_STATIC;
++ *chunk_size = 0;
++ break;
++ default:
++ abort ();
++ }
++ return sched;
++ }
++ default:
++ abort ();
++ }
++}
++
++bool
++GOMP_loop_ull_start (bool up, gomp_ull start, gomp_ull end,
++ gomp_ull incr, long sched, gomp_ull chunk_size,
++ gomp_ull *istart, gomp_ull *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (gomp_work_share_start (0))
++ {
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
++ sched, chunk_size);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ if (mem)
++ {
++ uintptr_t size = (uintptr_t) *mem;
++ if (size > (sizeof (struct gomp_work_share)
++ - offsetof (struct gomp_work_share,
++ inline_ordered_team_ids)))
++ thr->ts.work_share->ordered_team_ids
++ = gomp_malloc_cleared (size);
++ else
++ memset (thr->ts.work_share->ordered_team_ids, '\0', size);
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ if (mem)
++ *mem = (void *) thr->ts.work_share->ordered_team_ids;
++ }
++
++ return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend);
++}
++
+ /* The *_ordered_*_start routines are similar. The only difference is that
+ this work-share construct is initialized to expect an ORDERED section. */
+
+@@ -206,7 +303,7 @@ gomp_loop_ull_ordered_static_start (bool
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_STATIC, chunk_size);
+@@ -225,7 +322,7 @@ gomp_loop_ull_ordered_dynamic_start (boo
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_DYNAMIC, chunk_size);
+@@ -251,7 +348,7 @@ gomp_loop_ull_ordered_guided_start (bool
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (true))
++ if (gomp_work_share_start (1))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
+ GFS_GUIDED, chunk_size);
+@@ -275,7 +372,7 @@ GOMP_loop_ull_ordered_runtime_start (boo
+ gomp_ull *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_ull_ordered_static_start (up, start, end, incr,
+@@ -299,6 +396,82 @@ GOMP_loop_ull_ordered_runtime_start (boo
+ }
+ }
+
++bool
++GOMP_loop_ull_ordered_start (bool up, gomp_ull start, gomp_ull end,
++ gomp_ull incr, long sched, gomp_ull chunk_size,
++ gomp_ull *istart, gomp_ull *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ size_t ordered = 1;
++ bool ret;
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (mem)
++ ordered += (uintptr_t) *mem;
++ if (gomp_work_share_start (ordered))
++ {
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
++ sched, chunk_size);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ if (sched == GFS_STATIC)
++ gomp_ordered_static_init ();
++ else
++ gomp_mutex_lock (&thr->ts.work_share->lock);
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ sched = thr->ts.work_share->sched;
++ if (sched != GFS_STATIC)
++ gomp_mutex_lock (&thr->ts.work_share->lock);
++ }
++
++ if (mem)
++ {
++ uintptr_t p
++ = (uintptr_t) (thr->ts.work_share->ordered_team_ids
++ + (thr->ts.team ? thr->ts.team->nthreads : 1));
++ p += __alignof__ (long long) - 1;
++ p &= ~(__alignof__ (long long) - 1);
++ *mem = (void *) p;
++ }
++
++ switch (sched)
++ {
++ case GFS_STATIC:
++ case GFS_AUTO:
++ return !gomp_iter_ull_static_next (istart, iend);
++ case GFS_DYNAMIC:
++ ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
++ break;
++ case GFS_GUIDED:
++ ret = gomp_iter_ull_guided_next_locked (istart, iend);
++ break;
++ default:
++ abort ();
++ }
++
++ if (ret)
++ gomp_ordered_first ();
++ gomp_mutex_unlock (&thr->ts.work_share->lock);
++ return ret;
++}
++
+ /* The *_doacross_*_start routines are similar. The only difference is that
+ this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
+ section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
+@@ -313,11 +486,11 @@ gomp_loop_ull_doacross_static_start (uns
+ struct gomp_thread *thr = gomp_thread ();
+
+ thr->ts.static_trip = 0;
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
+ GFS_STATIC, chunk_size);
+- gomp_doacross_ull_init (ncounts, counts, chunk_size);
++ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -332,11 +505,11 @@ gomp_loop_ull_doacross_dynamic_start (un
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
+ GFS_DYNAMIC, chunk_size);
+- gomp_doacross_ull_init (ncounts, counts, chunk_size);
++ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -359,11 +532,11 @@ gomp_loop_ull_doacross_guided_start (uns
+ struct gomp_thread *thr = gomp_thread ();
+ bool ret;
+
+- if (gomp_work_share_start (false))
++ if (gomp_work_share_start (0))
+ {
+ gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
+ GFS_GUIDED, chunk_size);
+- gomp_doacross_ull_init (ncounts, counts, chunk_size);
++ gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
+ gomp_work_share_init_done ();
+ }
+
+@@ -383,7 +556,7 @@ GOMP_loop_ull_doacross_runtime_start (un
+ gomp_ull *istart, gomp_ull *iend)
+ {
+ struct gomp_task_icv *icv = gomp_icv (false);
+- switch (icv->run_sched_var)
++ switch (icv->run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_STATIC:
+ return gomp_loop_ull_doacross_static_start (ncounts, counts,
+@@ -407,6 +580,51 @@ GOMP_loop_ull_doacross_runtime_start (un
+ }
+ }
+
++bool
++GOMP_loop_ull_doacross_start (unsigned ncounts, gomp_ull *counts,
++ long sched, gomp_ull chunk_size,
++ gomp_ull *istart, gomp_ull *iend,
++ uintptr_t *reductions, void **mem)
++{
++ struct gomp_thread *thr = gomp_thread ();
++
++ thr->ts.static_trip = 0;
++ if (reductions)
++ gomp_workshare_taskgroup_start ();
++ if (gomp_work_share_start (0))
++ {
++ size_t extra = 0;
++ if (mem)
++ extra = (uintptr_t) *mem;
++ sched = gomp_adjust_sched (sched, &chunk_size);
++ gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
++ sched, chunk_size);
++ gomp_doacross_ull_init (ncounts, counts, chunk_size, extra);
++ if (reductions)
++ {
++ GOMP_taskgroup_reduction_register (reductions);
++ thr->task->taskgroup->workshare = true;
++ thr->ts.work_share->task_reductions = reductions;
++ }
++ gomp_work_share_init_done ();
++ }
++ else
++ {
++ if (reductions)
++ {
++ uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
++ gomp_workshare_task_reduction_register (reductions,
++ first_reductions);
++ }
++ sched = thr->ts.work_share->sched;
++ }
++
++ if (mem)
++ *mem = thr->ts.work_share->doacross->extra;
++
++ return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend);
++}
++
+ /* The *_next routines are called when the thread completes processing of
+ the iteration block currently assigned to it. If the work-share
+ construct is bound directly to a parallel construct, then the iteration
+@@ -570,6 +788,10 @@ extern __typeof(gomp_loop_ull_dynamic_st
+ __attribute__((alias ("gomp_loop_ull_dynamic_start")));
+ extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_nonmonotonic_guided_start
+ __attribute__((alias ("gomp_loop_ull_guided_start")));
++extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_nonmonotonic_runtime_start
++ __attribute__((alias ("GOMP_loop_ull_runtime_start")));
++extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_maybe_nonmonotonic_runtime_start
++ __attribute__((alias ("GOMP_loop_ull_runtime_start")));
+
+ extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start
+ __attribute__((alias ("gomp_loop_ull_ordered_static_start")));
+@@ -595,6 +817,10 @@ extern __typeof(gomp_loop_ull_dynamic_ne
+ __attribute__((alias ("gomp_loop_ull_dynamic_next")));
+ extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_nonmonotonic_guided_next
+ __attribute__((alias ("gomp_loop_ull_guided_next")));
++extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_nonmonotonic_runtime_next
++ __attribute__((alias ("GOMP_loop_ull_runtime_next")));
++extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_maybe_nonmonotonic_runtime_next
++ __attribute__((alias ("GOMP_loop_ull_runtime_next")));
+
+ extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next
+ __attribute__((alias ("gomp_loop_ull_ordered_static_next")));
+@@ -650,6 +876,23 @@ GOMP_loop_ull_nonmonotonic_guided_start
+ }
+
+ bool
++GOMP_loop_ull_nonmonotonic_runtime_start (bool up, gomp_ull start,
++ gomp_ull end, gomp_ull incr,
++ gomp_ull *istart, gomp_ull *iend)
++{
++ return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend);
++}
++
++bool
++GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool up, gomp_ull start,
++ gomp_ull end, gomp_ull incr,
++ gomp_ull *istart,
++ gomp_ull *iend)
++{
++ return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend);
++}
++
++bool
+ GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
+ gomp_ull incr, gomp_ull chunk_size,
+ gomp_ull *istart, gomp_ull *iend)
+@@ -734,6 +977,19 @@ GOMP_loop_ull_nonmonotonic_guided_next (
+ }
+
+ bool
++GOMP_loop_ull_nonmonotonic_runtime_next (gomp_ull *istart, gomp_ull *iend)
++{
++ return GOMP_loop_ull_runtime_next (istart, iend);
++}
++
++bool
++GOMP_loop_ull_maybe_nonmonotonic_runtime_next (gomp_ull *istart,
++ gomp_ull *iend)
++{
++ return GOMP_loop_ull_runtime_next (istart, iend);
++}
++
++bool
+ GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
+ {
+ return gomp_loop_ull_ordered_static_next (istart, iend);
+--- libgomp/oacc-int.h.jj 2018-04-25 09:40:31.320655306 +0200
++++ libgomp/oacc-int.h 2019-05-07 18:46:36.529109688 +0200
+@@ -99,6 +99,28 @@ void goacc_restore_bind (void);
+ void goacc_lazy_initialize (void);
+ void goacc_host_init (void);
+
++static inline bool
++async_valid_stream_id_p (int async)
++{
++ return async >= 0;
++}
++
++static inline bool
++async_valid_p (int async)
++{
++ return (async == acc_async_noval || async == acc_async_sync
++ || async_valid_stream_id_p (async));
++}
++
++static inline bool
++async_synchronous_p (int async)
++{
++ if (!async_valid_p (async))
++ return true;
++
++ return async == acc_async_sync;
++}
++
+ #ifdef HAVE_ATTRIBUTE_VISIBILITY
+ # pragma GCC visibility pop
+ #endif
+--- libgomp/testsuite/Makefile.in.jj 2018-04-25 09:40:31.452655368 +0200
++++ libgomp/testsuite/Makefile.in 2019-05-07 18:51:35.754330084 +0200
+@@ -223,6 +223,7 @@ mkdir_p = @mkdir_p@
+ multi_basedir = @multi_basedir@
+ offload_additional_lib_paths = @offload_additional_lib_paths@
+ offload_additional_options = @offload_additional_options@
++offload_plugins = @offload_plugins@
+ offload_targets = @offload_targets@
+ oldincludedir = @oldincludedir@
+ pdfdir = @pdfdir@
+--- libgomp/task.c.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/task.c 2019-05-07 18:46:36.547109400 +0200
+@@ -166,21 +166,72 @@ gomp_task_handle_depend (struct gomp_tas
+ void **depend)
+ {
+ size_t ndepend = (uintptr_t) depend[0];
+- size_t nout = (uintptr_t) depend[1];
+ size_t i;
+ hash_entry_type ent;
+
++ if (ndepend)
++ {
++ /* depend[0] is total # */
++ size_t nout = (uintptr_t) depend[1]; /* # of out: and inout: */
++ /* ndepend - nout is # of in: */
++ for (i = 0; i < ndepend; i++)
++ {
++ task->depend[i].addr = depend[2 + i];
++ task->depend[i].is_in = i >= nout;
++ }
++ }
++ else
++ {
++ ndepend = (uintptr_t) depend[1]; /* total # */
++ size_t nout = (uintptr_t) depend[2]; /* # of out: and inout: */
++ size_t nmutexinoutset = (uintptr_t) depend[3]; /* # of mutexinoutset: */
++ /* For now we treat mutexinoutset like out, which is compliant, but
++ inefficient. */
++ size_t nin = (uintptr_t) depend[4]; /* # of in: */
++ /* ndepend - nout - nmutexinoutset - nin is # of depobjs */
++ size_t normal = nout + nmutexinoutset + nin;
++ size_t n = 0;
++ for (i = normal; i < ndepend; i++)
++ {
++ void **d = (void **) (uintptr_t) depend[5 + i];
++ switch ((uintptr_t) d[1])
++ {
++ case GOMP_DEPEND_OUT:
++ case GOMP_DEPEND_INOUT:
++ case GOMP_DEPEND_MUTEXINOUTSET:
++ break;
++ case GOMP_DEPEND_IN:
++ continue;
++ default:
++ gomp_fatal ("unknown omp_depend_t dependence type %d",
++ (int) (uintptr_t) d[1]);
++ }
++ task->depend[n].addr = d[0];
++ task->depend[n++].is_in = 0;
++ }
++ for (i = 0; i < normal; i++)
++ {
++ task->depend[n].addr = depend[5 + i];
++ task->depend[n++].is_in = i >= nout + nmutexinoutset;
++ }
++ for (i = normal; i < ndepend; i++)
++ {
++ void **d = (void **) (uintptr_t) depend[5 + i];
++ if ((uintptr_t) d[1] != GOMP_DEPEND_IN)
++ continue;
++ task->depend[n].addr = d[0];
++ task->depend[n++].is_in = 1;
++ }
++ }
+ task->depend_count = ndepend;
+ task->num_dependees = 0;
+ if (parent->depend_hash == NULL)
+ parent->depend_hash = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12);
+ for (i = 0; i < ndepend; i++)
+ {
+- task->depend[i].addr = depend[2 + i];
+ task->depend[i].next = NULL;
+ task->depend[i].prev = NULL;
+ task->depend[i].task = task;
+- task->depend[i].is_in = i >= nout;
+ task->depend[i].redundant = false;
+ task->depend[i].redundant_out = false;
+
+@@ -205,7 +256,7 @@ gomp_task_handle_depend (struct gomp_tas
+ last = ent;
+
+ /* depend(in:...) doesn't depend on earlier depend(in:...). */
+- if (i >= nout && ent->is_in)
++ if (task->depend[i].is_in && ent->is_in)
+ continue;
+
+ if (!ent->is_in)
+@@ -280,9 +331,18 @@ gomp_task_handle_depend (struct gomp_tas
+ then the task may be executed by any member of the team.
+
+ DEPEND is an array containing:
++ if depend[0] is non-zero, then:
+ depend[0]: number of depend elements.
+- depend[1]: number of depend elements of type "out".
+- depend[2..N+1]: address of [1..N]th depend element. */
++ depend[1]: number of depend elements of type "out/inout".
++ depend[2..N+1]: address of [1..N]th depend element.
++ otherwise, when depend[0] is zero, then:
++ depend[1]: number of depend elements.
++ depend[2]: number of depend elements of type "out/inout".
++ depend[3]: number of depend elements of type "mutexinoutset".
++ depend[4]: number of depend elements of type "in".
++ depend[5..4+depend[2]+depend[3]+depend[4]]: address of depend elements
++ depend[5+depend[2]+depend[3]+depend[4]..4+depend[1]]: address of
++ omp_depend_t objects. */
+
+ void
+ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
+@@ -303,10 +363,20 @@ GOMP_task (void (*fn) (void *), void *da
+ #endif
+
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
+
+ if ((flags & GOMP_TASK_FLAG_PRIORITY) == 0)
+ priority = 0;
+@@ -377,7 +447,7 @@ GOMP_task (void (*fn) (void *), void *da
+ size_t depend_size = 0;
+
+ if (flags & GOMP_TASK_FLAG_DEPEND)
+- depend_size = ((uintptr_t) depend[0]
++ depend_size = ((uintptr_t) (depend[0] ? depend[0] : depend[1])
+ * sizeof (struct gomp_task_depend_entry));
+ task = gomp_malloc (sizeof (*task) + depend_size
+ + arg_size + arg_align - 1);
+@@ -404,14 +474,26 @@ GOMP_task (void (*fn) (void *), void *da
+ gomp_mutex_lock (&team->task_lock);
+ /* If parallel or taskgroup has been cancelled, don't start new
+ tasks. */
+- if (__builtin_expect ((gomp_team_barrier_cancelled (&team->barrier)
+- || (taskgroup && taskgroup->cancelled))
+- && !task->copy_ctors_done, 0))
++ if (__builtin_expect (gomp_cancel_var, 0)
++ && !task->copy_ctors_done)
+ {
+- gomp_mutex_unlock (&team->task_lock);
+- gomp_finish_task (task);
+- free (task);
+- return;
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ {
++ do_cancel:
++ gomp_mutex_unlock (&team->task_lock);
++ gomp_finish_task (task);
++ free (task);
++ return;
++ }
++ if (taskgroup)
++ {
++ if (taskgroup->cancelled)
++ goto do_cancel;
++ if (taskgroup->workshare
++ && taskgroup->prev
++ && taskgroup->prev->cancelled)
++ goto do_cancel;
++ }
+ }
+ if (taskgroup)
+ taskgroup->num_children++;
+@@ -463,6 +545,7 @@ GOMP_task (void (*fn) (void *), void *da
+
+ ialias (GOMP_taskgroup_start)
+ ialias (GOMP_taskgroup_end)
++ialias (GOMP_taskgroup_reduction_register)
+
+ #define TYPE long
+ #define UTYPE unsigned long
+@@ -601,10 +684,20 @@ gomp_create_target_task (struct gomp_dev
+ struct gomp_team *team = thr->ts.team;
+
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
+- return true;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return true;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return true;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return true;
++ }
++ }
+
+ struct gomp_target_task *ttask;
+ struct gomp_task *task;
+@@ -617,7 +710,7 @@ gomp_create_target_task (struct gomp_dev
+
+ if (depend != NULL)
+ {
+- depend_cnt = (uintptr_t) depend[0];
++ depend_cnt = (uintptr_t) (depend[0] ? depend[0] : depend[1]);
+ depend_size = depend_cnt * sizeof (struct gomp_task_depend_entry);
+ }
+ if (fn)
+@@ -687,13 +780,25 @@ gomp_create_target_task (struct gomp_dev
+ task->final_task = 0;
+ gomp_mutex_lock (&team->task_lock);
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+- if (__builtin_expect (gomp_team_barrier_cancelled (&team->barrier)
+- || (taskgroup && taskgroup->cancelled), 0))
++ if (__builtin_expect (gomp_cancel_var, 0))
+ {
+- gomp_mutex_unlock (&team->task_lock);
+- gomp_finish_task (task);
+- free (task);
+- return true;
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ {
++ do_cancel:
++ gomp_mutex_unlock (&team->task_lock);
++ gomp_finish_task (task);
++ free (task);
++ return true;
++ }
++ if (taskgroup)
++ {
++ if (taskgroup->cancelled)
++ goto do_cancel;
++ if (taskgroup->workshare
++ && taskgroup->prev
++ && taskgroup->prev->cancelled)
++ goto do_cancel;
++ }
+ }
+ if (depend_size)
+ {
+@@ -986,10 +1091,21 @@ gomp_task_run_pre (struct gomp_task *chi
+
+ if (--team->task_queued_count == 0)
+ gomp_team_barrier_clear_task_pending (&team->barrier);
+- if ((gomp_team_barrier_cancelled (&team->barrier)
+- || (taskgroup && taskgroup->cancelled))
++ if (__builtin_expect (gomp_cancel_var, 0)
+ && !child_task->copy_ctors_done)
+- return true;
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return true;
++ if (taskgroup)
++ {
++ if (taskgroup->cancelled)
++ return true;
++ if (taskgroup->workshare
++ && taskgroup->prev
++ && taskgroup->prev->cancelled)
++ return true;
++ }
++ }
+ return false;
+ }
+
+@@ -1456,6 +1572,35 @@ GOMP_taskwait (void)
+ }
+ }
+
++/* Called when encountering a taskwait directive with depend clause(s).
++ Wait as if it was an mergeable included task construct with empty body. */
++
++void
++GOMP_taskwait_depend (void **depend)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_team *team = thr->ts.team;
++
++ /* If parallel or taskgroup has been cancelled, return early. */
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
++
++ if (thr->task && thr->task->depend_hash)
++ gomp_task_maybe_wait_for_dependencies (depend);
++}
++
+ /* An undeferred task is about to run. Wait for all tasks that this
+ undeferred task depends on.
+
+@@ -1464,7 +1609,7 @@ GOMP_taskwait (void)
+ the scheduling queues. Then we iterate through these imminently
+ ready tasks (and possibly other high priority tasks), and run them.
+ If we run out of ready dependencies to execute, we either wait for
+- the reamining dependencies to finish, or wait for them to get
++ the remaining dependencies to finish, or wait for them to get
+ scheduled so we can run them.
+
+ DEPEND is as in GOMP_task. */
+@@ -1477,21 +1622,50 @@ gomp_task_maybe_wait_for_dependencies (v
+ struct gomp_team *team = thr->ts.team;
+ struct gomp_task_depend_entry elem, *ent = NULL;
+ struct gomp_taskwait taskwait;
+- size_t ndepend = (uintptr_t) depend[0];
++ size_t orig_ndepend = (uintptr_t) depend[0];
+ size_t nout = (uintptr_t) depend[1];
++ size_t ndepend = orig_ndepend;
++ size_t normal = ndepend;
++ size_t n = 2;
+ size_t i;
+ size_t num_awaited = 0;
+ struct gomp_task *child_task = NULL;
+ struct gomp_task *to_free = NULL;
+ int do_wake = 0;
+
++ if (ndepend == 0)
++ {
++ ndepend = nout;
++ nout = (uintptr_t) depend[2] + (uintptr_t) depend[3];
++ normal = nout + (uintptr_t) depend[4];
++ n = 5;
++ }
+ gomp_mutex_lock (&team->task_lock);
+ for (i = 0; i < ndepend; i++)
+ {
+- elem.addr = depend[i + 2];
++ elem.addr = depend[i + n];
++ elem.is_in = i >= nout;
++ if (__builtin_expect (i >= normal, 0))
++ {
++ void **d = (void **) elem.addr;
++ switch ((uintptr_t) d[1])
++ {
++ case GOMP_DEPEND_IN:
++ break;
++ case GOMP_DEPEND_OUT:
++ case GOMP_DEPEND_INOUT:
++ case GOMP_DEPEND_MUTEXINOUTSET:
++ elem.is_in = 0;
++ break;
++ default:
++ gomp_fatal ("unknown omp_depend_t dependence type %d",
++ (int) (uintptr_t) d[1]);
++ }
++ elem.addr = d[0];
++ }
+ ent = htab_find (task->depend_hash, &elem);
+ for (; ent; ent = ent->next)
+- if (i >= nout && ent->is_in)
++ if (elem.is_in && ent->is_in)
+ continue;
+ else
+ {
+@@ -1654,13 +1828,28 @@ GOMP_taskyield (void)
+ /* Nothing at the moment. */
+ }
+
++static inline struct gomp_taskgroup *
++gomp_taskgroup_init (struct gomp_taskgroup *prev)
++{
++ struct gomp_taskgroup *taskgroup
++ = gomp_malloc (sizeof (struct gomp_taskgroup));
++ taskgroup->prev = prev;
++ priority_queue_init (&taskgroup->taskgroup_queue);
++ taskgroup->reductions = prev ? prev->reductions : NULL;
++ taskgroup->in_taskgroup_wait = false;
++ taskgroup->cancelled = false;
++ taskgroup->workshare = false;
++ taskgroup->num_children = 0;
++ gomp_sem_init (&taskgroup->taskgroup_sem, 0);
++ return taskgroup;
++}
++
+ void
+ GOMP_taskgroup_start (void)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ struct gomp_task *task = thr->task;
+- struct gomp_taskgroup *taskgroup;
+
+ /* If team is NULL, all tasks are executed as
+ GOMP_TASK_UNDEFERRED tasks and thus all children tasks of
+@@ -1668,14 +1857,7 @@ GOMP_taskgroup_start (void)
+ by the time GOMP_taskgroup_end is called. */
+ if (team == NULL)
+ return;
+- taskgroup = gomp_malloc (sizeof (struct gomp_taskgroup));
+- taskgroup->prev = task->taskgroup;
+- priority_queue_init (&taskgroup->taskgroup_queue);
+- taskgroup->in_taskgroup_wait = false;
+- taskgroup->cancelled = false;
+- taskgroup->num_children = 0;
+- gomp_sem_init (&taskgroup->taskgroup_sem, 0);
+- task->taskgroup = taskgroup;
++ task->taskgroup = gomp_taskgroup_init (task->taskgroup);
+ }
+
+ void
+@@ -1840,6 +2022,302 @@ GOMP_taskgroup_end (void)
+ free (taskgroup);
+ }
+
++static inline __attribute__((always_inline)) void
++gomp_reduction_register (uintptr_t *data, uintptr_t *old, uintptr_t *orig,
++ unsigned nthreads)
++{
++ size_t total_cnt = 0;
++ uintptr_t *d = data;
++ struct htab *old_htab = NULL, *new_htab;
++ do
++ {
++ if (__builtin_expect (orig != NULL, 0))
++ {
++ /* For worksharing task reductions, memory has been allocated
++ already by some other thread that encountered the construct
++ earlier. */
++ d[2] = orig[2];
++ d[6] = orig[6];
++ orig = (uintptr_t *) orig[4];
++ }
++ else
++ {
++ size_t sz = d[1] * nthreads;
++ /* Should use omp_alloc if d[3] is not -1. */
++ void *ptr = gomp_aligned_alloc (d[2], sz);
++ memset (ptr, '\0', sz);
++ d[2] = (uintptr_t) ptr;
++ d[6] = d[2] + sz;
++ }
++ d[5] = 0;
++ total_cnt += d[0];
++ if (d[4] == 0)
++ {
++ d[4] = (uintptr_t) old;
++ break;
++ }
++ else
++ d = (uintptr_t *) d[4];
++ }
++ while (1);
++ if (old && old[5])
++ {
++ old_htab = (struct htab *) old[5];
++ total_cnt += htab_elements (old_htab);
++ }
++ new_htab = htab_create (total_cnt);
++ if (old_htab)
++ {
++ /* Copy old hash table, like in htab_expand. */
++ hash_entry_type *p, *olimit;
++ new_htab->n_elements = htab_elements (old_htab);
++ olimit = old_htab->entries + old_htab->size;
++ p = old_htab->entries;
++ do
++ {
++ hash_entry_type x = *p;
++ if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
++ *find_empty_slot_for_expand (new_htab, htab_hash (x)) = x;
++ p++;
++ }
++ while (p < olimit);
++ }
++ d = data;
++ do
++ {
++ size_t j;
++ for (j = 0; j < d[0]; ++j)
++ {
++ uintptr_t *p = d + 7 + j * 3;
++ p[2] = (uintptr_t) d;
++ /* Ugly hack, hash_entry_type is defined for the task dependencies,
++ which hash on the first element which is a pointer. We need
++ to hash also on the first sizeof (uintptr_t) bytes which contain
++ a pointer. Hide the cast from the compiler. */
++ hash_entry_type n;
++ __asm ("" : "=g" (n) : "0" (p));
++ *htab_find_slot (&new_htab, n, INSERT) = n;
++ }
++ if (d[4] == (uintptr_t) old)
++ break;
++ else
++ d = (uintptr_t *) d[4];
++ }
++ while (1);
++ d[5] = (uintptr_t) new_htab;
++}
++
++static void
++gomp_create_artificial_team (void)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_task_icv *icv;
++ struct gomp_team *team = gomp_new_team (1);
++ struct gomp_task *task = thr->task;
++ icv = task ? &task->icv : &gomp_global_icv;
++ team->prev_ts = thr->ts;
++ thr->ts.team = team;
++ thr->ts.team_id = 0;
++ thr->ts.work_share = &team->work_shares[0];
++ thr->ts.last_work_share = NULL;
++#ifdef HAVE_SYNC_BUILTINS
++ thr->ts.single_count = 0;
++#endif
++ thr->ts.static_trip = 0;
++ thr->task = &team->implicit_task[0];
++ gomp_init_task (thr->task, NULL, icv);
++ if (task)
++ {
++ thr->task = task;
++ gomp_end_task ();
++ free (task);
++ thr->task = &team->implicit_task[0];
++ }
++#ifdef LIBGOMP_USE_PTHREADS
++ else
++ pthread_setspecific (gomp_thread_destructor, thr);
++#endif
++}
++
++/* The format of data is:
++ data[0] cnt
++ data[1] size
++ data[2] alignment (on output array pointer)
++ data[3] allocator (-1 if malloc allocator)
++ data[4] next pointer
++ data[5] used internally (htab pointer)
++ data[6] used internally (end of array)
++ cnt times
++ ent[0] address
++ ent[1] offset
++ ent[2] used internally (pointer to data[0])
++ The entries are sorted by increasing offset, so that a binary
++ search can be performed. Normally, data[8] is 0, exception is
++ for worksharing construct task reductions in cancellable parallel,
++ where at offset 0 there should be space for a pointer and an integer
++ which are used internally. */
++
++void
++GOMP_taskgroup_reduction_register (uintptr_t *data)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_team *team = thr->ts.team;
++ struct gomp_task *task;
++ unsigned nthreads;
++ if (__builtin_expect (team == NULL, 0))
++ {
++ /* The task reduction code needs a team and task, so for
++ orphaned taskgroups just create the implicit team. */
++ gomp_create_artificial_team ();
++ ialias_call (GOMP_taskgroup_start) ();
++ team = thr->ts.team;
++ }
++ nthreads = team->nthreads;
++ task = thr->task;
++ gomp_reduction_register (data, task->taskgroup->reductions, NULL, nthreads);
++ task->taskgroup->reductions = data;
++}
++
++void
++GOMP_taskgroup_reduction_unregister (uintptr_t *data)
++{
++ uintptr_t *d = data;
++ htab_free ((struct htab *) data[5]);
++ do
++ {
++ gomp_aligned_free ((void *) d[2]);
++ d = (uintptr_t *) d[4];
++ }
++ while (d && !d[5]);
++}
++ialias (GOMP_taskgroup_reduction_unregister)
++
++/* For i = 0 to cnt-1, remap ptrs[i] which is either address of the
++ original list item or address of previously remapped original list
++ item to address of the private copy, store that to ptrs[i].
++ For i < cntorig, additionally set ptrs[cnt+i] to the address of
++ the original list item. */
++
++void
++GOMP_task_reduction_remap (size_t cnt, size_t cntorig, void **ptrs)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_task *task = thr->task;
++ unsigned id = thr->ts.team_id;
++ uintptr_t *data = task->taskgroup->reductions;
++ uintptr_t *d;
++ struct htab *reduction_htab = (struct htab *) data[5];
++ size_t i;
++ for (i = 0; i < cnt; ++i)
++ {
++ hash_entry_type ent, n;
++ __asm ("" : "=g" (ent) : "0" (ptrs + i));
++ n = htab_find (reduction_htab, ent);
++ if (n)
++ {
++ uintptr_t *p;
++ __asm ("" : "=g" (p) : "0" (n));
++ /* At this point, p[0] should be equal to (uintptr_t) ptrs[i],
++ p[1] is the offset within the allocated chunk for each
++ thread, p[2] is the array registered with
++ GOMP_taskgroup_reduction_register, d[2] is the base of the
++ allocated memory and d[1] is the size of the allocated chunk
++ for one thread. */
++ d = (uintptr_t *) p[2];
++ ptrs[i] = (void *) (d[2] + id * d[1] + p[1]);
++ if (__builtin_expect (i < cntorig, 0))
++ ptrs[cnt + i] = (void *) p[0];
++ continue;
++ }
++ d = data;
++ while (d != NULL)
++ {
++ if ((uintptr_t) ptrs[i] >= d[2] && (uintptr_t) ptrs[i] < d[6])
++ break;
++ d = (uintptr_t *) d[4];
++ }
++ if (d == NULL)
++ gomp_fatal ("couldn't find matching task_reduction or reduction with "
++ "task modifier for %p", ptrs[i]);
++ uintptr_t off = ((uintptr_t) ptrs[i] - d[2]) % d[1];
++ ptrs[i] = (void *) (d[2] + id * d[1] + off);
++ if (__builtin_expect (i < cntorig, 0))
++ {
++ size_t lo = 0, hi = d[0] - 1;
++ while (lo <= hi)
++ {
++ size_t m = (lo + hi) / 2;
++ if (d[7 + 3 * m + 1] < off)
++ lo = m + 1;
++ else if (d[7 + 3 * m + 1] == off)
++ {
++ ptrs[cnt + i] = (void *) d[7 + 3 * m];
++ break;
++ }
++ else
++ hi = m - 1;
++ }
++ if (lo > hi)
++ gomp_fatal ("couldn't find matching task_reduction or reduction "
++ "with task modifier for %p", ptrs[i]);
++ }
++ }
++}
++
++struct gomp_taskgroup *
++gomp_parallel_reduction_register (uintptr_t *data, unsigned nthreads)
++{
++ struct gomp_taskgroup *taskgroup = gomp_taskgroup_init (NULL);
++ gomp_reduction_register (data, NULL, NULL, nthreads);
++ taskgroup->reductions = data;
++ return taskgroup;
++}
++
++void
++gomp_workshare_task_reduction_register (uintptr_t *data, uintptr_t *orig)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_team *team = thr->ts.team;
++ struct gomp_task *task = thr->task;
++ unsigned nthreads = team->nthreads;
++ gomp_reduction_register (data, task->taskgroup->reductions, orig, nthreads);
++ task->taskgroup->reductions = data;
++}
++
++void
++gomp_workshare_taskgroup_start (void)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_team *team = thr->ts.team;
++ struct gomp_task *task;
++
++ if (team == NULL)
++ {
++ gomp_create_artificial_team ();
++ team = thr->ts.team;
++ }
++ task = thr->task;
++ task->taskgroup = gomp_taskgroup_init (task->taskgroup);
++ task->taskgroup->workshare = true;
++}
++
++void
++GOMP_workshare_task_reduction_unregister (bool cancelled)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_task *task = thr->task;
++ struct gomp_team *team = thr->ts.team;
++ uintptr_t *data = task->taskgroup->reductions;
++ ialias_call (GOMP_taskgroup_end) ();
++ if (thr->ts.team_id == 0)
++ ialias_call (GOMP_taskgroup_reduction_unregister) (data);
++ else
++ htab_free ((struct htab *) data[5]);
++
++ if (!cancelled)
++ gomp_team_barrier_wait (&team->barrier);
++}
++
+ int
+ omp_in_final (void)
+ {
+--- libgomp/team.c.jj 2018-04-25 09:40:31.322655307 +0200
++++ libgomp/team.c 2019-05-07 18:46:36.548109384 +0200
+@@ -32,7 +32,6 @@
+ #include
+
+ #ifdef LIBGOMP_USE_PTHREADS
+-/* This attribute contains PTHREAD_CREATE_DETACHED. */
+ pthread_attr_t gomp_thread_attr;
+
+ /* This key is for the thread destructor. */
+@@ -58,6 +57,7 @@ struct gomp_thread_start_data
+ struct gomp_thread_pool *thread_pool;
+ unsigned int place;
+ bool nested;
++ pthread_t handle;
+ };
+
+
+@@ -89,6 +89,9 @@ gomp_thread_start (void *xdata)
+ thr->ts = data->ts;
+ thr->task = data->task;
+ thr->place = data->place;
++#ifdef GOMP_NEEDS_THREAD_HANDLE
++ thr->handle = data->handle;
++#endif
+
+ thr->ts.team->ordered_release[thr->ts.team_id] = &thr->release;
+
+@@ -131,6 +134,7 @@ gomp_thread_start (void *xdata)
+ }
+
+ gomp_sem_destroy (&thr->release);
++ pthread_detach (pthread_self ());
+ thr->thread_pool = NULL;
+ thr->task = NULL;
+ return NULL;
+@@ -183,7 +187,7 @@ gomp_new_team (unsigned nthreads)
+ team->single_count = 0;
+ #endif
+ team->work_shares_to_free = &team->work_shares[0];
+- gomp_init_work_share (&team->work_shares[0], false, nthreads);
++ gomp_init_work_share (&team->work_shares[0], 0, nthreads);
+ team->work_shares[0].next_alloc = NULL;
+ team->work_share_list_free = NULL;
+ team->work_share_list_alloc = &team->work_shares[1];
+@@ -231,6 +235,7 @@ gomp_free_pool_helper (void *thread_pool
+ thr->thread_pool = NULL;
+ thr->task = NULL;
+ #ifdef LIBGOMP_USE_PTHREADS
++ pthread_detach (pthread_self ());
+ pthread_exit (NULL);
+ #elif defined(__nvptx__)
+ asm ("exit;");
+@@ -297,7 +302,8 @@ gomp_free_thread (void *arg __attribute_
+ #ifdef LIBGOMP_USE_PTHREADS
+ void
+ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
+- unsigned flags, struct gomp_team *team)
++ unsigned flags, struct gomp_team *team,
++ struct gomp_taskgroup *taskgroup)
+ {
+ struct gomp_thread_start_data *start_data;
+ struct gomp_thread *thr, *nthr;
+@@ -312,6 +318,7 @@ gomp_team_start (void (*fn) (void *), vo
+ unsigned int s = 0, rest = 0, p = 0, k = 0;
+ unsigned int affinity_count = 0;
+ struct gomp_thread **affinity_thr = NULL;
++ bool force_display = false;
+
+ thr = gomp_thread ();
+ nested = thr->ts.level;
+@@ -319,7 +326,12 @@ gomp_team_start (void (*fn) (void *), vo
+ task = thr->task;
+ icv = task ? &task->icv : &gomp_global_icv;
+ if (__builtin_expect (gomp_places_list != NULL, 0) && thr->place == 0)
+- gomp_init_affinity ();
++ {
++ gomp_init_affinity ();
++ if (__builtin_expect (gomp_display_affinity_var, 0) && nthreads == 1)
++ gomp_display_affinity_thread (gomp_thread_self (), &thr->ts,
++ thr->place);
++ }
+
+ /* Always save the previous state, even if this isn't a nested team.
+ In particular, we should save any work share state from an outer
+@@ -338,6 +350,9 @@ gomp_team_start (void (*fn) (void *), vo
+ #endif
+ thr->ts.static_trip = 0;
+ thr->task = &team->implicit_task[0];
++#ifdef GOMP_NEEDS_THREAD_HANDLE
++ thr->handle = pthread_self ();
++#endif
+ nthreads_var = icv->nthreads_var;
+ if (__builtin_expect (gomp_nthreads_var_list != NULL, 0)
+ && thr->ts.level < gomp_nthreads_var_list_len)
+@@ -350,6 +365,7 @@ gomp_team_start (void (*fn) (void *), vo
+ && thr->ts.level < gomp_bind_var_list_len)
+ bind_var = gomp_bind_var_list[thr->ts.level];
+ gomp_init_task (thr->task, task, icv);
++ thr->task->taskgroup = taskgroup;
+ team->implicit_task[0].icv.nthreads_var = nthreads_var;
+ team->implicit_task[0].icv.bind_var = bind_var;
+
+@@ -465,7 +481,9 @@ gomp_team_start (void (*fn) (void *), vo
+ pool->threads
+ = gomp_realloc (pool->threads,
+ pool->threads_size
+- * sizeof (struct gomp_thread_data *));
++ * sizeof (struct gomp_thread *));
++ /* Add current (master) thread to threads[]. */
++ pool->threads[0] = thr;
+ }
+
+ /* Release existing idle threads. */
+@@ -540,6 +558,7 @@ gomp_team_start (void (*fn) (void *), vo
+ + place_partition_len))
+ {
+ unsigned int l;
++ force_display = true;
+ if (affinity_thr == NULL)
+ {
+ unsigned int j;
+@@ -623,6 +642,7 @@ gomp_team_start (void (*fn) (void *), vo
+ gomp_init_task (nthr->task, task, icv);
+ team->implicit_task[i].icv.nthreads_var = nthreads_var;
+ team->implicit_task[i].icv.bind_var = bind_var;
++ nthr->task->taskgroup = taskgroup;
+ nthr->fn = fn;
+ nthr->data = data;
+ team->ordered_release[i] = &nthr->release;
+@@ -712,19 +732,17 @@ gomp_team_start (void (*fn) (void *), vo
+ {
+ size_t stacksize;
+ pthread_attr_init (&thread_attr);
+- pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
+ if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize))
+ pthread_attr_setstacksize (&thread_attr, stacksize);
+ attr = &thread_attr;
+ }
+
+ start_data = gomp_alloca (sizeof (struct gomp_thread_start_data)
+- * (nthreads-i));
++ * (nthreads - i));
+
+ /* Launch new threads. */
+ for (; i < nthreads; ++i)
+ {
+- pthread_t pt;
+ int err;
+
+ start_data->ts.place_partition_off = thr->ts.place_partition_off;
+@@ -810,11 +828,14 @@ gomp_team_start (void (*fn) (void *), vo
+ gomp_init_task (start_data->task, task, icv);
+ team->implicit_task[i].icv.nthreads_var = nthreads_var;
+ team->implicit_task[i].icv.bind_var = bind_var;
++ start_data->task->taskgroup = taskgroup;
+ start_data->thread_pool = pool;
+ start_data->nested = nested;
+
+ attr = gomp_adjust_thread_attr (attr, &thread_attr);
+- err = pthread_create (&pt, attr, gomp_thread_start, start_data++);
++ err = pthread_create (&start_data->handle, attr, gomp_thread_start,
++ start_data);
++ start_data++;
+ if (err != 0)
+ gomp_fatal ("Thread creation failed: %s", strerror (err));
+ }
+@@ -854,6 +875,42 @@ gomp_team_start (void (*fn) (void *), vo
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
+ #endif
+ }
++ if (__builtin_expect (gomp_display_affinity_var, 0))
++ {
++ if (nested
++ || nthreads != old_threads_used
++ || force_display)
++ {
++ gomp_display_affinity_thread (gomp_thread_self (), &thr->ts,
++ thr->place);
++ if (nested)
++ {
++ start_data -= nthreads - 1;
++ for (i = 1; i < nthreads; ++i)
++ {
++ gomp_display_affinity_thread (
++#ifdef LIBGOMP_USE_PTHREADS
++ start_data->handle,
++#else
++ gomp_thread_self (),
++#endif
++ &start_data->ts,
++ start_data->place);
++ start_data++;
++ }
++ }
++ else
++ {
++ for (i = 1; i < nthreads; ++i)
++ {
++ gomp_thread_handle handle
++ = gomp_thread_to_pthread_t (pool->threads[i]);
++ gomp_display_affinity_thread (handle, &pool->threads[i]->ts,
++ pool->threads[i]->place);
++ }
++ }
++ }
++ }
+ if (__builtin_expect (affinity_thr != NULL, 0)
+ && team->prev_ts.place_partition_len > 64)
+ free (affinity_thr);
+@@ -894,7 +951,7 @@ gomp_team_end (void)
+ gomp_end_task ();
+ thr->ts = team->prev_ts;
+
+- if (__builtin_expect (thr->ts.team != NULL, 0))
++ if (__builtin_expect (thr->ts.level != 0, 0))
+ {
+ #ifdef HAVE_SYNC_BUILTINS
+ __sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads);
+@@ -959,6 +1016,76 @@ team_destructor (void)
+ crashes. */
+ pthread_key_delete (gomp_thread_destructor);
+ }
++
++/* Similar to gomp_free_pool_helper, but don't detach itself,
++ gomp_pause_host will pthread_join those threads. */
++
++static void
++gomp_pause_pool_helper (void *thread_pool)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_thread_pool *pool
++ = (struct gomp_thread_pool *) thread_pool;
++ gomp_simple_barrier_wait_last (&pool->threads_dock);
++ gomp_sem_destroy (&thr->release);
++ thr->thread_pool = NULL;
++ thr->task = NULL;
++ pthread_exit (NULL);
++}
++
++/* Free a thread pool and release its threads. Return non-zero on
++ failure. */
++
++int
++gomp_pause_host (void)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_thread_pool *pool = thr->thread_pool;
++ if (thr->ts.level)
++ return -1;
++ if (pool)
++ {
++ if (pool->threads_used > 0)
++ {
++ int i;
++ pthread_t *thrs
++ = gomp_alloca (sizeof (pthread_t) * pool->threads_used);
++ for (i = 1; i < pool->threads_used; i++)
++ {
++ struct gomp_thread *nthr = pool->threads[i];
++ nthr->fn = gomp_pause_pool_helper;
++ nthr->data = pool;
++ thrs[i] = gomp_thread_to_pthread_t (nthr);
++ }
++ /* This barrier undocks threads docked on pool->threads_dock. */
++ gomp_simple_barrier_wait (&pool->threads_dock);
++ /* And this waits till all threads have called gomp_barrier_wait_last
++ in gomp_pause_pool_helper. */
++ gomp_simple_barrier_wait (&pool->threads_dock);
++ /* Now it is safe to destroy the barrier and free the pool. */
++ gomp_simple_barrier_destroy (&pool->threads_dock);
++
++#ifdef HAVE_SYNC_BUILTINS
++ __sync_fetch_and_add (&gomp_managed_threads,
++ 1L - pool->threads_used);
++#else
++ gomp_mutex_lock (&gomp_managed_threads_lock);
++ gomp_managed_threads -= pool->threads_used - 1L;
++ gomp_mutex_unlock (&gomp_managed_threads_lock);
++#endif
++ for (i = 1; i < pool->threads_used; i++)
++ pthread_join (thrs[i], NULL);
++ }
++ if (pool->last_team)
++ free_team (pool->last_team);
++#ifndef __nvptx__
++ free (pool->threads);
++ free (pool);
++#endif
++ thr->thread_pool = NULL;
++ }
++ return 0;
++}
+ #endif
+
+ struct gomp_task_icv *
+--- libgomp/libgomp.h.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/libgomp.h 2019-05-07 19:01:51.285535999 +0200
+@@ -44,6 +44,7 @@
+ #include "config.h"
+ #include "gstdint.h"
+ #include "libgomp-plugin.h"
++#include "gomp-constants.h"
+
+ #ifdef HAVE_PTHREAD_H
+ #include
+@@ -85,9 +86,21 @@ enum memmodel
+
+ /* alloc.c */
+
++#if defined(HAVE_ALIGNED_ALLOC) \
++ || defined(HAVE__ALIGNED_MALLOC) \
++ || defined(HAVE_POSIX_MEMALIGN) \
++ || defined(HAVE_MEMALIGN)
++/* Defined if gomp_aligned_alloc doesn't use fallback version
++ and free can be used instead of gomp_aligned_free. */
++#define GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC 1
++#endif
++
+ extern void *gomp_malloc (size_t) __attribute__((malloc));
+ extern void *gomp_malloc_cleared (size_t) __attribute__((malloc));
+ extern void *gomp_realloc (void *, size_t);
++extern void *gomp_aligned_alloc (size_t, size_t)
++ __attribute__((malloc, alloc_size (2)));
++extern void gomp_aligned_free (void *);
+
+ /* Avoid conflicting prototypes of alloca() in system headers by using
+ GCC's builtin alloca(). */
+@@ -137,7 +150,8 @@ enum gomp_schedule_type
+ GFS_STATIC,
+ GFS_DYNAMIC,
+ GFS_GUIDED,
+- GFS_AUTO
++ GFS_AUTO,
++ GFS_MONOTONIC = 0x80000000U
+ };
+
+ struct gomp_doacross_work_share
+@@ -174,6 +188,8 @@ struct gomp_doacross_work_share
+ /* Likewise, but for the ull implementation. */
+ unsigned long long boundary_ull;
+ };
++ /* Pointer to extra memory if needed for lastprivate(conditional). */
++ void *extra;
+ /* Array of shift counts for each dimension if they can be flattened. */
+ unsigned int shift_counts[];
+ };
+@@ -275,6 +291,9 @@ struct gomp_work_share
+ struct gomp_work_share *next_free;
+ };
+
++ /* Task reductions for this work-sharing construct. */
++ uintptr_t *task_reductions;
++
+ /* If only few threads are in the team, ordered_team_ids can point
+ to this array which fills the padding at the end of this struct. */
+ unsigned inline_ordered_team_ids[0];
+@@ -365,8 +384,12 @@ extern void **gomp_places_list;
+ extern unsigned long gomp_places_list_len;
+ extern unsigned int gomp_num_teams_var;
+ extern int gomp_debug_var;
++extern bool gomp_display_affinity_var;
++extern char *gomp_affinity_format_var;
++extern size_t gomp_affinity_format_len;
+ extern int goacc_device_num;
+ extern char *goacc_device_type;
++extern int goacc_default_dims[GOMP_DIM_MAX];
+
+ enum gomp_task_kind
+ {
+@@ -469,8 +492,10 @@ struct gomp_taskgroup
+ struct gomp_taskgroup *prev;
+ /* Queue of tasks that belong in this taskgroup. */
+ struct priority_queue taskgroup_queue;
++ uintptr_t *reductions;
+ bool in_taskgroup_wait;
+ bool cancelled;
++ bool workshare;
+ gomp_sem_t taskgroup_sem;
+ size_t num_children;
+ };
+@@ -613,6 +638,19 @@ struct gomp_thread
+
+ /* User pthread thread pool */
+ struct gomp_thread_pool *thread_pool;
++
++#if defined(LIBGOMP_USE_PTHREADS) \
++ && (!defined(HAVE_TLS) \
++ || !defined(__GLIBC__) \
++ || !defined(USING_INITIAL_EXEC_TLS))
++ /* pthread_t of the thread containing this gomp_thread.
++ On Linux when using initial-exec TLS,
++ (typeof (pthread_t)) gomp_thread () - pthread_self ()
++ is constant in all threads, so we can optimize and not
++ store it. */
++#define GOMP_NEEDS_THREAD_HANDLE 1
++ pthread_t handle;
++#endif
+ };
+
+
+@@ -709,6 +747,25 @@ extern bool gomp_affinity_finalize_place
+ extern bool gomp_affinity_init_level (int, unsigned long, bool);
+ extern void gomp_affinity_print_place (void *);
+ extern void gomp_get_place_proc_ids_8 (int, int64_t *);
++extern void gomp_display_affinity_place (char *, size_t, size_t *, int);
++
++/* affinity-fmt.c */
++
++extern void gomp_print_string (const char *str, size_t len);
++extern void gomp_set_affinity_format (const char *, size_t);
++extern void gomp_display_string (char *, size_t, size_t *, const char *,
++ size_t);
++#ifdef LIBGOMP_USE_PTHREADS
++typedef pthread_t gomp_thread_handle;
++#else
++typedef struct {} gomp_thread_handle;
++#endif
++extern size_t gomp_display_affinity (char *, size_t, const char *,
++ gomp_thread_handle,
++ struct gomp_team_state *, unsigned int);
++extern void gomp_display_affinity_thread (gomp_thread_handle,
++ struct gomp_team_state *,
++ unsigned int) __attribute__((cold));
+
+ /* iter.c */
+
+@@ -745,9 +802,9 @@ extern void gomp_ordered_next (void);
+ extern void gomp_ordered_static_init (void);
+ extern void gomp_ordered_static_next (void);
+ extern void gomp_ordered_sync (void);
+-extern void gomp_doacross_init (unsigned, long *, long);
++extern void gomp_doacross_init (unsigned, long *, long, size_t);
+ extern void gomp_doacross_ull_init (unsigned, unsigned long long *,
+- unsigned long long);
++ unsigned long long, size_t);
+
+ /* parallel.c */
+
+@@ -770,6 +827,10 @@ extern bool gomp_create_target_task (str
+ size_t *, unsigned short *, unsigned int,
+ void **, void **,
+ enum gomp_target_task_state);
++extern struct gomp_taskgroup *gomp_parallel_reduction_register (uintptr_t *,
++ unsigned);
++extern void gomp_workshare_taskgroup_start (void);
++extern void gomp_workshare_task_reduction_register (uintptr_t *, uintptr_t *);
+
+ static void inline
+ gomp_finish_task (struct gomp_task *task)
+@@ -782,9 +843,11 @@ gomp_finish_task (struct gomp_task *task
+
+ extern struct gomp_team *gomp_new_team (unsigned);
+ extern void gomp_team_start (void (*) (void *), void *, unsigned,
+- unsigned, struct gomp_team *);
++ unsigned, struct gomp_team *,
++ struct gomp_taskgroup *);
+ extern void gomp_team_end (void);
+ extern void gomp_free_thread (void *);
++extern int gomp_pause_host (void);
+
+ /* target.c */
+
+@@ -851,6 +914,8 @@ struct splay_tree_key_s {
+ uintptr_t tgt_offset;
+ /* Reference count. */
+ uintptr_t refcount;
++ /* Dynamic reference count. */
++ uintptr_t dynamic_refcount;
+ /* Pointer to the original mapping of "omp declare target link" object. */
+ splay_tree_key link_key;
+ };
+@@ -989,7 +1054,9 @@ enum gomp_map_vars_kind
+ };
+
+ extern void gomp_acc_insert_pointer (size_t, void **, size_t *, void *);
+-extern void gomp_acc_remove_pointer (void *, bool, int, int);
++extern void gomp_acc_remove_pointer (void *, size_t, bool, int, int, int);
++extern void gomp_acc_declare_allocate (bool, size_t, void **, size_t *,
++ unsigned short *);
+
+ extern struct target_mem_desc *gomp_map_vars (struct gomp_device_descr *,
+ size_t, void **, void **,
+@@ -999,12 +1066,13 @@ extern void gomp_unmap_vars (struct targ
+ extern void gomp_init_device (struct gomp_device_descr *);
+ extern void gomp_free_memmap (struct splay_tree_s *);
+ extern void gomp_unload_device (struct gomp_device_descr *);
++extern bool gomp_remove_var (struct gomp_device_descr *, splay_tree_key);
+
+ /* work.c */
+
+-extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned);
++extern void gomp_init_work_share (struct gomp_work_share *, size_t, unsigned);
+ extern void gomp_fini_work_share (struct gomp_work_share *);
+-extern bool gomp_work_share_start (bool);
++extern bool gomp_work_share_start (size_t);
+ extern void gomp_work_share_end (void);
+ extern bool gomp_work_share_end_cancel (void);
+ extern void gomp_work_share_end_nowait (void);
+@@ -1028,6 +1096,14 @@ gomp_work_share_init_done (void)
+ #include "omp-lock.h"
+ #define _LIBGOMP_OMP_LOCK_DEFINED 1
+ #include "omp.h.in"
++#define omp_sched_monotonic 0x80000000U
++typedef enum omp_pause_resource_t
++{
++ omp_pause_soft = 1,
++ omp_pause_hard = 2
++} omp_pause_resource_t;
++extern int omp_pause_resource (omp_pause_resource_t, int) __GOMP_NOTHROW;
++extern int omp_pause_resource_all (omp_pause_resource_t) __GOMP_NOTHROW;
+
+ #if !defined (HAVE_ATTRIBUTE_VISIBILITY) \
+ || !defined (HAVE_ATTRIBUTE_ALIAS) \
+@@ -1082,16 +1158,26 @@ extern int gomp_test_nest_lock_25 (omp_n
+ # define attribute_hidden
+ #endif
+
++#if __GNUC__ >= 9
++# define HAVE_ATTRIBUTE_COPY
++#endif
++
++#ifdef HAVE_ATTRIBUTE_COPY
++# define attribute_copy(arg) __attribute__ ((copy (arg)))
++#else
++# define attribute_copy(arg)
++#endif
++
+ #ifdef HAVE_ATTRIBUTE_ALIAS
+ # define strong_alias(fn, al) \
+- extern __typeof (fn) al __attribute__ ((alias (#fn)));
++ extern __typeof (fn) al __attribute__ ((alias (#fn))) attribute_copy (fn);
+
+ # define ialias_ulp ialias_str1(__USER_LABEL_PREFIX__)
+ # define ialias_str1(x) ialias_str2(x)
+ # define ialias_str2(x) #x
+ # define ialias(fn) \
+ extern __typeof (fn) gomp_ialias_##fn \
+- __attribute__ ((alias (#fn))) attribute_hidden;
++ __attribute__ ((alias (#fn))) attribute_hidden attribute_copy (fn);
+ # define ialias_redirect(fn) \
+ extern __typeof (fn) fn __asm__ (ialias_ulp "gomp_ialias_" #fn) attribute_hidden;
+ # define ialias_call(fn) gomp_ialias_ ## fn
+@@ -1131,4 +1217,42 @@ task_to_priority_node (enum priority_que
+ return (struct priority_node *) ((char *) task
+ + priority_queue_offset (type));
+ }
++
++#ifdef LIBGOMP_USE_PTHREADS
++static inline gomp_thread_handle
++gomp_thread_self (void)
++{
++ return pthread_self ();
++}
++
++static inline gomp_thread_handle
++gomp_thread_to_pthread_t (struct gomp_thread *thr)
++{
++ struct gomp_thread *this_thr = gomp_thread ();
++ if (thr == this_thr)
++ return pthread_self ();
++#ifdef GOMP_NEEDS_THREAD_HANDLE
++ return thr->handle;
++#else
++ /* On Linux with initial-exec TLS, the pthread_t of the thread containing
++ thr can be computed from thr, this_thr and pthread_self (),
++ as the distance between this_thr and pthread_self () is constant. */
++ return pthread_self () + ((uintptr_t) thr - (uintptr_t) this_thr);
++#endif
++}
++#else
++static inline gomp_thread_handle
++gomp_thread_self (void)
++{
++ return (gomp_thread_handle) {};
++}
++
++static inline gomp_thread_handle
++gomp_thread_to_pthread_t (struct gomp_thread *thr)
++{
++ (void) thr;
++ return gomp_thread_self ();
++}
++#endif
++
+ #endif /* LIBGOMP_H */
+--- libgomp/oacc-parallel.c.jj 2018-04-25 09:40:31.319655306 +0200
++++ libgomp/oacc-parallel.c 2019-05-07 19:09:47.010991153 +0200
+@@ -27,6 +27,8 @@
+ /* This file handles OpenACC constructs. */
+
+ #include "openacc.h"
++void acc_copyout_finalize (void *, size_t) __GOACC_NOTHROW;
++void acc_delete_finalize (void *, size_t) __GOACC_NOTHROW;
+ #include "libgomp.h"
+ #include "libgomp_g.h"
+ #include "gomp-constants.h"
+@@ -38,31 +40,95 @@
+ #include
+ #include
+
++
++/* In the ABI, the GOACC_FLAGs are encoded as an inverted bitmask, so that we
++ continue to support the following two legacy values. */
++_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_ICV) == 0,
++ "legacy GOMP_DEVICE_ICV broken");
++_Static_assert (GOACC_FLAGS_UNMARSHAL (GOMP_DEVICE_HOST_FALLBACK)
++ == GOACC_FLAG_HOST_FALLBACK,
++ "legacy GOMP_DEVICE_HOST_FALLBACK broken");
++
++
++/* Returns the number of mappings associated with the pointer or pset. PSET
++ have three mappings, whereas pointer have two. */
++
+ static int
+-find_pset (int pos, size_t mapnum, unsigned short *kinds)
++find_pointer (int pos, size_t mapnum, unsigned short *kinds)
+ {
+ if (pos + 1 >= mapnum)
+ return 0;
+
+ unsigned char kind = kinds[pos+1] & 0xff;
+
+- return kind == GOMP_MAP_TO_PSET;
++ if (kind == GOMP_MAP_TO_PSET)
++ return 3;
++ else if (kind == GOMP_MAP_POINTER)
++ return 2;
++
++ return 0;
++}
++
++/* Handle the mapping pair that are presented when a
++ deviceptr clause is used with Fortran. */
++
++static void
++handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes,
++ unsigned short *kinds)
++{
++ int i;
++
++ for (i = 0; i < mapnum; i++)
++ {
++ unsigned short kind1 = kinds[i] & 0xff;
++
++ /* Handle Fortran deviceptr clause. */
++ if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
++ {
++ unsigned short kind2;
++
++ if (i < (signed)mapnum - 1)
++ kind2 = kinds[i + 1] & 0xff;
++ else
++ kind2 = 0xffff;
++
++ if (sizes[i] == sizeof (void *))
++ continue;
++
++ /* At this point, we're dealing with a Fortran deviceptr.
++ If the next element is not what we're expecting, then
++ this is an instance of where the deviceptr variable was
++ not used within the region and the pointer was removed
++ by the gimplifier. */
++ if (kind2 == GOMP_MAP_POINTER
++ && sizes[i + 1] == 0
++ && hostaddrs[i] == *(void **)hostaddrs[i + 1])
++ {
++ kinds[i+1] = kinds[i];
++ sizes[i+1] = sizeof (void *);
++ }
++
++ /* Invalidate the entry. */
++ hostaddrs[i] = NULL;
++ }
++ }
+ }
+
+ static void goacc_wait (int async, int num_waits, va_list *ap);
+
+
+-/* Launch a possibly offloaded function on DEVICE. FN is the host fn
++/* Launch a possibly offloaded function with FLAGS. FN is the host fn
+ address. MAPNUM, HOSTADDRS, SIZES & KINDS describe the memory
+ blocks to be copied to/from the device. Varadic arguments are
+ keyed optional parameters terminated with a zero. */
+
+ void
+-GOACC_parallel_keyed (int device, void (*fn) (void *),
++GOACC_parallel_keyed (int flags_m, void (*fn) (void *),
+ size_t mapnum, void **hostaddrs, size_t *sizes,
+ unsigned short *kinds, ...)
+ {
+- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
++ int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
++
+ va_list ap;
+ struct goacc_thread *thr;
+ struct gomp_device_descr *acc_dev;
+@@ -88,9 +154,11 @@ GOACC_parallel_keyed (int device, void (
+ thr = goacc_thread ();
+ acc_dev = thr->dev;
+
++ handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds);
++
+ /* Host fallback if "if" clause is false or if the current device is set to
+ the host. */
+- if (host_fallback)
++ if (flags & GOACC_FLAG_HOST_FALLBACK)
+ {
+ goacc_save_and_set_bind (acc_device_host);
+ fn (hostaddrs);
+@@ -140,9 +208,7 @@ GOACC_parallel_keyed (int device, void (
+ case GOMP_LAUNCH_WAIT:
+ {
+ unsigned num_waits = GOMP_LAUNCH_OP (tag);
+-
+- if (num_waits)
+- goacc_wait (async, num_waits, &ap);
++ goacc_wait (async, num_waits, &ap);
+ break;
+ }
+
+@@ -177,16 +243,36 @@ GOACC_parallel_keyed (int device, void (
+ devaddrs = gomp_alloca (sizeof (void *) * mapnum);
+ for (i = 0; i < mapnum; i++)
+ devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
+- + tgt->list[i].key->tgt_offset);
++ + tgt->list[i].key->tgt_offset
++ + tgt->list[i].offset);
+
+ acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
+ async, dims, tgt);
+
+ /* If running synchronously, unmap immediately. */
+- if (async < acc_async_noval)
++ bool copyfrom = true;
++ if (async_synchronous_p (async))
+ gomp_unmap_vars (tgt, true);
+ else
+- tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
++ {
++ bool async_unmap = false;
++ for (size_t i = 0; i < tgt->list_count; i++)
++ {
++ splay_tree_key k = tgt->list[i].key;
++ if (k && k->refcount == 1)
++ {
++ async_unmap = true;
++ break;
++ }
++ }
++ if (async_unmap)
++ tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
++ else
++ {
++ copyfrom = false;
++ gomp_unmap_vars (tgt, copyfrom);
++ }
++ }
+
+ acc_dev->openacc.async_set_async_func (acc_async_sync);
+ }
+@@ -194,7 +280,7 @@ GOACC_parallel_keyed (int device, void (
+ /* Legacy entry point, only provide host execution. */
+
+ void
+-GOACC_parallel (int device, void (*fn) (void *),
++GOACC_parallel (int flags_m, void (*fn) (void *),
+ size_t mapnum, void **hostaddrs, size_t *sizes,
+ unsigned short *kinds,
+ int num_gangs, int num_workers, int vector_length,
+@@ -206,10 +292,11 @@ GOACC_parallel (int device, void (*fn) (
+ }
+
+ void
+-GOACC_data_start (int device, size_t mapnum,
++GOACC_data_start (int flags_m, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds)
+ {
+- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
++ int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
++
+ struct target_mem_desc *tgt;
+
+ #ifdef HAVE_INTTYPES_H
+@@ -227,7 +314,7 @@ GOACC_data_start (int device, size_t map
+
+ /* Host fallback or 'do nothing'. */
+ if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+- || host_fallback)
++ || (flags & GOACC_FLAG_HOST_FALLBACK))
+ {
+ tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true,
+ GOMP_MAP_VARS_OPENACC);
+@@ -258,13 +345,14 @@ GOACC_data_end (void)
+ }
+
+ void
+-GOACC_enter_exit_data (int device, size_t mapnum,
++GOACC_enter_exit_data (int flags_m, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ int async, int num_waits, ...)
+ {
++ int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
++
+ struct goacc_thread *thr;
+ struct gomp_device_descr *acc_dev;
+- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
+ bool data_enter = false;
+ size_t i;
+
+@@ -274,7 +362,7 @@ GOACC_enter_exit_data (int device, size_
+ acc_dev = thr->dev;
+
+ if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+- || host_fallback)
++ || (flags & GOACC_FLAG_HOST_FALLBACK))
+ return;
+
+ if (num_waits)
+@@ -286,6 +374,17 @@ GOACC_enter_exit_data (int device, size_
+ va_end (ap);
+ }
+
++ /* Determine whether "finalize" semantics apply to all mappings of this
++ OpenACC directive. */
++ bool finalize = false;
++ if (mapnum > 0)
++ {
++ unsigned char kind = kinds[0] & 0xff;
++ if (kind == GOMP_MAP_DELETE
++ || kind == GOMP_MAP_FORCE_FROM)
++ finalize = true;
++ }
++
+ acc_dev->openacc.async_set_async_func (async);
+
+ /* Determine if this is an "acc enter data". */
+@@ -298,13 +397,17 @@ GOACC_enter_exit_data (int device, size_
+
+ if (kind == GOMP_MAP_FORCE_ALLOC
+ || kind == GOMP_MAP_FORCE_PRESENT
+- || kind == GOMP_MAP_FORCE_TO)
++ || kind == GOMP_MAP_FORCE_TO
++ || kind == GOMP_MAP_TO
++ || kind == GOMP_MAP_ALLOC)
+ {
+ data_enter = true;
+ break;
+ }
+
+- if (kind == GOMP_MAP_DELETE
++ if (kind == GOMP_MAP_RELEASE
++ || kind == GOMP_MAP_DELETE
++ || kind == GOMP_MAP_FROM
+ || kind == GOMP_MAP_FORCE_FROM)
+ break;
+
+@@ -312,31 +415,35 @@ GOACC_enter_exit_data (int device, size_
+ kind);
+ }
+
++ /* In c, non-pointers and arrays are represented by a single data clause.
++ Dynamically allocated arrays and subarrays are represented by a data
++ clause followed by an internal GOMP_MAP_POINTER.
++
++ In fortran, scalars and not allocated arrays are represented by a
++ single data clause. Allocated arrays and subarrays have three mappings:
++ 1) the original data clause, 2) a PSET 3) a pointer to the array data.
++ */
++
+ if (data_enter)
+ {
+ for (i = 0; i < mapnum; i++)
+ {
+ unsigned char kind = kinds[i] & 0xff;
+
+- /* Scan for PSETs. */
+- int psets = find_pset (i, mapnum, kinds);
++ /* Scan for pointers and PSETs. */
++ int pointer = find_pointer (i, mapnum, kinds);
+
+- if (!psets)
++ if (!pointer)
+ {
+ switch (kind)
+ {
+- case GOMP_MAP_POINTER:
+- gomp_acc_insert_pointer (1, &hostaddrs[i], &sizes[i],
+- &kinds[i]);
+- break;
++ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_FORCE_ALLOC:
+ acc_create (hostaddrs[i], sizes[i]);
+ break;
+- case GOMP_MAP_FORCE_PRESENT:
+- acc_present_or_copyin (hostaddrs[i], sizes[i]);
+- break;
++ case GOMP_MAP_TO:
+ case GOMP_MAP_FORCE_TO:
+- acc_present_or_copyin (hostaddrs[i], sizes[i]);
++ acc_copyin (hostaddrs[i], sizes[i]);
+ break;
+ default:
+ gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
+@@ -346,12 +453,13 @@ GOACC_enter_exit_data (int device, size_
+ }
+ else
+ {
+- gomp_acc_insert_pointer (3, &hostaddrs[i], &sizes[i], &kinds[i]);
++ gomp_acc_insert_pointer (pointer, &hostaddrs[i],
++ &sizes[i], &kinds[i]);
+ /* Increment 'i' by two because OpenACC requires fortran
+ arrays to be contiguous, so each PSET is associated with
+ one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and
+ one MAP_POINTER. */
+- i += 2;
++ i += pointer - 1;
+ }
+ }
+ }
+@@ -360,22 +468,28 @@ GOACC_enter_exit_data (int device, size_
+ {
+ unsigned char kind = kinds[i] & 0xff;
+
+- int psets = find_pset (i, mapnum, kinds);
++ int pointer = find_pointer (i, mapnum, kinds);
+
+- if (!psets)
++ if (!pointer)
+ {
+ switch (kind)
+ {
+- case GOMP_MAP_POINTER:
+- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
+- == GOMP_MAP_FORCE_FROM,
+- async, 1);
+- break;
++ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+- acc_delete (hostaddrs[i], sizes[i]);
++ if (acc_is_present (hostaddrs[i], sizes[i]))
++ {
++ if (finalize)
++ acc_delete_finalize (hostaddrs[i], sizes[i]);
++ else
++ acc_delete (hostaddrs[i], sizes[i]);
++ }
+ break;
++ case GOMP_MAP_FROM:
+ case GOMP_MAP_FORCE_FROM:
+- acc_copyout (hostaddrs[i], sizes[i]);
++ if (finalize)
++ acc_copyout_finalize (hostaddrs[i], sizes[i]);
++ else
++ acc_copyout (hostaddrs[i], sizes[i]);
+ break;
+ default:
+ gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
+@@ -385,10 +499,12 @@ GOACC_enter_exit_data (int device, size_
+ }
+ else
+ {
+- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
+- == GOMP_MAP_FORCE_FROM, async, 3);
++ bool copyfrom = (kind == GOMP_MAP_FORCE_FROM
++ || kind == GOMP_MAP_FROM);
++ gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async,
++ finalize, pointer);
+ /* See the above comment. */
+- i += 2;
++ i += pointer - 1;
+ }
+ }
+
+@@ -398,13 +514,20 @@ GOACC_enter_exit_data (int device, size_
+ static void
+ goacc_wait (int async, int num_waits, va_list *ap)
+ {
+- struct goacc_thread *thr = goacc_thread ();
+- struct gomp_device_descr *acc_dev = thr->dev;
+-
+ while (num_waits--)
+ {
+ int qid = va_arg (*ap, int);
+-
++
++ /* Waiting on ACC_ASYNC_NOVAL maps to 'wait all'. */
++ if (qid == acc_async_noval)
++ {
++ if (async == acc_async_sync)
++ acc_wait_all ();
++ else
++ acc_wait_all_async (async);
++ break;
++ }
++
+ if (acc_async_test (qid))
+ continue;
+
+@@ -415,16 +538,17 @@ goacc_wait (int async, int num_waits, va
+ launching on, the queue itself will order work as
+ required, so there's no need to wait explicitly. */
+ else
+- acc_dev->openacc.async_wait_async_func (qid, async);
++ acc_wait_async (qid, async);
+ }
+ }
+
+ void
+-GOACC_update (int device, size_t mapnum,
++GOACC_update (int flags_m, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ int async, int num_waits, ...)
+ {
+- bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
++ int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
++
+ size_t i;
+
+ goacc_lazy_initialize ();
+@@ -433,7 +557,7 @@ GOACC_update (int device, size_t mapnum,
+ struct gomp_device_descr *acc_dev = thr->dev;
+
+ if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+- || host_fallback)
++ || (flags & GOACC_FLAG_HOST_FALLBACK))
+ return;
+
+ if (num_waits)
+@@ -447,6 +571,7 @@ GOACC_update (int device, size_t mapnum,
+
+ acc_dev->openacc.async_set_async_func (async);
+
++ bool update_device = false;
+ for (i = 0; i < mapnum; ++i)
+ {
+ unsigned char kind = kinds[i] & 0xff;
+@@ -457,11 +582,46 @@ GOACC_update (int device, size_t mapnum,
+ case GOMP_MAP_TO_PSET:
+ break;
+
++ case GOMP_MAP_ALWAYS_POINTER:
++ if (update_device)
++ {
++ /* Save the contents of the host pointer. */
++ void *dptr = acc_deviceptr (hostaddrs[i-1]);
++ uintptr_t t = *(uintptr_t *) hostaddrs[i];
++
++ /* Update the contents of the host pointer to reflect
++ the value of the allocated device memory in the
++ previous pointer. */
++ *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr;
++ acc_update_device (hostaddrs[i], sizeof (uintptr_t));
++
++ /* Restore the host pointer. */
++ *(uintptr_t *) hostaddrs[i] = t;
++ update_device = false;
++ }
++ break;
++
++ case GOMP_MAP_TO:
++ if (!acc_is_present (hostaddrs[i], sizes[i]))
++ {
++ update_device = false;
++ break;
++ }
++ /* Fallthru */
+ case GOMP_MAP_FORCE_TO:
++ update_device = true;
+ acc_update_device (hostaddrs[i], sizes[i]);
+ break;
+
++ case GOMP_MAP_FROM:
++ if (!acc_is_present (hostaddrs[i], sizes[i]))
++ {
++ update_device = false;
++ break;
++ }
++ /* Fallthru */
+ case GOMP_MAP_FORCE_FROM:
++ update_device = false;
+ acc_update_self (hostaddrs[i], sizes[i]);
+ break;
+
+@@ -487,8 +647,8 @@ GOACC_wait (int async, int num_waits, ..
+ }
+ else if (async == acc_async_sync)
+ acc_wait_all ();
+- else if (async == acc_async_noval)
+- goacc_thread ()->dev->openacc.async_wait_all_async_func (acc_async_noval);
++ else
++ acc_wait_all_async (async);
+ }
+
+ int
+@@ -504,7 +664,7 @@ GOACC_get_thread_num (void)
+ }
+
+ void
+-GOACC_declare (int device, size_t mapnum,
++GOACC_declare (int flags_m, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds)
+ {
+ int i;
+@@ -522,9 +682,10 @@ GOACC_declare (int device, size_t mapnum
+ case GOMP_MAP_FORCE_FROM:
+ case GOMP_MAP_FORCE_TO:
+ case GOMP_MAP_POINTER:
++ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+- &kinds[i], 0, 0);
++ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
++ &kinds[i], GOMP_ASYNC_SYNC, 0);
+ break;
+
+ case GOMP_MAP_FORCE_DEVICEPTR:
+@@ -532,20 +693,19 @@ GOACC_declare (int device, size_t mapnum
+
+ case GOMP_MAP_ALLOC:
+ if (!acc_is_present (hostaddrs[i], sizes[i]))
+- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+- &kinds[i], 0, 0);
++ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
++ &kinds[i], GOMP_ASYNC_SYNC, 0);
+ break;
+
+ case GOMP_MAP_TO:
+- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+- &kinds[i], 0, 0);
++ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
++ &kinds[i], GOMP_ASYNC_SYNC, 0);
+
+ break;
+
+ case GOMP_MAP_FROM:
+- kinds[i] = GOMP_MAP_FORCE_FROM;
+- GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
+- &kinds[i], 0, 0);
++ GOACC_enter_exit_data (flags_m, 1, &hostaddrs[i], &sizes[i],
++ &kinds[i], GOMP_ASYNC_SYNC, 0);
+ break;
+
+ case GOMP_MAP_FORCE_PRESENT:
+--- libgomp/openacc2.f90.jj 2019-05-07 19:54:18.828514375 +0200
++++ libgomp/openacc2.f90 2019-05-07 19:56:38.454296347 +0200
+@@ -0,0 +1,1502 @@
++! OpenACC Runtime Library Definitions.
++
++! Copyright (C) 2014-2019 Free Software Foundation, Inc.
++
++! Contributed by Tobias Burnus
++! and Mentor Embedded.
++
++! This file is part of the GNU Offloading and Multi Processing Library
++! (libgomp).
++
++! Libgomp is free software; you can redistribute it and/or modify it
++! under the terms of the GNU General Public License as published by
++! the Free Software Foundation; either version 3, or (at your option)
++! any later version.
++
++! Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++! FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++! more details.
++
++! Under Section 7 of GPL version 3, you are granted additional
++! permissions described in the GCC Runtime Library Exception, version
++! 3.1, as published by the Free Software Foundation.
++
++! You should have received a copy of the GNU General Public License and
++! a copy of the GCC Runtime Library Exception along with this program;
++! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++! .
++
++module openacc_kinds2
++ use iso_fortran_env, only: int32
++ implicit none
++
++ private :: int32
++ public :: acc_device_kind
++
++ integer, parameter :: acc_device_kind = int32
++
++ public :: acc_device_none, acc_device_default, acc_device_host
++ public :: acc_device_not_host, acc_device_nvidia
++
++ ! Keep in sync with include/gomp-constants.h.
++ integer (acc_device_kind), parameter :: acc_device_none = 0
++ integer (acc_device_kind), parameter :: acc_device_default = 1
++ integer (acc_device_kind), parameter :: acc_device_host = 2
++ ! integer (acc_device_kind), parameter :: acc_device_host_nonshm = 3 removed.
++ integer (acc_device_kind), parameter :: acc_device_not_host = 4
++ integer (acc_device_kind), parameter :: acc_device_nvidia = 5
++
++ public :: acc_handle_kind
++
++ integer, parameter :: acc_handle_kind = int32
++
++ public :: acc_async_noval, acc_async_sync
++
++ ! Keep in sync with include/gomp-constants.h.
++ integer (acc_handle_kind), parameter :: acc_async_noval = -1
++ integer (acc_handle_kind), parameter :: acc_async_sync = -2
++
++end module
++
++module openacc_internal2
++ use openacc_kinds2
++ implicit none
++
++ interface
++ function acc_get_num_devices_h (d)
++ import
++ integer acc_get_num_devices_h
++ integer (acc_device_kind) d
++ end function
++
++ subroutine acc_set_device_type_h (d)
++ import
++ integer (acc_device_kind) d
++ end subroutine
++
++ function acc_get_device_type_h ()
++ import
++ integer (acc_device_kind) acc_get_device_type_h
++ end function
++
++ subroutine acc_set_device_num_h (n, d)
++ import
++ integer n
++ integer (acc_device_kind) d
++ end subroutine
++
++ function acc_get_device_num_h (d)
++ import
++ integer acc_get_device_num_h
++ integer (acc_device_kind) d
++ end function
++
++ function acc_async_test_h (a)
++ logical acc_async_test_h
++ integer a
++ end function
++
++ function acc_async_test_all_h ()
++ logical acc_async_test_all_h
++ end function
++
++ subroutine acc_wait_h (a)
++ integer a
++ end subroutine
++
++ subroutine acc_wait_async_h (a1, a2)
++ integer a1, a2
++ end subroutine
++
++ subroutine acc_wait_all_h ()
++ end subroutine
++
++ subroutine acc_wait_all_async_h (a)
++ integer a
++ end subroutine
++
++ subroutine acc_init_h (d)
++ import
++ integer (acc_device_kind) d
++ end subroutine
++
++ subroutine acc_shutdown_h (d)
++ import
++ integer (acc_device_kind) d
++ end subroutine
++
++ function acc_on_device_h (d)
++ import
++ integer (acc_device_kind) d
++ logical acc_on_device_h
++ end function
++
++ subroutine acc_copyin_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_copyin_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_copyin_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_present_or_copyin_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_present_or_copyin_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_present_or_copyin_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_create_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_create_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_create_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_present_or_create_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_present_or_create_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_present_or_create_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_copyout_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_copyout_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_copyout_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_copyout_finalize_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_copyout_finalize_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_copyout_finalize_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_delete_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_delete_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_delete_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_delete_finalize_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_delete_finalize_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_delete_finalize_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_update_device_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_update_device_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_update_device_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ subroutine acc_update_self_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end subroutine
++
++ subroutine acc_update_self_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end subroutine
++
++ subroutine acc_update_self_array_h (a)
++ type (*), dimension (..), contiguous :: a
++ end subroutine
++
++ function acc_is_present_32_h (a, len)
++ use iso_c_binding, only: c_int32_t
++ logical acc_is_present_32_h
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ end function
++
++ function acc_is_present_64_h (a, len)
++ use iso_c_binding, only: c_int64_t
++ logical acc_is_present_64_h
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ end function
++
++ function acc_is_present_array_h (a)
++ logical acc_is_present_array_h
++ type (*), dimension (..), contiguous :: a
++ end function
++
++ subroutine acc_copyin_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_copyin_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_copyin_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_create_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_create_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_create_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_copyout_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_copyout_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_copyout_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_delete_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_delete_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_delete_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_device_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_device_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_device_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_self_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_self_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ end subroutine
++
++ subroutine acc_update_self_async_array_h (a, async)
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ end subroutine
++ end interface
++
++ interface
++ function acc_get_num_devices_l (d) &
++ bind (C, name = "acc_get_num_devices")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_get_num_devices_l
++ integer (c_int), value :: d
++ end function
++
++ subroutine acc_set_device_type_l (d) &
++ bind (C, name = "acc_set_device_type")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: d
++ end subroutine
++
++ function acc_get_device_type_l () &
++ bind (C, name = "acc_get_device_type")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_get_device_type_l
++ end function
++
++ subroutine acc_set_device_num_l (n, d) &
++ bind (C, name = "acc_set_device_num")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: n, d
++ end subroutine
++
++ function acc_get_device_num_l (d) &
++ bind (C, name = "acc_get_device_num")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_get_device_num_l
++ integer (c_int), value :: d
++ end function
++
++ function acc_async_test_l (a) &
++ bind (C, name = "acc_async_test")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_async_test_l
++ integer (c_int), value :: a
++ end function
++
++ function acc_async_test_all_l () &
++ bind (C, name = "acc_async_test_all")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_async_test_all_l
++ end function
++
++ subroutine acc_wait_l (a) &
++ bind (C, name = "acc_wait")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: a
++ end subroutine
++
++ subroutine acc_wait_async_l (a1, a2) &
++ bind (C, name = "acc_wait_async")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: a1, a2
++ end subroutine
++
++ subroutine acc_wait_all_l () &
++ bind (C, name = "acc_wait_all")
++ use iso_c_binding, only: c_int
++ end subroutine
++
++ subroutine acc_wait_all_async_l (a) &
++ bind (C, name = "acc_wait_all_async")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: a
++ end subroutine
++
++ subroutine acc_init_l (d) &
++ bind (C, name = "acc_init")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: d
++ end subroutine
++
++ subroutine acc_shutdown_l (d) &
++ bind (C, name = "acc_shutdown")
++ use iso_c_binding, only: c_int
++ integer (c_int), value :: d
++ end subroutine
++
++ function acc_on_device_l (d) &
++ bind (C, name = "acc_on_device")
++ use iso_c_binding, only: c_int
++ integer (c_int) :: acc_on_device_l
++ integer (c_int), value :: d
++ end function
++
++ subroutine acc_copyin_l (a, len) &
++ bind (C, name = "acc_copyin")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_present_or_copyin_l (a, len) &
++ bind (C, name = "acc_present_or_copyin")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_create_l (a, len) &
++ bind (C, name = "acc_create")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_present_or_create_l (a, len) &
++ bind (C, name = "acc_present_or_create")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_copyout_l (a, len) &
++ bind (C, name = "acc_copyout")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_copyout_finalize_l (a, len) &
++ bind (C, name = "acc_copyout_finalize")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_delete_l (a, len) &
++ bind (C, name = "acc_delete")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_delete_finalize_l (a, len) &
++ bind (C, name = "acc_delete_finalize")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_update_device_l (a, len) &
++ bind (C, name = "acc_update_device")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ subroutine acc_update_self_l (a, len) &
++ bind (C, name = "acc_update_self")
++ use iso_c_binding, only: c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end subroutine
++
++ function acc_is_present_l (a, len) &
++ bind (C, name = "acc_is_present")
++ use iso_c_binding, only: c_int32_t, c_size_t
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ integer (c_int32_t) :: acc_is_present_l
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ end function
++
++ subroutine acc_copyin_async_l (a, len, async) &
++ bind (C, name = "acc_copyin_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++
++ subroutine acc_create_async_l (a, len, async) &
++ bind (C, name = "acc_create_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++
++ subroutine acc_copyout_async_l (a, len, async) &
++ bind (C, name = "acc_copyout_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++
++ subroutine acc_delete_async_l (a, len, async) &
++ bind (C, name = "acc_delete_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++
++ subroutine acc_update_device_async_l (a, len, async) &
++ bind (C, name = "acc_update_device_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++
++ subroutine acc_update_self_async_l (a, len, async) &
++ bind (C, name = "acc_update_self_async")
++ use iso_c_binding, only: c_size_t, c_int
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_size_t), value :: len
++ integer (c_int), value :: async
++ end subroutine
++ end interface
++end module
++
++module openacc2
++ use openacc_kinds2
++ use openacc_internal2
++ implicit none
++
++ public :: openacc_version
++
++ public :: acc_get_num_devices, acc_set_device_type, acc_get_device_type
++ public :: acc_set_device_num, acc_get_device_num, acc_async_test
++ public :: acc_async_test_all
++ public :: acc_wait, acc_async_wait, acc_wait_async
++ public :: acc_wait_all, acc_async_wait_all, acc_wait_all_async
++ public :: acc_init, acc_shutdown, acc_on_device
++ public :: acc_copyin, acc_present_or_copyin, acc_pcopyin, acc_create
++ public :: acc_present_or_create, acc_pcreate, acc_copyout, acc_delete
++ public :: acc_update_device, acc_update_self, acc_is_present
++ public :: acc_copyin_async, acc_create_async, acc_copyout_async
++ public :: acc_delete_async, acc_update_device_async, acc_update_self_async
++
++ integer, parameter :: openacc_version = 201306
++
++ interface acc_get_num_devices
++ procedure :: acc_get_num_devices_h
++ end interface
++
++ interface acc_set_device_type
++ procedure :: acc_set_device_type_h
++ end interface
++
++ interface acc_get_device_type
++ procedure :: acc_get_device_type_h
++ end interface
++
++ interface acc_set_device_num
++ procedure :: acc_set_device_num_h
++ end interface
++
++ interface acc_get_device_num
++ procedure :: acc_get_device_num_h
++ end interface
++
++ interface acc_async_test
++ procedure :: acc_async_test_h
++ end interface
++
++ interface acc_async_test_all
++ procedure :: acc_async_test_all_h
++ end interface
++
++ interface acc_wait
++ procedure :: acc_wait_h
++ end interface
++
++ ! acc_async_wait is an OpenACC 1.0 compatibility name for acc_wait.
++ interface acc_async_wait
++ procedure :: acc_wait_h
++ end interface
++
++ interface acc_wait_async
++ procedure :: acc_wait_async_h
++ end interface
++
++ interface acc_wait_all
++ procedure :: acc_wait_all_h
++ end interface
++
++ ! acc_async_wait_all is an OpenACC 1.0 compatibility name for acc_wait_all.
++ interface acc_async_wait_all
++ procedure :: acc_wait_all_h
++ end interface
++
++ interface acc_wait_all_async
++ procedure :: acc_wait_all_async_h
++ end interface
++
++ interface acc_init
++ procedure :: acc_init_h
++ end interface
++
++ interface acc_shutdown
++ procedure :: acc_shutdown_h
++ end interface
++
++ interface acc_on_device
++ procedure :: acc_on_device_h
++ end interface
++
++ ! acc_malloc: Only available in C/C++
++ ! acc_free: Only available in C/C++
++
++ ! As vendor extension, the following code supports both 32bit and 64bit
++ ! arguments for "size"; the OpenACC standard only permits default-kind
++ ! integers, which are of kind 4 (i.e. 32 bits).
++ ! Additionally, the two-argument version also takes arrays as argument.
++ ! and the one argument version also scalars. Note that the code assumes
++ ! that the arrays are contiguous.
++
++ interface acc_copyin
++ procedure :: acc_copyin_32_h
++ procedure :: acc_copyin_64_h
++ procedure :: acc_copyin_array_h
++ end interface
++
++ interface acc_present_or_copyin
++ procedure :: acc_present_or_copyin_32_h
++ procedure :: acc_present_or_copyin_64_h
++ procedure :: acc_present_or_copyin_array_h
++ end interface
++
++ interface acc_pcopyin
++ procedure :: acc_present_or_copyin_32_h
++ procedure :: acc_present_or_copyin_64_h
++ procedure :: acc_present_or_copyin_array_h
++ end interface
++
++ interface acc_create
++ procedure :: acc_create_32_h
++ procedure :: acc_create_64_h
++ procedure :: acc_create_array_h
++ end interface
++
++ interface acc_present_or_create
++ procedure :: acc_present_or_create_32_h
++ procedure :: acc_present_or_create_64_h
++ procedure :: acc_present_or_create_array_h
++ end interface
++
++ interface acc_pcreate
++ procedure :: acc_present_or_create_32_h
++ procedure :: acc_present_or_create_64_h
++ procedure :: acc_present_or_create_array_h
++ end interface
++
++ interface acc_copyout
++ procedure :: acc_copyout_32_h
++ procedure :: acc_copyout_64_h
++ procedure :: acc_copyout_array_h
++ end interface
++
++ interface acc_copyout_finalize
++ procedure :: acc_copyout_finalize_32_h
++ procedure :: acc_copyout_finalize_64_h
++ procedure :: acc_copyout_finalize_array_h
++ end interface
++
++ interface acc_delete
++ procedure :: acc_delete_32_h
++ procedure :: acc_delete_64_h
++ procedure :: acc_delete_array_h
++ end interface
++
++ interface acc_delete_finalize
++ procedure :: acc_delete_finalize_32_h
++ procedure :: acc_delete_finalize_64_h
++ procedure :: acc_delete_finalize_array_h
++ end interface
++
++ interface acc_update_device
++ procedure :: acc_update_device_32_h
++ procedure :: acc_update_device_64_h
++ procedure :: acc_update_device_array_h
++ end interface
++
++ interface acc_update_self
++ procedure :: acc_update_self_32_h
++ procedure :: acc_update_self_64_h
++ procedure :: acc_update_self_array_h
++ end interface
++
++ ! acc_map_data: Only available in C/C++
++ ! acc_unmap_data: Only available in C/C++
++ ! acc_deviceptr: Only available in C/C++
++ ! acc_hostptr: Only available in C/C++
++
++ interface acc_is_present
++ procedure :: acc_is_present_32_h
++ procedure :: acc_is_present_64_h
++ procedure :: acc_is_present_array_h
++ end interface
++
++ ! acc_memcpy_to_device: Only available in C/C++
++ ! acc_memcpy_from_device: Only available in C/C++
++
++ interface acc_copyin_async
++ procedure :: acc_copyin_async_32_h
++ procedure :: acc_copyin_async_64_h
++ procedure :: acc_copyin_async_array_h
++ end interface
++
++ interface acc_create_async
++ procedure :: acc_create_async_32_h
++ procedure :: acc_create_async_64_h
++ procedure :: acc_create_async_array_h
++ end interface
++
++ interface acc_copyout_async
++ procedure :: acc_copyout_async_32_h
++ procedure :: acc_copyout_async_64_h
++ procedure :: acc_copyout_async_array_h
++ end interface
++
++ interface acc_delete_async
++ procedure :: acc_delete_async_32_h
++ procedure :: acc_delete_async_64_h
++ procedure :: acc_delete_async_array_h
++ end interface
++
++ interface acc_update_device_async
++ procedure :: acc_update_device_async_32_h
++ procedure :: acc_update_device_async_64_h
++ procedure :: acc_update_device_async_array_h
++ end interface
++
++ interface acc_update_self_async
++ procedure :: acc_update_self_async_32_h
++ procedure :: acc_update_self_async_64_h
++ procedure :: acc_update_self_async_array_h
++ end interface
++
++end module
++
++function acc_get_num_devices_h (d)
++ use openacc_internal2, only: acc_get_num_devices_l
++ use openacc_kinds2
++ integer acc_get_num_devices_h
++ integer (acc_device_kind) d
++ acc_get_num_devices_h = acc_get_num_devices_l (d)
++end function
++
++subroutine acc_set_device_type_h (d)
++ use openacc_internal2, only: acc_set_device_type_l
++ use openacc_kinds2
++ integer (acc_device_kind) d
++ call acc_set_device_type_l (d)
++end subroutine
++
++function acc_get_device_type_h ()
++ use openacc_internal2, only: acc_get_device_type_l
++ use openacc_kinds2
++ integer (acc_device_kind) acc_get_device_type_h
++ acc_get_device_type_h = acc_get_device_type_l ()
++end function
++
++subroutine acc_set_device_num_h (n, d)
++ use openacc_internal2, only: acc_set_device_num_l
++ use openacc_kinds2
++ integer n
++ integer (acc_device_kind) d
++ call acc_set_device_num_l (n, d)
++end subroutine
++
++function acc_get_device_num_h (d)
++ use openacc_internal2, only: acc_get_device_num_l
++ use openacc_kinds2
++ integer acc_get_device_num_h
++ integer (acc_device_kind) d
++ acc_get_device_num_h = acc_get_device_num_l (d)
++end function
++
++function acc_async_test_h (a)
++ use openacc_internal2, only: acc_async_test_l
++ logical acc_async_test_h
++ integer a
++ if (acc_async_test_l (a) .eq. 1) then
++ acc_async_test_h = .TRUE.
++ else
++ acc_async_test_h = .FALSE.
++ end if
++end function
++
++function acc_async_test_all_h ()
++ use openacc_internal2, only: acc_async_test_all_l
++ logical acc_async_test_all_h
++ if (acc_async_test_all_l () .eq. 1) then
++ acc_async_test_all_h = .TRUE.
++ else
++ acc_async_test_all_h = .FALSE.
++ end if
++end function
++
++subroutine acc_wait_h (a)
++ use openacc_internal2, only: acc_wait_l
++ integer a
++ call acc_wait_l (a)
++end subroutine
++
++subroutine acc_wait_async_h (a1, a2)
++ use openacc_internal2, only: acc_wait_async_l
++ integer a1, a2
++ call acc_wait_async_l (a1, a2)
++end subroutine
++
++subroutine acc_wait_all_h ()
++ use openacc_internal2, only: acc_wait_all_l
++ call acc_wait_all_l ()
++end subroutine
++
++subroutine acc_wait_all_async_h (a)
++ use openacc_internal2, only: acc_wait_all_async_l
++ integer a
++ call acc_wait_all_async_l (a)
++end subroutine
++
++subroutine acc_init_h (d)
++ use openacc_internal2, only: acc_init_l
++ use openacc_kinds2
++ integer (acc_device_kind) d
++ call acc_init_l (d)
++end subroutine
++
++subroutine acc_shutdown_h (d)
++ use openacc_internal2, only: acc_shutdown_l
++ use openacc_kinds2
++ integer (acc_device_kind) d
++ call acc_shutdown_l (d)
++end subroutine
++
++function acc_on_device_h (d)
++ use openacc_internal2, only: acc_on_device_l
++ use openacc_kinds2
++ integer (acc_device_kind) d
++ logical acc_on_device_h
++ if (acc_on_device_l (d) .eq. 1) then
++ acc_on_device_h = .TRUE.
++ else
++ acc_on_device_h = .FALSE.
++ end if
++end function
++
++subroutine acc_copyin_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_copyin_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_copyin_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyin_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_copyin_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_copyin_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyin_array_h (a)
++ use openacc_internal2, only: acc_copyin_l
++ type (*), dimension (..), contiguous :: a
++ call acc_copyin_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_present_or_copyin_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_present_or_copyin_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_present_or_copyin_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_present_or_copyin_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_present_or_copyin_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_present_or_copyin_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_present_or_copyin_array_h (a)
++ use openacc_internal2, only: acc_present_or_copyin_l
++ type (*), dimension (..), contiguous :: a
++ call acc_present_or_copyin_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_create_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_create_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_create_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_create_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_create_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_create_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_create_array_h (a)
++ use openacc_internal2, only: acc_create_l
++ type (*), dimension (..), contiguous :: a
++ call acc_create_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_present_or_create_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_present_or_create_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_present_or_create_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_present_or_create_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_present_or_create_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_present_or_create_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_present_or_create_array_h (a)
++ use openacc_internal2, only: acc_present_or_create_l
++ type (*), dimension (..), contiguous :: a
++ call acc_present_or_create_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_copyout_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_copyout_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_copyout_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyout_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_copyout_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_copyout_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyout_array_h (a)
++ use openacc_internal2, only: acc_copyout_l
++ type (*), dimension (..), contiguous :: a
++ call acc_copyout_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_copyout_finalize_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_copyout_finalize_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_copyout_finalize_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyout_finalize_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_copyout_finalize_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_copyout_finalize_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_copyout_finalize_array_h (a)
++ use openacc_internal2, only: acc_copyout_finalize_l
++ type (*), dimension (..), contiguous :: a
++ call acc_copyout_finalize_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_delete_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_delete_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_delete_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_delete_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_delete_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_delete_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_delete_array_h (a)
++ use openacc_internal2, only: acc_delete_l
++ type (*), dimension (..), contiguous :: a
++ call acc_delete_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_delete_finalize_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_delete_finalize_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_delete_finalize_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_delete_finalize_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_delete_finalize_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_delete_finalize_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_delete_finalize_array_h (a)
++ use openacc_internal2, only: acc_delete_finalize_l
++ type (*), dimension (..), contiguous :: a
++ call acc_delete_finalize_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_update_device_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_update_device_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_update_device_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_update_device_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_update_device_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_update_device_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_update_device_array_h (a)
++ use openacc_internal2, only: acc_update_device_l
++ type (*), dimension (..), contiguous :: a
++ call acc_update_device_l (a, sizeof (a))
++end subroutine
++
++subroutine acc_update_self_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_update_self_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ call acc_update_self_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_update_self_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_update_self_l
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ call acc_update_self_l (a, int (len, kind = c_size_t))
++end subroutine
++
++subroutine acc_update_self_array_h (a)
++ use openacc_internal2, only: acc_update_self_l
++ type (*), dimension (..), contiguous :: a
++ call acc_update_self_l (a, sizeof (a))
++end subroutine
++
++function acc_is_present_32_h (a, len)
++ use iso_c_binding, only: c_int32_t, c_size_t
++ use openacc_internal2, only: acc_is_present_l
++ logical acc_is_present_32_h
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ if (acc_is_present_l (a, int (len, kind = c_size_t)) .eq. 1) then
++ acc_is_present_32_h = .TRUE.
++ else
++ acc_is_present_32_h = .FALSE.
++ end if
++end function
++
++function acc_is_present_64_h (a, len)
++ use iso_c_binding, only: c_int64_t, c_size_t
++ use openacc_internal2, only: acc_is_present_l
++ logical acc_is_present_64_h
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ if (acc_is_present_l (a, int (len, kind = c_size_t)) .eq. 1) then
++ acc_is_present_64_h = .TRUE.
++ else
++ acc_is_present_64_h = .FALSE.
++ end if
++end function
++
++function acc_is_present_array_h (a)
++ use openacc_internal2, only: acc_is_present_l
++ logical acc_is_present_array_h
++ type (*), dimension (..), contiguous :: a
++ acc_is_present_array_h = acc_is_present_l (a, sizeof (a)) == 1
++end function
++
++subroutine acc_copyin_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_copyin_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_copyin_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_copyin_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_copyin_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_copyin_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_copyin_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_copyin_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_copyin_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_create_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_create_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_create_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_create_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_create_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_create_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_create_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_create_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_create_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_copyout_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_copyout_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_copyout_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_copyout_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_copyout_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_copyout_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_copyout_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_copyout_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_copyout_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_delete_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_delete_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_delete_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_delete_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_delete_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_delete_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_delete_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_delete_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_delete_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_device_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_update_device_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_update_device_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_device_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_update_device_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_update_device_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_device_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_update_device_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_update_device_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_self_async_32_h (a, len, async)
++ use iso_c_binding, only: c_int32_t, c_size_t, c_int
++ use openacc_internal2, only: acc_update_self_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int32_t) len
++ integer (acc_handle_kind) async
++ call acc_update_self_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_self_async_64_h (a, len, async)
++ use iso_c_binding, only: c_int64_t, c_size_t, c_int
++ use openacc_internal2, only: acc_update_self_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ !GCC$ ATTRIBUTES NO_ARG_CHECK :: a
++ type (*), dimension (*) :: a
++ integer (c_int64_t) len
++ integer (acc_handle_kind) async
++ call acc_update_self_async_l (a, int (len, kind = c_size_t), int (async, kind = c_int))
++end subroutine
++
++subroutine acc_update_self_async_array_h (a, async)
++ use iso_c_binding, only: c_int
++ use openacc_internal2, only: acc_update_self_async_l
++ use openacc_kinds2, only: acc_handle_kind
++ type (*), dimension (..), contiguous :: a
++ integer (acc_handle_kind) async
++ call acc_update_self_async_l (a, sizeof (a), int (async, kind = c_int))
++end subroutine
+--- libgomp/taskloop.c.jj 2018-04-25 09:40:31.913655581 +0200
++++ libgomp/taskloop.c 2019-05-07 18:46:36.547109400 +0200
+@@ -149,11 +149,28 @@ GOMP_taskloop (void (*fn) (void *), void
+
+ if (flags & GOMP_TASK_FLAG_NOGROUP)
+ {
+- if (thr->task && thr->task->taskgroup && thr->task->taskgroup->cancelled)
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0)
++ && thr->task
++ && thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
+ }
+ else
+- ialias_call (GOMP_taskgroup_start) ();
++ {
++ ialias_call (GOMP_taskgroup_start) ();
++ if (flags & GOMP_TASK_FLAG_REDUCTION)
++ {
++ struct gomp_data_head { TYPE t1, t2; uintptr_t *ptr; };
++ uintptr_t *ptr = ((struct gomp_data_head *) data)->ptr;
++ ialias_call (GOMP_taskgroup_reduction_register) (ptr);
++ }
++ }
+
+ if (priority > gomp_max_task_priority_var)
+ priority = gomp_max_task_priority_var;
+@@ -284,19 +301,31 @@ GOMP_taskloop (void (*fn) (void *), void
+ gomp_mutex_lock (&team->task_lock);
+ /* If parallel or taskgroup has been cancelled, don't start new
+ tasks. */
+- if (__builtin_expect ((gomp_team_barrier_cancelled (&team->barrier)
+- || (taskgroup && taskgroup->cancelled))
+- && cpyfn == NULL, 0))
++ if (__builtin_expect (gomp_cancel_var, 0)
++ && cpyfn == NULL)
+ {
+- gomp_mutex_unlock (&team->task_lock);
+- for (i = 0; i < num_tasks; i++)
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ {
++ do_cancel:
++ gomp_mutex_unlock (&team->task_lock);
++ for (i = 0; i < num_tasks; i++)
++ {
++ gomp_finish_task (tasks[i]);
++ free (tasks[i]);
++ }
++ if ((flags & GOMP_TASK_FLAG_NOGROUP) == 0)
++ ialias_call (GOMP_taskgroup_end) ();
++ return;
++ }
++ if (taskgroup)
+ {
+- gomp_finish_task (tasks[i]);
+- free (tasks[i]);
++ if (taskgroup->cancelled)
++ goto do_cancel;
++ if (taskgroup->workshare
++ && taskgroup->prev
++ && taskgroup->prev->cancelled)
++ goto do_cancel;
+ }
+- if ((flags & GOMP_TASK_FLAG_NOGROUP) == 0)
+- ialias_call (GOMP_taskgroup_end) ();
+- return;
+ }
+ if (taskgroup)
+ taskgroup->num_children += num_tasks;
+--- libgomp/parallel.c.jj 2018-04-25 09:40:31.926655587 +0200
++++ libgomp/parallel.c 2019-05-07 18:46:36.532109640 +0200
+@@ -123,7 +123,8 @@ void
+ GOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads)
+ {
+ num_threads = gomp_resolve_num_threads (num_threads, 0);
+- gomp_team_start (fn, data, num_threads, 0, gomp_new_team (num_threads));
++ gomp_team_start (fn, data, num_threads, 0, gomp_new_team (num_threads),
++ NULL);
+ }
+
+ void
+@@ -161,14 +162,33 @@ GOMP_parallel_end (void)
+ ialias (GOMP_parallel_end)
+
+ void
+-GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, unsigned int flags)
++GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads,
++ unsigned int flags)
+ {
+ num_threads = gomp_resolve_num_threads (num_threads, 0);
+- gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads));
++ gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads),
++ NULL);
+ fn (data);
+ ialias_call (GOMP_parallel_end) ();
+ }
+
++unsigned
++GOMP_parallel_reductions (void (*fn) (void *), void *data,
++ unsigned num_threads, unsigned int flags)
++{
++ struct gomp_taskgroup *taskgroup;
++ num_threads = gomp_resolve_num_threads (num_threads, 0);
++ uintptr_t *rdata = *(uintptr_t **)data;
++ taskgroup = gomp_parallel_reduction_register (rdata, num_threads);
++ gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads),
++ taskgroup);
++ fn (data);
++ ialias_call (GOMP_parallel_end) ();
++ gomp_sem_destroy (&taskgroup->taskgroup_sem);
++ free (taskgroup);
++ return num_threads;
++}
++
+ bool
+ GOMP_cancellation_point (int which)
+ {
+@@ -185,8 +205,15 @@ GOMP_cancellation_point (int which)
+ }
+ else if (which & GOMP_CANCEL_TASKGROUP)
+ {
+- if (thr->task->taskgroup && thr->task->taskgroup->cancelled)
+- return true;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return true;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return true;
++ }
+ /* FALLTHRU into the GOMP_CANCEL_PARALLEL case,
+ as #pragma omp cancel parallel also cancels all explicit
+ tasks. */
+@@ -218,11 +245,17 @@ GOMP_cancel (int which, bool do_cancel)
+ }
+ else if (which & GOMP_CANCEL_TASKGROUP)
+ {
+- if (thr->task->taskgroup && !thr->task->taskgroup->cancelled)
++ if (thr->task->taskgroup)
+ {
+- gomp_mutex_lock (&team->task_lock);
+- thr->task->taskgroup->cancelled = true;
+- gomp_mutex_unlock (&team->task_lock);
++ struct gomp_taskgroup *taskgroup = thr->task->taskgroup;
++ if (taskgroup->workshare && taskgroup->prev)
++ taskgroup = taskgroup->prev;
++ if (!taskgroup->cancelled)
++ {
++ gomp_mutex_lock (&team->task_lock);
++ taskgroup->cancelled = true;
++ gomp_mutex_unlock (&team->task_lock);
++ }
+ }
+ return true;
+ }
+--- libgomp/oacc-plugin.h.jj 2018-04-25 09:40:31.322655307 +0200
++++ libgomp/oacc-plugin.h 2019-05-07 18:46:36.531109656 +0200
+@@ -29,5 +29,6 @@
+
+ extern void GOMP_PLUGIN_async_unmap_vars (void *, int);
+ extern void *GOMP_PLUGIN_acc_thread (void);
++extern int GOMP_PLUGIN_acc_default_dim (unsigned int);
+
+ #endif
+--- libgomp/target.c.jj 2018-04-25 09:40:31.912655580 +0200
++++ libgomp/target.c 2019-05-07 19:07:21.032306327 +0200
+@@ -180,16 +180,22 @@ gomp_device_copy (struct gomp_device_des
+ /* Infrastructure for coalescing adjacent or nearly adjacent (in device addresses)
+ host to device memory transfers. */
+
++struct gomp_coalesce_chunk
++{
++ /* The starting and ending point of a coalesced chunk of memory. */
++ size_t start, end;
++};
++
+ struct gomp_coalesce_buf
+ {
+ /* Buffer into which gomp_copy_host2dev will memcpy data and from which
+ it will be copied to the device. */
+ void *buf;
+ struct target_mem_desc *tgt;
+- /* Array with offsets, chunks[2 * i] is the starting offset and
+- chunks[2 * i + 1] ending offset relative to tgt->tgt_start device address
++ /* Array with offsets, chunks[i].start is the starting offset and
++ chunks[i].end ending offset relative to tgt->tgt_start device address
+ of chunks which are to be copied to buf and later copied to device. */
+- size_t *chunks;
++ struct gomp_coalesce_chunk *chunks;
+ /* Number of chunks in chunks array, or -1 if coalesce buffering should not
+ be performed. */
+ long chunk_cnt;
+@@ -222,14 +228,14 @@ gomp_coalesce_buf_add (struct gomp_coale
+ {
+ if (cbuf->chunk_cnt < 0)
+ return;
+- if (start < cbuf->chunks[2 * cbuf->chunk_cnt - 1])
++ if (start < cbuf->chunks[cbuf->chunk_cnt - 1].end)
+ {
+ cbuf->chunk_cnt = -1;
+ return;
+ }
+- if (start < cbuf->chunks[2 * cbuf->chunk_cnt - 1] + MAX_COALESCE_BUF_GAP)
++ if (start < cbuf->chunks[cbuf->chunk_cnt - 1].end + MAX_COALESCE_BUF_GAP)
+ {
+- cbuf->chunks[2 * cbuf->chunk_cnt - 1] = start + len;
++ cbuf->chunks[cbuf->chunk_cnt - 1].end = start + len;
+ cbuf->use_cnt++;
+ return;
+ }
+@@ -239,8 +245,8 @@ gomp_coalesce_buf_add (struct gomp_coale
+ if (cbuf->use_cnt == 1)
+ cbuf->chunk_cnt--;
+ }
+- cbuf->chunks[2 * cbuf->chunk_cnt] = start;
+- cbuf->chunks[2 * cbuf->chunk_cnt + 1] = start + len;
++ cbuf->chunks[cbuf->chunk_cnt].start = start;
++ cbuf->chunks[cbuf->chunk_cnt].end = start + len;
+ cbuf->chunk_cnt++;
+ cbuf->use_cnt = 1;
+ }
+@@ -271,20 +277,20 @@ gomp_copy_host2dev (struct gomp_device_d
+ if (cbuf)
+ {
+ uintptr_t doff = (uintptr_t) d - cbuf->tgt->tgt_start;
+- if (doff < cbuf->chunks[2 * cbuf->chunk_cnt - 1])
++ if (doff < cbuf->chunks[cbuf->chunk_cnt - 1].end)
+ {
+ long first = 0;
+ long last = cbuf->chunk_cnt - 1;
+ while (first <= last)
+ {
+ long middle = (first + last) >> 1;
+- if (cbuf->chunks[2 * middle + 1] <= doff)
++ if (cbuf->chunks[middle].end <= doff)
+ first = middle + 1;
+- else if (cbuf->chunks[2 * middle] <= doff)
++ else if (cbuf->chunks[middle].start <= doff)
+ {
+- if (doff + sz > cbuf->chunks[2 * middle + 1])
++ if (doff + sz > cbuf->chunks[middle].end)
+ gomp_fatal ("internal libgomp cbuf error");
+- memcpy ((char *) cbuf->buf + (doff - cbuf->chunks[0]),
++ memcpy ((char *) cbuf->buf + (doff - cbuf->chunks[0].start),
+ h, sz);
+ return;
+ }
+@@ -510,8 +516,8 @@ gomp_map_vars (struct gomp_device_descr
+ cbuf.buf = NULL;
+ if (mapnum > 1 || pragma_kind == GOMP_MAP_VARS_TARGET)
+ {
+- cbuf.chunks
+- = (size_t *) gomp_alloca ((2 * mapnum + 2) * sizeof (size_t));
++ size_t chunks_size = (mapnum + 1) * sizeof (struct gomp_coalesce_chunk);
++ cbuf.chunks = (struct gomp_coalesce_chunk *) gomp_alloca (chunks_size);
+ cbuf.chunk_cnt = 0;
+ }
+ if (pragma_kind == GOMP_MAP_VARS_TARGET)
+@@ -521,8 +527,8 @@ gomp_map_vars (struct gomp_device_descr
+ tgt_size = mapnum * sizeof (void *);
+ cbuf.chunk_cnt = 1;
+ cbuf.use_cnt = 1 + (mapnum > 1);
+- cbuf.chunks[0] = 0;
+- cbuf.chunks[1] = tgt_size;
++ cbuf.chunks[0].start = 0;
++ cbuf.chunks[0].end = tgt_size;
+ }
+
+ gomp_mutex_lock (&devicep->lock);
+@@ -707,7 +713,7 @@ gomp_map_vars (struct gomp_device_descr
+ if (cbuf.chunk_cnt > 0)
+ {
+ cbuf.buf
+- = malloc (cbuf.chunks[2 * cbuf.chunk_cnt - 1] - cbuf.chunks[0]);
++ = malloc (cbuf.chunks[cbuf.chunk_cnt - 1].end - cbuf.chunks[0].start);
+ if (cbuf.buf)
+ {
+ cbuf.tgt = tgt;
+@@ -859,6 +865,7 @@ gomp_map_vars (struct gomp_device_descr
+ tgt->list[i].offset = 0;
+ tgt->list[i].length = k->host_end - k->host_start;
+ k->refcount = 1;
++ k->dynamic_refcount = 0;
+ tgt->refcount++;
+ array->left = NULL;
+ array->right = NULL;
+@@ -956,9 +963,10 @@ gomp_map_vars (struct gomp_device_descr
+ /* Set link pointer on target to the device address of the
+ mapped object. */
+ void *tgt_addr = (void *) (tgt->tgt_start + k->tgt_offset);
+- devicep->host2dev_func (devicep->target_id,
+- (void *) n->tgt_offset,
+- &tgt_addr, sizeof (void *));
++ /* We intentionally do not use coalescing here, as it's not
++ data allocated by the current call to this function. */
++ gomp_copy_host2dev (devicep, (void *) n->tgt_offset,
++ &tgt_addr, sizeof (void *), NULL);
+ }
+ array++;
+ }
+@@ -981,10 +989,14 @@ gomp_map_vars (struct gomp_device_descr
+ {
+ long c = 0;
+ for (c = 0; c < cbuf.chunk_cnt; ++c)
+- gomp_copy_host2dev (devicep, (void *) (tgt->tgt_start + cbuf.chunks[2 * c]),
+- (char *) cbuf.buf + (cbuf.chunks[2 * c] - cbuf.chunks[0]),
+- cbuf.chunks[2 * c + 1] - cbuf.chunks[2 * c], NULL);
++ gomp_copy_host2dev (devicep,
++ (void *) (tgt->tgt_start + cbuf.chunks[c].start),
++ (char *) cbuf.buf + (cbuf.chunks[c].start
++ - cbuf.chunks[0].start),
++ cbuf.chunks[c].end - cbuf.chunks[c].start, NULL);
+ free (cbuf.buf);
++ cbuf.buf = NULL;
++ cbufp = NULL;
+ }
+
+ /* If the variable from "omp target enter data" map-list was already mapped,
+@@ -1011,6 +1023,23 @@ gomp_unmap_tgt (struct target_mem_desc *
+ free (tgt);
+ }
+
++attribute_hidden bool
++gomp_remove_var (struct gomp_device_descr *devicep, splay_tree_key k)
++{
++ bool is_tgt_unmapped = false;
++ splay_tree_remove (&devicep->mem_map, k);
++ if (k->link_key)
++ splay_tree_insert (&devicep->mem_map, (splay_tree_node) k->link_key);
++ if (k->tgt->refcount > 1)
++ k->tgt->refcount--;
++ else
++ {
++ is_tgt_unmapped = true;
++ gomp_unmap_tgt (k->tgt);
++ }
++ return is_tgt_unmapped;
++}
++
+ /* Unmap variables described by TGT. If DO_COPYFROM is true, copy relevant
+ variables back from device to host: if it is false, it is assumed that this
+ has been done already. */
+@@ -1059,16 +1088,7 @@ gomp_unmap_vars (struct target_mem_desc
+ + tgt->list[i].offset),
+ tgt->list[i].length);
+ if (do_unmap)
+- {
+- splay_tree_remove (&devicep->mem_map, k);
+- if (k->link_key)
+- splay_tree_insert (&devicep->mem_map,
+- (splay_tree_node) k->link_key);
+- if (k->tgt->refcount > 1)
+- k->tgt->refcount--;
+- else
+- gomp_unmap_tgt (k->tgt);
+- }
++ gomp_remove_var (devicep, k);
+ }
+
+ if (tgt->refcount > 1)
+@@ -1298,17 +1318,7 @@ gomp_unload_image_from_device (struct go
+ else
+ {
+ splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &k);
+- splay_tree_remove (&devicep->mem_map, n);
+- if (n->link_key)
+- {
+- if (n->tgt->refcount > 1)
+- n->tgt->refcount--;
+- else
+- {
+- is_tgt_unmapped = true;
+- gomp_unmap_tgt (n->tgt);
+- }
+- }
++ is_tgt_unmapped = gomp_remove_var (devicep, n);
+ }
+ }
+
+@@ -1855,11 +1865,20 @@ GOMP_target_update_ext (int device, size
+ struct gomp_team *team = thr->ts.team;
+ /* If parallel or taskgroup has been cancelled, don't start new
+ tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup
+- && thr->task->taskgroup->cancelled)))
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
+
+ gomp_task_maybe_wait_for_dependencies (depend);
+ }
+@@ -1874,10 +1893,20 @@ GOMP_target_update_ext (int device, size
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
+
+ gomp_update (devicep, mapnum, hostaddrs, sizes, kinds, true);
+ }
+@@ -1986,11 +2015,20 @@ GOMP_target_enter_exit_data (int device,
+ struct gomp_team *team = thr->ts.team;
+ /* If parallel or taskgroup has been cancelled, don't start new
+ tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup
+- && thr->task->taskgroup->cancelled)))
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
+
+ gomp_task_maybe_wait_for_dependencies (depend);
+ }
+@@ -2005,10 +2043,20 @@ GOMP_target_enter_exit_data (int device,
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+- if (team
+- && (gomp_team_barrier_cancelled (&team->barrier)
+- || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
+- return;
++ if (__builtin_expect (gomp_cancel_var, 0) && team)
++ {
++ if (gomp_team_barrier_cancelled (&team->barrier))
++ return;
++ if (thr->task->taskgroup)
++ {
++ if (thr->task->taskgroup->cancelled)
++ return;
++ if (thr->task->taskgroup->workshare
++ && thr->task->taskgroup->prev
++ && thr->task->taskgroup->prev->cancelled)
++ return;
++ }
++ }
+
+ size_t i;
+ if ((flags & GOMP_TARGET_FLAG_EXIT_DATA) == 0)
+@@ -2197,8 +2245,9 @@ omp_target_is_present (void *ptr, int de
+ }
+
+ int
+-omp_target_memcpy (void *dst, void *src, size_t length, size_t dst_offset,
+- size_t src_offset, int dst_device_num, int src_device_num)
++omp_target_memcpy (void *dst, void *src, size_t length,
++ size_t dst_offset, size_t src_offset, int dst_device_num,
++ int src_device_num)
+ {
+ struct gomp_device_descr *dst_devicep = NULL, *src_devicep = NULL;
+ bool ret;
+@@ -2287,21 +2336,25 @@ omp_target_memcpy_rect_worker (void *dst
+ return EINVAL;
+ if (dst_devicep == NULL && src_devicep == NULL)
+ {
+- memcpy ((char *) dst + dst_off, (char *) src + src_off, length);
++ memcpy ((char *) dst + dst_off, (char *) src + src_off,
++ length);
+ ret = 1;
+ }
+ else if (src_devicep == NULL)
+ ret = dst_devicep->host2dev_func (dst_devicep->target_id,
+ (char *) dst + dst_off,
+- (char *) src + src_off, length);
++ (char *) src + src_off,
++ length);
+ else if (dst_devicep == NULL)
+ ret = src_devicep->dev2host_func (src_devicep->target_id,
+ (char *) dst + dst_off,
+- (char *) src + src_off, length);
++ (char *) src + src_off,
++ length);
+ else if (src_devicep == dst_devicep)
+ ret = src_devicep->dev2dev_func (src_devicep->target_id,
+ (char *) dst + dst_off,
+- (char *) src + src_off, length);
++ (char *) src + src_off,
++ length);
+ else
+ ret = 0;
+ return ret ? 0 : EINVAL;
+@@ -2396,8 +2449,8 @@ omp_target_memcpy_rect (void *dst, void
+ }
+
+ int
+-omp_target_associate_ptr (void *host_ptr, void *device_ptr, size_t size,
+- size_t device_offset, int device_num)
++omp_target_associate_ptr (void *host_ptr, void *device_ptr,
++ size_t size, size_t device_offset, int device_num)
+ {
+ if (device_num == GOMP_DEVICE_HOST_FALLBACK)
+ return EINVAL;
+@@ -2499,6 +2552,31 @@ omp_target_disassociate_ptr (void *ptr,
+ return ret;
+ }
+
++int
++omp_pause_resource (omp_pause_resource_t kind, int device_num)
++{
++ (void) kind;
++ if (device_num == GOMP_DEVICE_HOST_FALLBACK)
++ return gomp_pause_host ();
++ if (device_num < 0 || device_num >= gomp_get_num_devices ())
++ return -1;
++ /* Do nothing for target devices for now. */
++ return 0;
++}
++
++int
++omp_pause_resource_all (omp_pause_resource_t kind)
++{
++ (void) kind;
++ if (gomp_pause_host ())
++ return -1;
++ /* Do nothing for target devices for now. */
++ return 0;
++}
++
++ialias (omp_pause_resource)
++ialias (omp_pause_resource_all)
++
+ #ifdef PLUGIN_SUPPORT
+
+ /* This function tries to load a plugin for DEVICE. Name of plugin is passed
+@@ -2632,9 +2710,9 @@ gomp_target_fini (void)
+ }
+ }
+
+-/* This function initializes the runtime needed for offloading.
+- It parses the list of offload targets and tries to load the plugins for
+- these targets. On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP
++/* This function initializes the runtime for offloading.
++ It parses the list of offload plugins, and tries to load these.
++ On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP
+ will be set, and the array DEVICES initialized, containing descriptors for
+ corresponding devices, first the GOMP_OFFLOAD_CAP_OPENMP_400 ones, follows
+ by the others. */
+@@ -2651,7 +2729,7 @@ gomp_target_init (void)
+ num_devices = 0;
+ devices = NULL;
+
+- cur = OFFLOAD_TARGETS;
++ cur = OFFLOAD_PLUGINS;
+ if (*cur)
+ do
+ {
+--- libgomp/ordered.c.jj 2018-04-25 09:40:31.926655587 +0200
++++ libgomp/ordered.c 2019-05-07 18:46:36.532109640 +0200
+@@ -259,7 +259,8 @@ GOMP_ordered_end (void)
+ #define MAX_COLLAPSED_BITS (__SIZEOF_LONG__ * __CHAR_BIT__)
+
+ void
+-gomp_doacross_init (unsigned ncounts, long *counts, long chunk_size)
++gomp_doacross_init (unsigned ncounts, long *counts, long chunk_size,
++ size_t extra)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+@@ -269,13 +270,24 @@ gomp_doacross_init (unsigned ncounts, lo
+ struct gomp_doacross_work_share *doacross;
+
+ if (team == NULL || team->nthreads == 1)
+- return;
++ {
++ empty:
++ if (!extra)
++ ws->doacross = NULL;
++ else
++ {
++ doacross = gomp_malloc_cleared (sizeof (*doacross) + extra);
++ doacross->extra = (void *) (doacross + 1);
++ ws->doacross = doacross;
++ }
++ return;
++ }
+
+ for (i = 0; i < ncounts; i++)
+ {
+ /* If any count is 0, GOMP_doacross_{post,wait} can't be called. */
+ if (counts[i] == 0)
+- return;
++ goto empty;
+
+ if (num_bits <= MAX_COLLAPSED_BITS)
+ {
+@@ -314,7 +326,7 @@ gomp_doacross_init (unsigned ncounts, lo
+ elt_sz = (elt_sz + 63) & ~63UL;
+
+ doacross = gomp_malloc (sizeof (*doacross) + 63 + num_ents * elt_sz
+- + shift_sz);
++ + shift_sz + extra);
+ doacross->chunk_size = chunk_size;
+ doacross->elt_sz = elt_sz;
+ doacross->ncounts = ncounts;
+@@ -322,6 +334,13 @@ gomp_doacross_init (unsigned ncounts, lo
+ doacross->array = (unsigned char *)
+ ((((uintptr_t) (doacross + 1)) + 63 + shift_sz)
+ & ~(uintptr_t) 63);
++ if (extra)
++ {
++ doacross->extra = doacross->array + num_ents * elt_sz;
++ memset (doacross->extra, '\0', extra);
++ }
++ else
++ doacross->extra = NULL;
+ if (num_bits <= MAX_COLLAPSED_BITS)
+ {
+ unsigned int shift_count = 0;
+@@ -360,7 +379,8 @@ GOMP_doacross_post (long *counts)
+ unsigned long ent;
+ unsigned int i;
+
+- if (__builtin_expect (doacross == NULL, 0))
++ if (__builtin_expect (doacross == NULL, 0)
++ || __builtin_expect (doacross->array == NULL, 0))
+ {
+ __sync_synchronize ();
+ return;
+@@ -411,7 +431,8 @@ GOMP_doacross_wait (long first, ...)
+ unsigned long ent;
+ unsigned int i;
+
+- if (__builtin_expect (doacross == NULL, 0))
++ if (__builtin_expect (doacross == NULL, 0)
++ || __builtin_expect (doacross->array == NULL, 0))
+ {
+ __sync_synchronize ();
+ return;
+@@ -488,7 +509,8 @@ GOMP_doacross_wait (long first, ...)
+ typedef unsigned long long gomp_ull;
+
+ void
+-gomp_doacross_ull_init (unsigned ncounts, gomp_ull *counts, gomp_ull chunk_size)
++gomp_doacross_ull_init (unsigned ncounts, gomp_ull *counts,
++ gomp_ull chunk_size, size_t extra)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+@@ -498,13 +520,24 @@ gomp_doacross_ull_init (unsigned ncounts
+ struct gomp_doacross_work_share *doacross;
+
+ if (team == NULL || team->nthreads == 1)
+- return;
++ {
++ empty:
++ if (!extra)
++ ws->doacross = NULL;
++ else
++ {
++ doacross = gomp_malloc_cleared (sizeof (*doacross) + extra);
++ doacross->extra = (void *) (doacross + 1);
++ ws->doacross = doacross;
++ }
++ return;
++ }
+
+ for (i = 0; i < ncounts; i++)
+ {
+ /* If any count is 0, GOMP_doacross_{post,wait} can't be called. */
+ if (counts[i] == 0)
+- return;
++ goto empty;
+
+ if (num_bits <= MAX_COLLAPSED_BITS)
+ {
+@@ -557,6 +590,13 @@ gomp_doacross_ull_init (unsigned ncounts
+ doacross->array = (unsigned char *)
+ ((((uintptr_t) (doacross + 1)) + 63 + shift_sz)
+ & ~(uintptr_t) 63);
++ if (extra)
++ {
++ doacross->extra = doacross->array + num_ents * elt_sz;
++ memset (doacross->extra, '\0', extra);
++ }
++ else
++ doacross->extra = NULL;
+ if (num_bits <= MAX_COLLAPSED_BITS)
+ {
+ unsigned int shift_count = 0;
+@@ -595,7 +635,8 @@ GOMP_doacross_ull_post (gomp_ull *counts
+ unsigned long ent;
+ unsigned int i;
+
+- if (__builtin_expect (doacross == NULL, 0))
++ if (__builtin_expect (doacross == NULL, 0)
++ || __builtin_expect (doacross->array == NULL, 0))
+ {
+ __sync_synchronize ();
+ return;
+@@ -667,7 +708,8 @@ GOMP_doacross_ull_wait (gomp_ull first,
+ unsigned long ent;
+ unsigned int i;
+
+- if (__builtin_expect (doacross == NULL, 0))
++ if (__builtin_expect (doacross == NULL, 0)
++ || __builtin_expect (doacross->array == NULL, 0))
+ {
+ __sync_synchronize ();
+ return;
+--- libgomp/alloc.c.jj 2018-04-25 09:40:31.926655587 +0200
++++ libgomp/alloc.c 2019-05-07 18:46:36.336112770 +0200
+@@ -57,3 +57,50 @@ gomp_realloc (void *old, size_t size)
+ gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
+ return ret;
+ }
++
++void *
++gomp_aligned_alloc (size_t al, size_t size)
++{
++ void *ret;
++ if (al < sizeof (void *))
++ al = sizeof (void *);
++#ifdef HAVE_ALIGNED_ALLOC
++ ret = aligned_alloc (al, size);
++#elif defined(HAVE__ALIGNED_MALLOC)
++ ret = _aligned_malloc (size, al);
++#elif defined(HAVE_POSIX_MEMALIGN)
++ if (posix_memalign (&ret, al, size) != 0)
++ ret = NULL;
++#elif defined(HAVE_MEMALIGN)
++ {
++ extern void *memalign (size_t, size_t);
++ ret = memalign (al, size);
++ }
++#else
++ ret = NULL;
++ if ((al & (al - 1)) == 0 && size)
++ {
++ void *p = malloc (size + al);
++ if (p)
++ {
++ void *ap = (void *) (((uintptr_t) p + al) & -al);
++ ((void **) ap)[-1] = p;
++ ret = ap;
++ }
++ }
++#endif
++ if (ret == NULL)
++ gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
++ return ret;
++}
++
++void
++gomp_aligned_free (void *ptr)
++{
++#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC
++ free (ptr);
++#else
++ if (ptr)
++ free (((void **) ptr)[-1]);
++#endif
++}
+--- libgomp/configure.ac.jj 2018-04-25 09:40:31.321655307 +0200
++++ libgomp/configure.ac 2019-05-07 18:46:36.471110614 +0200
+@@ -219,6 +219,7 @@ m4_include([plugin/configfrag.ac])
+
+ # Check for functions needed.
+ AC_CHECK_FUNCS(getloadavg clock_gettime strtoull)
++AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc)
+
+ # Check for broken semaphore implementation on darwin.
+ # sem_init returns: sem_init error: Function not implemented.
+@@ -266,6 +267,41 @@ if test $ac_cv_func_clock_gettime = no;
+ [Define to 1 if you have the `clock_gettime' function.])])
+ fi
+
++# Check for uname.
++AC_COMPILE_IFELSE(
++ [AC_LANG_PROGRAM(
++ [#include
++ #include
++ #include ],
++ [struct utsname buf;
++ volatile size_t len = 0;
++ if (!uname (buf))
++ len = strlen (buf.nodename);])],
++ AC_DEFINE(HAVE_UNAME, 1,
++[ Define if uname is supported and struct utsname has nodename field.]))
++
++# Check for gethostname.
++AC_COMPILE_IFELSE(
++ [AC_LANG_PROGRAM(
++ [#include ],
++ [
++changequote(,)dnl
++ char buf[256];
++ if (gethostname (buf, sizeof (buf) - 1) == 0)
++ buf[255] = '\0';
++changequote([,])dnl
++ ])],
++ AC_DEFINE(HAVE_GETHOSTNAME, 1,
++[ Define if gethostname is supported.]))
++
++# Check for getpid.
++AC_COMPILE_IFELSE(
++ [AC_LANG_PROGRAM(
++ [#include ],
++ [int pid = getpid ();])],
++ AC_DEFINE(HAVE_GETPID, 1,
++[ Define if getpid is supported.]))
++
+ # See if we support thread-local storage.
+ GCC_CHECK_TLS
+
+--- libgomp/icv.c.jj 2018-04-25 09:40:31.870655561 +0200
++++ libgomp/icv.c 2019-05-07 18:46:36.501110134 +0200
+@@ -69,7 +69,7 @@ void
+ omp_set_schedule (omp_sched_t kind, int chunk_size)
+ {
+ struct gomp_task_icv *icv = gomp_icv (true);
+- switch (kind)
++ switch (kind & ~omp_sched_monotonic)
+ {
+ case omp_sched_static:
+ if (chunk_size < 1)
+--- libgomp/configure.jj 2018-04-25 09:40:31.913655581 +0200
++++ libgomp/configure 2019-05-07 18:47:37.961128420 +0200
+@@ -636,6 +636,8 @@ PLUGIN_NVPTX_FALSE
+ PLUGIN_NVPTX_TRUE
+ offload_additional_lib_paths
+ offload_additional_options
++offload_targets
++offload_plugins
+ PLUGIN_HSA_LIBS
+ PLUGIN_HSA_LDFLAGS
+ PLUGIN_HSA_CPPFLAGS
+@@ -648,7 +650,6 @@ PLUGIN_NVPTX_CPPFLAGS
+ PLUGIN_NVPTX
+ CUDA_DRIVER_LIB
+ CUDA_DRIVER_INCLUDE
+-offload_targets
+ libtool_VERSION
+ ac_ct_FC
+ FCFLAGS
+@@ -11157,7 +11158,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 11160 "configure"
++#line 11161 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -11263,7 +11264,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 11266 "configure"
++#line 11267 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -15167,8 +15168,6 @@ fi
+ # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ # .
+
+-offload_targets=
+-
+ plugin_support=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5
+ $as_echo_n "checking for dlsym in -ldl... " >&6; }
+@@ -15302,7 +15301,11 @@ if test "${with_cuda_driver_lib+set}" =
+ fi
+
+ case "x$with_cuda_driver" in
+- x | xno) ;;
++ x) ;;
++ xno)
++ CUDA_DRIVER_INCLUDE=no
++ CUDA_DRIVER_LIB=no
++ ;;
+ *) CUDA_DRIVER_INCLUDE=$with_cuda_driver/include
+ CUDA_DRIVER_LIB=$with_cuda_driver/lib
+ ;;
+@@ -15313,10 +15316,12 @@ fi
+ if test "x$with_cuda_driver_lib" != x; then
+ CUDA_DRIVER_LIB=$with_cuda_driver_lib
+ fi
+-if test "x$CUDA_DRIVER_INCLUDE" != x; then
++if test "x$CUDA_DRIVER_INCLUDE" != x \
++ && test "x$CUDA_DRIVER_INCLUDE" != xno; then
+ CUDA_DRIVER_CPPFLAGS=-I$CUDA_DRIVER_INCLUDE
+ fi
+-if test "x$CUDA_DRIVER_LIB" != x; then
++if test "x$CUDA_DRIVER_LIB" != x \
++ && test "x$CUDA_DRIVER_LIB" != xno; then
+ CUDA_DRIVER_LDFLAGS=-L$CUDA_DRIVER_LIB
+ fi
+
+@@ -15383,7 +15388,13 @@ PLUGIN_HSA_LIBS=
+
+
+
+-# Get offload targets and path to install tree of offloading compiler.
++# Parse '--enable-offload-targets', figure out the corresponding libgomp
++# plugins, and configure to find the corresponding offload compilers.
++# 'offload_plugins' and 'offload_targets' will be populated in the same order.
++offload_plugins=
++offload_targets=
++
++
+ offload_additional_options=
+ offload_additional_lib_paths=
+
+@@ -15392,25 +15403,27 @@ if test x"$enable_offload_targets" != x;
+ for tgt in `echo $enable_offload_targets | sed -e 's#,# #g'`; do
+ tgt_dir=`echo $tgt | grep '=' | sed 's/.*=//'`
+ tgt=`echo $tgt | sed 's/=.*//'`
+- tgt_name=
++ tgt_plugin=
+ case $tgt in
+ *-intelmic-* | *-intelmicemul-*)
+- tgt_name=intelmic
++ tgt_plugin=intelmic
+ ;;
+ nvptx*)
+- tgt_name=nvptx
++ tgt_plugin=nvptx
+ PLUGIN_NVPTX=$tgt
+- PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS
+- PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS
+- PLUGIN_NVPTX_LIBS='-lcuda'
+-
+- PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS
+- CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS"
+- PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS
+- LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS"
+- PLUGIN_NVPTX_save_LIBS=$LIBS
+- LIBS="$PLUGIN_NVPTX_LIBS $LIBS"
+- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++ if test "x$CUDA_DRIVER_LIB" != xno \
++ && test "x$CUDA_DRIVER_LIB" != xno; then
++ PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS
++ PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS
++ PLUGIN_NVPTX_LIBS='-lcuda'
++
++ PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS
++ CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS"
++ PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS
++ LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS"
++ PLUGIN_NVPTX_save_LIBS=$LIBS
++ LIBS="$PLUGIN_NVPTX_LIBS $LIBS"
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h. */
+ #include "cuda.h"
+ int
+@@ -15426,13 +15439,16 @@ if ac_fn_c_try_link "$LINENO"; then :
+ fi
+ rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+- CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS
+- LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS
+- LIBS=$PLUGIN_NVPTX_save_LIBS
++ CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS
++ LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS
++ LIBS=$PLUGIN_NVPTX_save_LIBS
++ fi
+ case $PLUGIN_NVPTX in
+ nvptx*)
+- if test "x$CUDA_DRIVER_INCLUDE" = x \
+- && test "x$CUDA_DRIVER_LIB" = x; then
++ if (test "x$CUDA_DRIVER_INCLUDE" = x \
++ || test "x$CUDA_DRIVER_INCLUDE" = xno) \
++ && (test "x$CUDA_DRIVER_LIB" = x \
++ || test "x$CUDA_DRIVER_LIB" = xno); then
+ PLUGIN_NVPTX=1
+ PLUGIN_NVPTX_CPPFLAGS='-I$(srcdir)/plugin/cuda'
+ PLUGIN_NVPTX_LIBS='-ldl'
+@@ -15452,7 +15468,7 @@ rm -f core conftest.err conftest.$ac_obj
+ PLUGIN_HSA=0
+ ;;
+ *)
+- tgt_name=hsa
++ tgt_plugin=hsa
+ PLUGIN_HSA=$tgt
+ PLUGIN_HSA_CPPFLAGS=$HSA_RUNTIME_CPPFLAGS
+ PLUGIN_HSA_LDFLAGS="$HSA_RUNTIME_LDFLAGS"
+@@ -15470,7 +15486,7 @@ rm -f core conftest.err conftest.$ac_obj
+ LDFLAGS=$PLUGIN_HSA_save_LDFLAGS
+ LIBS=$PLUGIN_HSA_save_LIBS
+ case $PLUGIN_HSA in
+- hsa*)
++ hsa*)
+ HSA_PLUGIN=0
+ as_fn_error "HSA run-time package required for HSA support" "$LINENO" 5
+ ;;
+@@ -15487,16 +15503,19 @@ rm -f core conftest.err conftest.$ac_obj
+ as_fn_error "unknown offload target specified" "$LINENO" 5
+ ;;
+ esac
+- if test x"$tgt_name" = x; then
+- # Don't configure libgomp for this offloading target if we don't build
+- # the corresponding plugin.
++ if test x"$tgt_plugin" = x; then
++ # Not configuring libgomp for this offload target if we're not building
++ # the corresponding offload plugin.
+ continue
+- elif test x"$offload_targets" = x; then
+- offload_targets=$tgt_name
++ elif test x"$offload_plugins" = x; then
++ offload_plugins=$tgt_plugin
++ offload_targets=$tgt
+ else
+- offload_targets=$offload_targets,$tgt_name
++ offload_plugins=$offload_plugins,$tgt_plugin
++ offload_targets=$offload_targets,$tgt
+ fi
+- if test "$tgt_name" = hsa; then
++ # Configure additional search paths.
++ if test "$tgt_plugin" = hsa; then
+ # Offloading compilation is all handled by the target compiler.
+ :
+ elif test x"$tgt_dir" != x; then
+@@ -15510,7 +15529,7 @@ rm -f core conftest.err conftest.$ac_obj
+ fi
+
+ cat >>confdefs.h <<_ACEOF
+-#define OFFLOAD_TARGETS "$offload_targets"
++#define OFFLOAD_PLUGINS "$offload_plugins"
+ _ACEOF
+
+ if test $PLUGIN_NVPTX = 1; then
+@@ -15570,6 +15589,19 @@ _ACEOF
+ fi
+ done
+
++for ac_func in aligned_alloc posix_memalign memalign _aligned_malloc
++do :
++ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
++eval as_val=\$$as_ac_var
++ if test "x$as_val" = x""yes; then :
++ cat >>confdefs.h <<_ACEOF
++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++done
++
+
+ # Check for broken semaphore implementation on darwin.
+ # sem_init returns: sem_init error: Function not implemented.
+@@ -15784,6 +15816,72 @@ fi
+
+ fi
+
++# Check for uname.
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++ #include
++ #include
++int
++main ()
++{
++struct utsname buf;
++ volatile size_t len = 0;
++ if (!uname (buf))
++ len = strlen (buf.nodename);
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++$as_echo "#define HAVE_UNAME 1" >>confdefs.h
++
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
++# Check for gethostname.
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++int
++main ()
++{
++
++ char buf[256];
++ if (gethostname (buf, sizeof (buf) - 1) == 0)
++ buf[255] = '\0';
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++$as_echo "#define HAVE_GETHOSTNAME 1" >>confdefs.h
++
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
++# Check for getpid.
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++int
++main ()
++{
++int pid = getpid ();
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++$as_echo "#define HAVE_GETPID 1" >>confdefs.h
++
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
+ # See if we support thread-local storage.
+
+
+--- libgomp/Makefile.am.jj 2018-04-25 09:40:31.926655587 +0200
++++ libgomp/Makefile.am 2019-05-07 19:59:03.683989317 +0200
+@@ -63,12 +63,13 @@ libgomp_la_SOURCES = alloc.c atomic.c ba
+ parallel.c sections.c single.c task.c team.c work.c lock.c mutex.c \
+ proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c target.c \
+ splay-tree.c libgomp-plugin.c oacc-parallel.c oacc-host.c oacc-init.c \
+- oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c
++ oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
++ affinity-fmt.c teams.c
+
+ include $(top_srcdir)/plugin/Makefrag.am
+
+ if USE_FORTRAN
+-libgomp_la_SOURCES += openacc.f90
++libgomp_la_SOURCES += openacc2.f90
+ endif
+
+ nodist_noinst_HEADERS = libgomp_f.h
+@@ -87,8 +88,6 @@ omp_lib_kinds.mod: omp_lib.mod
+ :
+ openacc_kinds.mod: openacc.mod
+ :
+-openacc.mod: openacc.lo
+- :
+ %.mod: %.f90
+ $(FC) $(FCFLAGS) -fsyntax-only $<
+ fortran.lo: libgomp_f.h
+--- libgomp/oacc-mem.c.jj 2018-04-25 09:40:31.924655586 +0200
++++ libgomp/oacc-mem.c 2019-05-07 18:46:36.530109672 +0200
+@@ -153,8 +153,9 @@ acc_free (void *d)
+ gomp_fatal ("error in freeing device memory in %s", __FUNCTION__);
+ }
+
+-void
+-acc_memcpy_to_device (void *d, void *h, size_t s)
++static void
++memcpy_tofrom_device (bool from, void *d, void *h, size_t s, int async,
++ const char *libfnname)
+ {
+ /* No need to call lazy open here, as the device pointer must have
+ been obtained from a routine that did that. */
+@@ -164,31 +165,49 @@ acc_memcpy_to_device (void *d, void *h,
+
+ if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+ {
+- memmove (d, h, s);
++ if (from)
++ memmove (h, d, s);
++ else
++ memmove (d, h, s);
+ return;
+ }
+
+- if (!thr->dev->host2dev_func (thr->dev->target_id, d, h, s))
+- gomp_fatal ("error in %s", __FUNCTION__);
++ if (async > acc_async_sync)
++ thr->dev->openacc.async_set_async_func (async);
++
++ bool ret = (from
++ ? thr->dev->dev2host_func (thr->dev->target_id, h, d, s)
++ : thr->dev->host2dev_func (thr->dev->target_id, d, h, s));
++
++ if (async > acc_async_sync)
++ thr->dev->openacc.async_set_async_func (acc_async_sync);
++
++ if (!ret)
++ gomp_fatal ("error in %s", libfnname);
+ }
+
+ void
+-acc_memcpy_from_device (void *h, void *d, size_t s)
++acc_memcpy_to_device (void *d, void *h, size_t s)
+ {
+- /* No need to call lazy open here, as the device pointer must have
+- been obtained from a routine that did that. */
+- struct goacc_thread *thr = goacc_thread ();
++ memcpy_tofrom_device (false, d, h, s, acc_async_sync, __FUNCTION__);
++}
+
+- assert (thr && thr->dev);
++void
++acc_memcpy_to_device_async (void *d, void *h, size_t s, int async)
++{
++ memcpy_tofrom_device (false, d, h, s, async, __FUNCTION__);
++}
+
+- if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+- {
+- memmove (h, d, s);
+- return;
+- }
++void
++acc_memcpy_from_device (void *h, void *d, size_t s)
++{
++ memcpy_tofrom_device (true, d, h, s, acc_async_sync, __FUNCTION__);
++}
+
+- if (!thr->dev->dev2host_func (thr->dev->target_id, h, d, s))
+- gomp_fatal ("error in %s", __FUNCTION__);
++void
++acc_memcpy_from_device_async (void *h, void *d, size_t s, int async)
++{
++ memcpy_tofrom_device (true, d, h, s, async, __FUNCTION__);
+ }
+
+ /* Return the device pointer that corresponds to host data H. Or NULL
+@@ -347,6 +366,7 @@ acc_map_data (void *h, void *d, size_t s
+
+ tgt = gomp_map_vars (acc_dev, mapnum, &hostaddrs, &devaddrs, &sizes,
+ &kinds, true, GOMP_MAP_VARS_OPENACC);
++ tgt->list[0].key->refcount = REFCOUNT_INFINITY;
+ }
+
+ gomp_mutex_lock (&acc_dev->lock);
+@@ -389,6 +409,9 @@ acc_unmap_data (void *h)
+ (void *) n->host_start, (int) host_size, (void *) h);
+ }
+
++ /* Mark for removal. */
++ n->refcount = 1;
++
+ t = n->tgt;
+
+ if (t->refcount == 2)
+@@ -424,7 +447,7 @@ acc_unmap_data (void *h)
+ #define FLAG_COPY (1 << 2)
+
+ static void *
+-present_create_copy (unsigned f, void *h, size_t s)
++present_create_copy (unsigned f, void *h, size_t s, int async)
+ {
+ void *d;
+ splay_tree_key n;
+@@ -460,6 +483,11 @@ present_create_copy (unsigned f, void *h
+ gomp_fatal ("[%p,+%d] not mapped", (void *)h, (int)s);
+ }
+
++ if (n->refcount != REFCOUNT_INFINITY)
++ {
++ n->refcount++;
++ n->dynamic_refcount++;
++ }
+ gomp_mutex_unlock (&acc_dev->lock);
+ }
+ else if (!(f & FLAG_CREATE))
+@@ -481,8 +509,16 @@ present_create_copy (unsigned f, void *h
+
+ gomp_mutex_unlock (&acc_dev->lock);
+
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (async);
++
+ tgt = gomp_map_vars (acc_dev, mapnum, &hostaddrs, NULL, &s, &kinds, true,
+ GOMP_MAP_VARS_OPENACC);
++ /* Initialize dynamic refcount. */
++ tgt->list[0].key->dynamic_refcount = 1;
++
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (acc_async_sync);
+
+ gomp_mutex_lock (&acc_dev->lock);
+
+@@ -499,53 +535,71 @@ present_create_copy (unsigned f, void *h
+ void *
+ acc_create (void *h, size_t s)
+ {
+- return present_create_copy (FLAG_CREATE, h, s);
++ return present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s, acc_async_sync);
+ }
+
+-void *
+-acc_copyin (void *h, size_t s)
++void
++acc_create_async (void *h, size_t s, int async)
+ {
+- return present_create_copy (FLAG_CREATE | FLAG_COPY, h, s);
++ present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s, async);
+ }
+
++/* acc_present_or_create used to be what acc_create is now. */
++/* acc_pcreate is acc_present_or_create by a different name. */
++#ifdef HAVE_ATTRIBUTE_ALIAS
++strong_alias (acc_create, acc_present_or_create)
++strong_alias (acc_create, acc_pcreate)
++#else
+ void *
+ acc_present_or_create (void *h, size_t s)
+ {
+- return present_create_copy (FLAG_PRESENT | FLAG_CREATE, h, s);
++ return acc_create (h, s);
+ }
+
+-/* acc_pcreate is acc_present_or_create by a different name. */
+-#ifdef HAVE_ATTRIBUTE_ALIAS
+-strong_alias (acc_present_or_create, acc_pcreate)
+-#else
+ void *
+ acc_pcreate (void *h, size_t s)
+ {
+- return acc_present_or_create (h, s);
++ return acc_create (h, s);
+ }
+ #endif
+
+ void *
+-acc_present_or_copyin (void *h, size_t s)
++acc_copyin (void *h, size_t s)
++{
++ return present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s,
++ acc_async_sync);
++}
++
++void
++acc_copyin_async (void *h, size_t s, int async)
+ {
+- return present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s);
++ present_create_copy (FLAG_PRESENT | FLAG_CREATE | FLAG_COPY, h, s, async);
+ }
+
++/* acc_present_or_copyin used to be what acc_copyin is now. */
+ /* acc_pcopyin is acc_present_or_copyin by a different name. */
+ #ifdef HAVE_ATTRIBUTE_ALIAS
+-strong_alias (acc_present_or_copyin, acc_pcopyin)
++strong_alias (acc_copyin, acc_present_or_copyin)
++strong_alias (acc_copyin, acc_pcopyin)
+ #else
+ void *
++acc_present_or_copyin (void *h, size_t s)
++{
++ return acc_copyin (h, s);
++}
++
++void *
+ acc_pcopyin (void *h, size_t s)
+ {
+- return acc_present_or_copyin (h, s);
++ return acc_copyin (h, s);
+ }
+ #endif
+
+-#define FLAG_COPYOUT (1 << 0)
++#define FLAG_COPYOUT (1 << 0)
++#define FLAG_FINALIZE (1 << 1)
+
+ static void
+-delete_copyout (unsigned f, void *h, size_t s, const char *libfnname)
++delete_copyout (unsigned f, void *h, size_t s, int async, const char *libfnname)
+ {
+ size_t host_size;
+ splay_tree_key n;
+@@ -581,31 +635,111 @@ delete_copyout (unsigned f, void *h, siz
+ (void *) n->host_start, (int) host_size, (void *) h, (int) s);
+ }
+
+- gomp_mutex_unlock (&acc_dev->lock);
++ if (n->refcount == REFCOUNT_INFINITY)
++ {
++ n->refcount = 0;
++ n->dynamic_refcount = 0;
++ }
++ if (n->refcount < n->dynamic_refcount)
++ {
++ gomp_mutex_unlock (&acc_dev->lock);
++ gomp_fatal ("Dynamic reference counting assert fail\n");
++ }
+
+- if (f & FLAG_COPYOUT)
+- acc_dev->dev2host_func (acc_dev->target_id, h, d, s);
++ if (f & FLAG_FINALIZE)
++ {
++ n->refcount -= n->dynamic_refcount;
++ n->dynamic_refcount = 0;
++ }
++ else if (n->dynamic_refcount)
++ {
++ n->dynamic_refcount--;
++ n->refcount--;
++ }
++
++ if (n->refcount == 0)
++ {
++ if (n->tgt->refcount == 2)
++ {
++ struct target_mem_desc *tp, *t;
++ for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL;
++ tp = t, t = t->prev)
++ if (n->tgt == t)
++ {
++ if (tp)
++ tp->prev = t->prev;
++ else
++ acc_dev->openacc.data_environ = t->prev;
++ break;
++ }
++ }
++
++ if (f & FLAG_COPYOUT)
++ {
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (async);
++ acc_dev->dev2host_func (acc_dev->target_id, h, d, s);
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (acc_async_sync);
++ }
+
+- acc_unmap_data (h);
++ gomp_remove_var (acc_dev, n);
++ }
+
+- if (!acc_dev->free_func (acc_dev->target_id, d))
+- gomp_fatal ("error in freeing device memory in %s", libfnname);
++ gomp_mutex_unlock (&acc_dev->lock);
+ }
+
+ void
+ acc_delete (void *h , size_t s)
+ {
+- delete_copyout (0, h, s, __FUNCTION__);
++ delete_copyout (0, h, s, acc_async_sync, __FUNCTION__);
++}
++
++void
++acc_delete_async (void *h , size_t s, int async)
++{
++ delete_copyout (0, h, s, async, __FUNCTION__);
++}
++
++void
++acc_delete_finalize (void *h , size_t s)
++{
++ delete_copyout (FLAG_FINALIZE, h, s, acc_async_sync, __FUNCTION__);
++}
++
++void
++acc_delete_finalize_async (void *h , size_t s, int async)
++{
++ delete_copyout (FLAG_FINALIZE, h, s, async, __FUNCTION__);
+ }
+
+ void
+ acc_copyout (void *h, size_t s)
+ {
+- delete_copyout (FLAG_COPYOUT, h, s, __FUNCTION__);
++ delete_copyout (FLAG_COPYOUT, h, s, acc_async_sync, __FUNCTION__);
++}
++
++void
++acc_copyout_async (void *h, size_t s, int async)
++{
++ delete_copyout (FLAG_COPYOUT, h, s, async, __FUNCTION__);
++}
++
++void
++acc_copyout_finalize (void *h, size_t s)
++{
++ delete_copyout (FLAG_COPYOUT | FLAG_FINALIZE, h, s, acc_async_sync,
++ __FUNCTION__);
++}
++
++void
++acc_copyout_finalize_async (void *h, size_t s, int async)
++{
++ delete_copyout (FLAG_COPYOUT | FLAG_FINALIZE, h, s, async, __FUNCTION__);
+ }
+
+ static void
+-update_dev_host (int is_dev, void *h, size_t s)
++update_dev_host (int is_dev, void *h, size_t s, int async)
+ {
+ splay_tree_key n;
+ void *d;
+@@ -631,24 +765,42 @@ update_dev_host (int is_dev, void *h, si
+ d = (void *) (n->tgt->tgt_start + n->tgt_offset
+ + (uintptr_t) h - n->host_start);
+
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (async);
++
+ if (is_dev)
+ acc_dev->host2dev_func (acc_dev->target_id, d, h, s);
+ else
+ acc_dev->dev2host_func (acc_dev->target_id, h, d, s);
+
++ if (async > acc_async_sync)
++ acc_dev->openacc.async_set_async_func (acc_async_sync);
++
+ gomp_mutex_unlock (&acc_dev->lock);
+ }
+
+ void
+ acc_update_device (void *h, size_t s)
+ {
+- update_dev_host (1, h, s);
++ update_dev_host (1, h, s, acc_async_sync);
++}
++
++void
++acc_update_device_async (void *h, size_t s, int async)
++{
++ update_dev_host (1, h, s, async);
+ }
+
+ void
+ acc_update_self (void *h, size_t s)
+ {
+- update_dev_host (0, h, s);
++ update_dev_host (0, h, s, acc_async_sync);
++}
++
++void
++acc_update_self_async (void *h, size_t s, int async)
++{
++ update_dev_host (0, h, s, async);
+ }
+
+ void
+@@ -659,11 +811,37 @@ gomp_acc_insert_pointer (size_t mapnum,
+ struct goacc_thread *thr = goacc_thread ();
+ struct gomp_device_descr *acc_dev = thr->dev;
+
++ if (acc_is_present (*hostaddrs, *sizes))
++ {
++ splay_tree_key n;
++ gomp_mutex_lock (&acc_dev->lock);
++ n = lookup_host (acc_dev, *hostaddrs, *sizes);
++ gomp_mutex_unlock (&acc_dev->lock);
++
++ tgt = n->tgt;
++ for (size_t i = 0; i < tgt->list_count; i++)
++ if (tgt->list[i].key == n)
++ {
++ for (size_t j = 0; j < mapnum; j++)
++ if (i + j < tgt->list_count && tgt->list[i + j].key)
++ {
++ tgt->list[i + j].key->refcount++;
++ tgt->list[i + j].key->dynamic_refcount++;
++ }
++ return;
++ }
++ /* Should not reach here. */
++ gomp_fatal ("Dynamic refcount incrementing failed for pointer/pset");
++ }
++
+ gomp_debug (0, " %s: prepare mappings\n", __FUNCTION__);
+ tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs,
+ NULL, sizes, kinds, true, GOMP_MAP_VARS_OPENACC);
+ gomp_debug (0, " %s: mappings prepared\n", __FUNCTION__);
+
++ /* Initialize dynamic refcount. */
++ tgt->list[0].key->dynamic_refcount = 1;
++
+ gomp_mutex_lock (&acc_dev->lock);
+ tgt->prev = acc_dev->openacc.data_environ;
+ acc_dev->openacc.data_environ = tgt;
+@@ -671,7 +849,8 @@ gomp_acc_insert_pointer (size_t mapnum,
+ }
+
+ void
+-gomp_acc_remove_pointer (void *h, bool force_copyfrom, int async, int mapnum)
++gomp_acc_remove_pointer (void *h, size_t s, bool force_copyfrom, int async,
++ int finalize, int mapnum)
+ {
+ struct goacc_thread *thr = goacc_thread ();
+ struct gomp_device_descr *acc_dev = thr->dev;
+@@ -679,6 +858,9 @@ gomp_acc_remove_pointer (void *h, bool f
+ struct target_mem_desc *t;
+ int minrefs = (mapnum == 1) ? 2 : 3;
+
++ if (!acc_is_present (h, s))
++ return;
++
+ gomp_mutex_lock (&acc_dev->lock);
+
+ n = lookup_host (acc_dev, h, 1);
+@@ -693,40 +875,65 @@ gomp_acc_remove_pointer (void *h, bool f
+
+ t = n->tgt;
+
+- struct target_mem_desc *tp;
++ if (n->refcount < n->dynamic_refcount)
++ {
++ gomp_mutex_unlock (&acc_dev->lock);
++ gomp_fatal ("Dynamic reference counting assert fail\n");
++ }
+
+- if (t->refcount == minrefs)
++ if (finalize)
+ {
+- /* This is the last reference, so pull the descriptor off the
+- chain. This avoids gomp_unmap_vars via gomp_unmap_tgt from
+- freeing the device memory. */
+- t->tgt_end = 0;
+- t->to_free = 0;
++ n->refcount -= n->dynamic_refcount;
++ n->dynamic_refcount = 0;
++ }
++ else if (n->dynamic_refcount)
++ {
++ n->dynamic_refcount--;
++ n->refcount--;
++ }
+
+- for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL;
+- tp = t, t = t->prev)
++ gomp_mutex_unlock (&acc_dev->lock);
++
++ if (n->refcount == 0)
++ {
++ if (t->refcount == minrefs)
+ {
+- if (n->tgt == t)
++ /* This is the last reference, so pull the descriptor off the
++ chain. This prevents gomp_unmap_vars via gomp_unmap_tgt from
++ freeing the device memory. */
++ struct target_mem_desc *tp;
++ for (tp = NULL, t = acc_dev->openacc.data_environ; t != NULL;
++ tp = t, t = t->prev)
+ {
+- if (tp)
+- tp->prev = t->prev;
+- else
+- acc_dev->openacc.data_environ = t->prev;
+- break;
++ if (n->tgt == t)
++ {
++ if (tp)
++ tp->prev = t->prev;
++ else
++ acc_dev->openacc.data_environ = t->prev;
++ break;
++ }
+ }
+ }
+- }
+
+- if (force_copyfrom)
+- t->list[0].copy_from = 1;
++ /* Set refcount to 1 to allow gomp_unmap_vars to unmap it. */
++ n->refcount = 1;
++ t->refcount = minrefs;
++ for (size_t i = 0; i < t->list_count; i++)
++ if (t->list[i].key == n)
++ {
++ t->list[i].copy_from = force_copyfrom ? 1 : 0;
++ break;
++ }
+
+- gomp_mutex_unlock (&acc_dev->lock);
++ /* If running synchronously, unmap immediately. */
++ if (async < acc_async_noval)
++ gomp_unmap_vars (t, true);
++ else
++ t->device_descr->openacc.register_async_cleanup_func (t, async);
++ }
+
+- /* If running synchronously, unmap immediately. */
+- if (async < acc_async_noval)
+- gomp_unmap_vars (t, true);
+- else
+- t->device_descr->openacc.register_async_cleanup_func (t, async);
++ gomp_mutex_unlock (&acc_dev->lock);
+
+ gomp_debug (0, " %s: mappings restored\n", __FUNCTION__);
+ }
+--- libgomp/env.c.jj 2018-04-25 09:40:31.924655586 +0200
++++ libgomp/env.c 2019-05-07 18:46:36.482110438 +0200
+@@ -88,8 +88,12 @@ void **gomp_places_list;
+ unsigned long gomp_places_list_len;
+ int gomp_debug_var;
+ unsigned int gomp_num_teams_var;
++bool gomp_display_affinity_var;
++char *gomp_affinity_format_var = "level %L thread %i affinity %A";
++size_t gomp_affinity_format_len;
+ char *goacc_device_type;
+ int goacc_device_num;
++int goacc_default_dims[GOMP_DIM_MAX];
+
+ #ifndef LIBGOMP_OFFLOADED_ONLY
+
+@@ -100,6 +104,7 @@ parse_schedule (void)
+ {
+ char *env, *end;
+ unsigned long value;
++ int monotonic = 0;
+
+ env = getenv ("OMP_SCHEDULE");
+ if (env == NULL)
+@@ -107,6 +112,26 @@ parse_schedule (void)
+
+ while (isspace ((unsigned char) *env))
+ ++env;
++ if (strncasecmp (env, "monotonic", 9) == 0)
++ {
++ monotonic = 1;
++ env += 9;
++ }
++ else if (strncasecmp (env, "nonmonotonic", 12) == 0)
++ {
++ monotonic = -1;
++ env += 12;
++ }
++ if (monotonic)
++ {
++ while (isspace ((unsigned char) *env))
++ ++env;
++ if (*env != ':')
++ goto unknown;
++ ++env;
++ while (isspace ((unsigned char) *env))
++ ++env;
++ }
+ if (strncasecmp (env, "static", 6) == 0)
+ {
+ gomp_global_icv.run_sched_var = GFS_STATIC;
+@@ -130,12 +155,16 @@ parse_schedule (void)
+ else
+ goto unknown;
+
++ if (monotonic == 1
++ || (monotonic == 0 && gomp_global_icv.run_sched_var == GFS_STATIC))
++ gomp_global_icv.run_sched_var |= GFS_MONOTONIC;
++
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ {
+ gomp_global_icv.run_sched_chunk_size
+- = gomp_global_icv.run_sched_var != GFS_STATIC;
++ = (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC;
+ return;
+ }
+ if (*env++ != ',')
+@@ -158,7 +187,8 @@ parse_schedule (void)
+ if ((int)value != value)
+ goto invalid;
+
+- if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
++ if (value == 0
++ && (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC) != GFS_STATIC)
+ value = 1;
+ gomp_global_icv.run_sched_chunk_size = value;
+ return;
+@@ -1066,6 +1096,36 @@ parse_acc_device_type (void)
+ }
+
+ static void
++parse_gomp_openacc_dim (void)
++{
++ /* The syntax is the same as for the -fopenacc-dim compilation option. */
++ const char *var_name = "GOMP_OPENACC_DIM";
++ const char *env_var = getenv (var_name);
++ if (!env_var)
++ return;
++
++ const char *pos = env_var;
++ int i;
++ for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
++ {
++ if (i && *pos++ != ':')
++ break;
++
++ if (*pos == ':')
++ continue;
++
++ const char *eptr;
++ errno = 0;
++ long val = strtol (pos, (char **)&eptr, 10);
++ if (errno || val < 0 || (unsigned)val != val)
++ break;
++
++ goacc_default_dims[i] = (int)val;
++ pos = eptr;
++ }
++}
++
++static void
+ handle_omp_display_env (unsigned long stacksize, int wait_policy)
+ {
+ const char *env;
+@@ -1119,19 +1179,34 @@ handle_omp_display_env (unsigned long st
+ fputs ("'\n", stderr);
+
+ fprintf (stderr, " OMP_SCHEDULE = '");
+- switch (gomp_global_icv.run_sched_var)
++ if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
++ {
++ if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
++ fputs ("MONOTONIC:", stderr);
++ }
++ else if (gomp_global_icv.run_sched_var == GFS_STATIC)
++ fputs ("NONMONOTONIC:", stderr);
++ switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
+ {
+ case GFS_RUNTIME:
+ fputs ("RUNTIME", stderr);
++ if (gomp_global_icv.run_sched_chunk_size != 1)
++ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
+ break;
+ case GFS_STATIC:
+ fputs ("STATIC", stderr);
++ if (gomp_global_icv.run_sched_chunk_size != 0)
++ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
+ break;
+ case GFS_DYNAMIC:
+ fputs ("DYNAMIC", stderr);
++ if (gomp_global_icv.run_sched_chunk_size != 1)
++ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
+ break;
+ case GFS_GUIDED:
+ fputs ("GUIDED", stderr);
++ if (gomp_global_icv.run_sched_chunk_size != 1)
++ fprintf (stderr, ",%d", gomp_global_icv.run_sched_chunk_size);
+ break;
+ case GFS_AUTO:
+ fputs ("AUTO", stderr);
+@@ -1197,6 +1272,10 @@ handle_omp_display_env (unsigned long st
+ gomp_global_icv.default_device_var);
+ fprintf (stderr, " OMP_MAX_TASK_PRIORITY = '%d'\n",
+ gomp_max_task_priority_var);
++ fprintf (stderr, " OMP_DISPLAY_AFFINITY = '%s'\n",
++ gomp_display_affinity_var ? "TRUE" : "FALSE");
++ fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
++ gomp_affinity_format_var);
+
+ if (verbose)
+ {
+@@ -1228,6 +1307,7 @@ initialize_env (void)
+ parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
+ parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
+ parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
++ parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var);
+ parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
+ parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
+ parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
+@@ -1277,6 +1357,13 @@ initialize_env (void)
+ }
+ if (gomp_global_icv.bind_var != omp_proc_bind_false)
+ gomp_init_affinity ();
++
++ {
++ const char *env = getenv ("OMP_AFFINITY_FORMAT");
++ if (env != NULL)
++ gomp_set_affinity_format (env, strlen (env));
++ }
++
+ wait_policy = parse_wait_policy ();
+ if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
+ {
+@@ -1302,7 +1389,6 @@ initialize_env (void)
+
+ /* Not strictly environment related, but ordering constructors is tricky. */
+ pthread_attr_init (&gomp_thread_attr);
+- pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
+
+ if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
+ || parse_stacksize ("GOMP_STACKSIZE", &stacksize)
+@@ -1336,6 +1422,7 @@ initialize_env (void)
+ goacc_device_num = 0;
+
+ parse_acc_device_type ();
++ parse_gomp_openacc_dim ();
+
+ goacc_runtime_initialize ();
+ }
+--- libgomp/fortran.c.jj 2018-04-25 09:40:31.913655581 +0200
++++ libgomp/fortran.c 2019-05-07 18:46:36.491110295 +0200
+@@ -28,6 +28,8 @@
+ #include "libgomp.h"
+ #include "libgomp_f.h"
+ #include
++#include
++#include
+ #include
+
+ #ifdef HAVE_ATTRIBUTE_ALIAS
+@@ -82,6 +84,8 @@ ialias_redirect (omp_get_team_num)
+ ialias_redirect (omp_is_initial_device)
+ ialias_redirect (omp_get_initial_device)
+ ialias_redirect (omp_get_max_task_priority)
++ialias_redirect (omp_pause_resource)
++ialias_redirect (omp_pause_resource_all)
+ #endif
+
+ #ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
+@@ -368,7 +372,9 @@ omp_get_schedule_ (int32_t *kind, int32_
+ omp_sched_t k;
+ int cs;
+ omp_get_schedule (&k, &cs);
+- *kind = k;
++ /* For now mask off GFS_MONOTONIC, because OpenMP 4.5 code will not
++ expect to see it. */
++ *kind = k & ~GFS_MONOTONIC;
+ *chunk_size = cs;
+ }
+
+@@ -378,7 +384,8 @@ omp_get_schedule_8_ (int32_t *kind, int6
+ omp_sched_t k;
+ int cs;
+ omp_get_schedule (&k, &cs);
+- *kind = k;
++ /* See above. */
++ *kind = k & ~GFS_MONOTONIC;
+ *chunk_size = cs;
+ }
+
+@@ -576,3 +583,96 @@ omp_get_max_task_priority_ (void)
+ {
+ return omp_get_max_task_priority ();
+ }
++
++void
++omp_set_affinity_format_ (const char *format, size_t format_len)
++{
++ gomp_set_affinity_format (format, format_len);
++}
++
++int32_t
++omp_get_affinity_format_ (char *buffer, size_t buffer_len)
++{
++ size_t len = strlen (gomp_affinity_format_var);
++ if (buffer_len)
++ {
++ if (len < buffer_len)
++ {
++ memcpy (buffer, gomp_affinity_format_var, len);
++ memset (buffer + len, ' ', buffer_len - len);
++ }
++ else
++ memcpy (buffer, gomp_affinity_format_var, buffer_len);
++ }
++ return len;
++}
++
++void
++omp_display_affinity_ (const char *format, size_t format_len)
++{
++ char *fmt = NULL, fmt_buf[256];
++ char buf[512];
++ if (format_len)
++ {
++ fmt = format_len < 256 ? fmt_buf : gomp_malloc (format_len + 1);
++ memcpy (fmt, format, format_len);
++ fmt[format_len] = '\0';
++ }
++ struct gomp_thread *thr = gomp_thread ();
++ size_t ret
++ = gomp_display_affinity (buf, sizeof buf,
++ format_len ? fmt : gomp_affinity_format_var,
++ gomp_thread_self (), &thr->ts, thr->place);
++ if (ret < sizeof buf)
++ {
++ buf[ret] = '\n';
++ gomp_print_string (buf, ret + 1);
++ }
++ else
++ {
++ char *b = gomp_malloc (ret + 1);
++ gomp_display_affinity (buf, sizeof buf,
++ format_len ? fmt : gomp_affinity_format_var,
++ gomp_thread_self (), &thr->ts, thr->place);
++ b[ret] = '\n';
++ gomp_print_string (b, ret + 1);
++ free (b);
++ }
++ if (fmt && fmt != fmt_buf)
++ free (fmt);
++}
++
++int32_t
++omp_capture_affinity_ (char *buffer, const char *format,
++ size_t buffer_len, size_t format_len)
++{
++ char *fmt = NULL, fmt_buf[256];
++ if (format_len)
++ {
++ fmt = format_len < 256 ? fmt_buf : gomp_malloc (format_len + 1);
++ memcpy (fmt, format, format_len);
++ fmt[format_len] = '\0';
++ }
++ struct gomp_thread *thr = gomp_thread ();
++ size_t ret
++ = gomp_display_affinity (buffer, buffer_len,
++ format_len ? fmt : gomp_affinity_format_var,
++ gomp_thread_self (), &thr->ts, thr->place);
++ if (fmt && fmt != fmt_buf)
++ free (fmt);
++ if (ret < buffer_len)
++ memset (buffer + ret, ' ', buffer_len - ret);
++ return ret;
++}
++
++int32_t
++omp_pause_resource_ (const int32_t *kind, const int32_t *device_num)
++{
++ return omp_pause_resource (*kind, *device_num);
++}
++
++int32_t
++omp_pause_resource_all_ (const int32_t *kind)
++{
++ return omp_pause_resource_all (*kind);
++}
+--- libgomp/configure.tgt.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/configure.tgt 2019-05-07 18:46:36.479110486 +0200
+@@ -18,7 +18,7 @@ if test $gcc_cv_have_tls = yes ; then
+ ;;
+
+ *-*-linux* | *-*-gnu*)
+- XCFLAGS="${XCFLAGS} -ftls-model=initial-exec"
++ XCFLAGS="${XCFLAGS} -ftls-model=initial-exec -DUSING_INITIAL_EXEC_TLS"
+ ;;
+
+ *-*-rtems*)
+--- libgomp/icv-device.c.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/icv-device.c 2019-05-07 18:46:36.513109943 +0200
+@@ -49,20 +49,6 @@ omp_get_num_devices (void)
+ }
+
+ int
+-omp_get_num_teams (void)
+-{
+- /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */
+- return 1;
+-}
+-
+-int
+-omp_get_team_num (void)
+-{
+- /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */
+- return 0;
+-}
+-
+-int
+ omp_is_initial_device (void)
+ {
+ /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */
+@@ -72,6 +58,4 @@ omp_is_initial_device (void)
+ ialias (omp_set_default_device)
+ ialias (omp_get_default_device)
+ ialias (omp_get_num_devices)
+-ialias (omp_get_num_teams)
+-ialias (omp_get_team_num)
+ ialias (omp_is_initial_device)
+--- libgomp/Makefile.in.jj 2018-04-25 09:40:31.320655306 +0200
++++ libgomp/Makefile.in 2019-05-07 20:00:01.082077522 +0200
+@@ -90,7 +90,7 @@ DIST_COMMON = $(top_srcdir)/plugin/Makef
+ $(srcdir)/libgomp.spec.in $(srcdir)/../depcomp
+ @PLUGIN_NVPTX_TRUE@am__append_1 = libgomp-plugin-nvptx.la
+ @PLUGIN_HSA_TRUE@am__append_2 = libgomp-plugin-hsa.la
+-@USE_FORTRAN_TRUE@am__append_3 = openacc.f90
++@USE_FORTRAN_TRUE@am__append_3 = openacc2.f90
+ subdir = .
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+@@ -172,7 +172,7 @@ libgomp_plugin_nvptx_la_LINK = $(LIBTOOL
+ @PLUGIN_NVPTX_TRUE@am_libgomp_plugin_nvptx_la_rpath = -rpath \
+ @PLUGIN_NVPTX_TRUE@ $(toolexeclibdir)
+ libgomp_la_LIBADD =
+-@USE_FORTRAN_TRUE@am__objects_1 = openacc.lo
++@USE_FORTRAN_TRUE@am__objects_1 = openacc2.lo
+ am_libgomp_la_OBJECTS = alloc.lo atomic.lo barrier.lo critical.lo \
+ env.lo error.lo icv.lo icv-device.lo iter.lo iter_ull.lo \
+ loop.lo loop_ull.lo ordered.lo parallel.lo sections.lo \
+@@ -180,7 +180,8 @@ am_libgomp_la_OBJECTS = alloc.lo atomic.
+ sem.lo bar.lo ptrlock.lo time.lo fortran.lo affinity.lo \
+ target.lo splay-tree.lo libgomp-plugin.lo oacc-parallel.lo \
+ oacc-host.lo oacc-init.lo oacc-mem.lo oacc-async.lo \
+- oacc-plugin.lo oacc-cuda.lo priority_queue.lo $(am__objects_1)
++ oacc-plugin.lo oacc-cuda.lo priority_queue.lo affinity-fmt.lo \
++ teams.lo $(am__objects_1)
+ libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
+ DEFAULT_INCLUDES = -I.@am__isrc@
+ depcomp = $(SHELL) $(top_srcdir)/../depcomp
+@@ -380,6 +381,7 @@ mkdir_p = @mkdir_p@
+ multi_basedir = @multi_basedir@
+ offload_additional_lib_paths = @offload_additional_lib_paths@
+ offload_additional_options = @offload_additional_options@
++offload_plugins = @offload_plugins@
+ offload_targets = @offload_targets@
+ oldincludedir = @oldincludedir@
+ pdfdir = @pdfdir@
+@@ -436,7 +438,7 @@ libgomp_la_SOURCES = alloc.c atomic.c ba
+ affinity.c target.c splay-tree.c libgomp-plugin.c \
+ oacc-parallel.c oacc-host.c oacc-init.c oacc-mem.c \
+ oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
+- $(am__append_3)
++ affinity-fmt.c teams.c $(am__append_3)
+
+ # Nvidia PTX OpenACC plugin.
+ @PLUGIN_NVPTX_TRUE@libgomp_plugin_nvptx_version_info = -version-info $(libtool_VERSION)
+@@ -599,6 +601,7 @@ mostlyclean-compile:
+ distclean-compile:
+ -rm -f *.tab.c
+
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity-fmt.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic.Plo@am__quote@
+@@ -638,6 +641,7 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/team.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/teams.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work.Plo@am__quote@
+
+@@ -1292,8 +1296,6 @@ omp_lib_kinds.mod: omp_lib.mod
+ :
+ openacc_kinds.mod: openacc.mod
+ :
+-openacc.mod: openacc.lo
+- :
+ %.mod: %.f90
+ $(FC) $(FCFLAGS) -fsyntax-only $<
+ fortran.lo: libgomp_f.h
+--- libgomp/plugin/cuda/cuda.h.jj 2018-04-25 09:40:31.914655581 +0200
++++ libgomp/plugin/cuda/cuda.h 2019-05-07 18:46:36.533109624 +0200
+@@ -44,6 +44,7 @@ typedef void *CUevent;
+ typedef void *CUfunction;
+ typedef void *CUlinkState;
+ typedef void *CUmodule;
++typedef size_t (*CUoccupancyB2DSize)(int);
+ typedef void *CUstream;
+
+ typedef enum {
+@@ -88,6 +89,7 @@ typedef enum {
+ CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES = 4,
+ CU_JIT_ERROR_LOG_BUFFER = 5,
+ CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES = 6,
++ CU_JIT_OPTIMIZATION_LEVEL = 7,
+ CU_JIT_LOG_VERBOSE = 12
+ } CUjit_option;
+
+@@ -169,6 +171,8 @@ CUresult cuModuleGetGlobal (CUdeviceptr
+ CUresult cuModuleLoad (CUmodule *, const char *);
+ CUresult cuModuleLoadData (CUmodule *, const void *);
+ CUresult cuModuleUnload (CUmodule);
++CUresult cuOccupancyMaxPotentialBlockSize(int *, int *, CUfunction,
++ CUoccupancyB2DSize, size_t, int);
+ CUresult cuStreamCreate (CUstream *, unsigned);
+ #define cuStreamDestroy cuStreamDestroy_v2
+ CUresult cuStreamDestroy (CUstream);
+--- libgomp/plugin/cuda-lib.def.jj 2019-05-07 18:46:36.533109624 +0200
++++ libgomp/plugin/cuda-lib.def 2019-05-07 18:46:36.533109624 +0200
+@@ -0,0 +1,49 @@
++CUDA_ONE_CALL (cuCtxCreate)
++CUDA_ONE_CALL (cuCtxDestroy)
++CUDA_ONE_CALL (cuCtxGetCurrent)
++CUDA_ONE_CALL (cuCtxGetDevice)
++CUDA_ONE_CALL (cuCtxPopCurrent)
++CUDA_ONE_CALL (cuCtxPushCurrent)
++CUDA_ONE_CALL (cuCtxSynchronize)
++CUDA_ONE_CALL (cuDeviceGet)
++CUDA_ONE_CALL (cuDeviceGetAttribute)
++CUDA_ONE_CALL (cuDeviceGetCount)
++CUDA_ONE_CALL (cuEventCreate)
++CUDA_ONE_CALL (cuEventDestroy)
++CUDA_ONE_CALL (cuEventElapsedTime)
++CUDA_ONE_CALL (cuEventQuery)
++CUDA_ONE_CALL (cuEventRecord)
++CUDA_ONE_CALL (cuEventSynchronize)
++CUDA_ONE_CALL (cuFuncGetAttribute)
++CUDA_ONE_CALL_MAYBE_NULL (cuGetErrorString)
++CUDA_ONE_CALL (cuInit)
++CUDA_ONE_CALL (cuLaunchKernel)
++CUDA_ONE_CALL (cuLinkAddData)
++CUDA_ONE_CALL_MAYBE_NULL (cuLinkAddData_v2)
++CUDA_ONE_CALL (cuLinkComplete)
++CUDA_ONE_CALL (cuLinkCreate)
++CUDA_ONE_CALL_MAYBE_NULL (cuLinkCreate_v2)
++CUDA_ONE_CALL (cuLinkDestroy)
++CUDA_ONE_CALL (cuMemAlloc)
++CUDA_ONE_CALL (cuMemAllocHost)
++CUDA_ONE_CALL (cuMemcpy)
++CUDA_ONE_CALL (cuMemcpyDtoDAsync)
++CUDA_ONE_CALL (cuMemcpyDtoH)
++CUDA_ONE_CALL (cuMemcpyDtoHAsync)
++CUDA_ONE_CALL (cuMemcpyHtoD)
++CUDA_ONE_CALL (cuMemcpyHtoDAsync)
++CUDA_ONE_CALL (cuMemFree)
++CUDA_ONE_CALL (cuMemFreeHost)
++CUDA_ONE_CALL (cuMemGetAddressRange)
++CUDA_ONE_CALL (cuMemHostGetDevicePointer)
++CUDA_ONE_CALL (cuModuleGetFunction)
++CUDA_ONE_CALL (cuModuleGetGlobal)
++CUDA_ONE_CALL (cuModuleLoad)
++CUDA_ONE_CALL (cuModuleLoadData)
++CUDA_ONE_CALL (cuModuleUnload)
++CUDA_ONE_CALL_MAYBE_NULL (cuOccupancyMaxPotentialBlockSize)
++CUDA_ONE_CALL (cuStreamCreate)
++CUDA_ONE_CALL (cuStreamDestroy)
++CUDA_ONE_CALL (cuStreamQuery)
++CUDA_ONE_CALL (cuStreamSynchronize)
++CUDA_ONE_CALL (cuStreamWaitEvent)
+--- libgomp/plugin/plugin-nvptx.c.jj 2018-04-25 09:40:31.915655582 +0200
++++ libgomp/plugin/plugin-nvptx.c 2019-05-07 18:46:36.535109592 +0200
+@@ -31,6 +31,7 @@
+ is not clear as to what that state might be. Or how one might
+ propagate it from one thread to another. */
+
++#define _GNU_SOURCE
+ #include "openacc.h"
+ #include "config.h"
+ #include "libgomp-plugin.h"
+@@ -48,60 +49,41 @@
+ #include
+ #include
+
++#if CUDA_VERSION < 6000
++extern CUresult cuGetErrorString (CUresult, const char **);
++#define CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR 82
++#endif
++
++#if CUDA_VERSION >= 6050
++#undef cuLinkCreate
++#undef cuLinkAddData
++CUresult cuLinkAddData (CUlinkState, CUjitInputType, void *, size_t,
++ const char *, unsigned, CUjit_option *, void **);
++CUresult cuLinkCreate (unsigned, CUjit_option *, void **, CUlinkState *);
++#else
++typedef size_t (*CUoccupancyB2DSize)(int);
++CUresult cuLinkAddData_v2 (CUlinkState, CUjitInputType, void *, size_t,
++ const char *, unsigned, CUjit_option *, void **);
++CUresult cuLinkCreate_v2 (unsigned, CUjit_option *, void **, CUlinkState *);
++CUresult cuOccupancyMaxPotentialBlockSize(int *, int *, CUfunction,
++ CUoccupancyB2DSize, size_t, int);
++#endif
++
++#define DO_PRAGMA(x) _Pragma (#x)
++
+ #if PLUGIN_NVPTX_DYNAMIC
+ # include
+
+-# define CUDA_CALLS \
+-CUDA_ONE_CALL (cuCtxCreate) \
+-CUDA_ONE_CALL (cuCtxDestroy) \
+-CUDA_ONE_CALL (cuCtxGetCurrent) \
+-CUDA_ONE_CALL (cuCtxGetDevice) \
+-CUDA_ONE_CALL (cuCtxPopCurrent) \
+-CUDA_ONE_CALL (cuCtxPushCurrent) \
+-CUDA_ONE_CALL (cuCtxSynchronize) \
+-CUDA_ONE_CALL (cuDeviceGet) \
+-CUDA_ONE_CALL (cuDeviceGetAttribute) \
+-CUDA_ONE_CALL (cuDeviceGetCount) \
+-CUDA_ONE_CALL (cuEventCreate) \
+-CUDA_ONE_CALL (cuEventDestroy) \
+-CUDA_ONE_CALL (cuEventElapsedTime) \
+-CUDA_ONE_CALL (cuEventQuery) \
+-CUDA_ONE_CALL (cuEventRecord) \
+-CUDA_ONE_CALL (cuEventSynchronize) \
+-CUDA_ONE_CALL (cuFuncGetAttribute) \
+-CUDA_ONE_CALL (cuGetErrorString) \
+-CUDA_ONE_CALL (cuInit) \
+-CUDA_ONE_CALL (cuLaunchKernel) \
+-CUDA_ONE_CALL (cuLinkAddData) \
+-CUDA_ONE_CALL (cuLinkComplete) \
+-CUDA_ONE_CALL (cuLinkCreate) \
+-CUDA_ONE_CALL (cuLinkDestroy) \
+-CUDA_ONE_CALL (cuMemAlloc) \
+-CUDA_ONE_CALL (cuMemAllocHost) \
+-CUDA_ONE_CALL (cuMemcpy) \
+-CUDA_ONE_CALL (cuMemcpyDtoDAsync) \
+-CUDA_ONE_CALL (cuMemcpyDtoH) \
+-CUDA_ONE_CALL (cuMemcpyDtoHAsync) \
+-CUDA_ONE_CALL (cuMemcpyHtoD) \
+-CUDA_ONE_CALL (cuMemcpyHtoDAsync) \
+-CUDA_ONE_CALL (cuMemFree) \
+-CUDA_ONE_CALL (cuMemFreeHost) \
+-CUDA_ONE_CALL (cuMemGetAddressRange) \
+-CUDA_ONE_CALL (cuMemHostGetDevicePointer)\
+-CUDA_ONE_CALL (cuModuleGetFunction) \
+-CUDA_ONE_CALL (cuModuleGetGlobal) \
+-CUDA_ONE_CALL (cuModuleLoad) \
+-CUDA_ONE_CALL (cuModuleLoadData) \
+-CUDA_ONE_CALL (cuModuleUnload) \
+-CUDA_ONE_CALL (cuStreamCreate) \
+-CUDA_ONE_CALL (cuStreamDestroy) \
+-CUDA_ONE_CALL (cuStreamQuery) \
+-CUDA_ONE_CALL (cuStreamSynchronize) \
+-CUDA_ONE_CALL (cuStreamWaitEvent)
+-# define CUDA_ONE_CALL(call) \
+- __typeof (call) *call;
+ struct cuda_lib_s {
+- CUDA_CALLS
++
++# define CUDA_ONE_CALL(call) \
++ __typeof (call) *call;
++# define CUDA_ONE_CALL_MAYBE_NULL(call) \
++ CUDA_ONE_CALL (call)
++#include "cuda-lib.def"
++# undef CUDA_ONE_CALL
++# undef CUDA_ONE_CALL_MAYBE_NULL
++
+ } cuda_lib;
+
+ /* -1 if init_cuda_lib has not been called yet, false
+@@ -120,24 +102,41 @@ init_cuda_lib (void)
+ cuda_lib_inited = false;
+ if (h == NULL)
+ return false;
+-# undef CUDA_ONE_CALL
+-# define CUDA_ONE_CALL(call) CUDA_ONE_CALL_1 (call)
+-# define CUDA_ONE_CALL_1(call) \
++
++# define CUDA_ONE_CALL(call) CUDA_ONE_CALL_1 (call, false)
++# define CUDA_ONE_CALL_MAYBE_NULL(call) CUDA_ONE_CALL_1 (call, true)
++# define CUDA_ONE_CALL_1(call, allow_null) \
+ cuda_lib.call = dlsym (h, #call); \
+- if (cuda_lib.call == NULL) \
++ if (!allow_null && cuda_lib.call == NULL) \
+ return false;
+- CUDA_CALLS
++#include "cuda-lib.def"
++# undef CUDA_ONE_CALL
++# undef CUDA_ONE_CALL_1
++# undef CUDA_ONE_CALL_MAYBE_NULL
++
+ cuda_lib_inited = true;
+ return true;
+ }
+-# undef CUDA_ONE_CALL
+-# undef CUDA_ONE_CALL_1
+ # define CUDA_CALL_PREFIX cuda_lib.
+ #else
++
++# define CUDA_ONE_CALL(call)
++# define CUDA_ONE_CALL_MAYBE_NULL(call) DO_PRAGMA (weak call)
++#include "cuda-lib.def"
++#undef CUDA_ONE_CALL_MAYBE_NULL
++#undef CUDA_ONE_CALL
++
+ # define CUDA_CALL_PREFIX
+ # define init_cuda_lib() true
+ #endif
+
++#include "secure_getenv.h"
++
++#undef MIN
++#undef MAX
++#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
++#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
++
+ /* Convenience macros for the frequently used CUDA library call and
+ error handling sequence as well as CUDA library calls that
+ do the error checking themselves or don't do it at all. */
+@@ -171,40 +170,42 @@ init_cuda_lib (void)
+ #define CUDA_CALL_NOCHECK(FN, ...) \
+ CUDA_CALL_PREFIX FN (__VA_ARGS__)
+
++#define CUDA_CALL_EXISTS(FN) \
++ CUDA_CALL_PREFIX FN
++
+ static const char *
+ cuda_error (CUresult r)
+ {
+-#if CUDA_VERSION < 7000
+- /* Specified in documentation and present in library from at least
+- 5.5. Not declared in header file prior to 7.0. */
+- extern CUresult cuGetErrorString (CUresult, const char **);
+-#endif
++ const char *fallback = "unknown cuda error";
+ const char *desc;
+
++ if (!CUDA_CALL_EXISTS (cuGetErrorString))
++ return fallback;
++
+ r = CUDA_CALL_NOCHECK (cuGetErrorString, r, &desc);
+- if (r != CUDA_SUCCESS)
+- desc = "unknown cuda error";
++ if (r == CUDA_SUCCESS)
++ return desc;
+
+- return desc;
++ return fallback;
+ }
+
+ static unsigned int instantiated_devices = 0;
+ static pthread_mutex_t ptx_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+
++struct cuda_map
++{
++ CUdeviceptr d;
++ size_t size;
++ bool active;
++ struct cuda_map *next;
++};
++
+ struct ptx_stream
+ {
+ CUstream stream;
+ pthread_t host_thread;
+ bool multithreaded;
+-
+- CUdeviceptr d;
+- void *h;
+- void *h_begin;
+- void *h_end;
+- void *h_next;
+- void *h_prev;
+- void *h_tail;
+-
++ struct cuda_map *map;
+ struct ptx_stream *next;
+ };
+
+@@ -216,12 +217,64 @@ struct nvptx_thread
+ struct ptx_device *ptx_dev;
+ };
+
+-struct map
++static struct cuda_map *
++cuda_map_create (size_t size)
+ {
+- int async;
+- size_t size;
+- char mappings[0];
+-};
++ struct cuda_map *map = GOMP_PLUGIN_malloc (sizeof (struct cuda_map));
++
++ assert (map);
++
++ map->next = NULL;
++ map->size = size;
++ map->active = false;
++
++ CUDA_CALL_ERET (NULL, cuMemAlloc, &map->d, size);
++ assert (map->d);
++
++ return map;
++}
++
++static void
++cuda_map_destroy (struct cuda_map *map)
++{
++ if (map->active)
++ /* Possible reasons for the map to be still active:
++ - the associated async kernel might still be running.
++ - the associated async kernel might have finished, but the
++ corresponding event that should trigger the pop_map has not been
++ processed by event_gc.
++ - the associated sync kernel might have aborted
++
++ The async cases could happen if the user specified an async region
++ without adding a corresponding wait that is guaranteed to be executed
++ (before returning from main, or in an atexit handler).
++ We do not want to deallocate a device pointer that is still being
++ used, so skip it.
++
++ In the sync case, the device pointer is no longer used, but deallocating
++ it using cuMemFree will not succeed, so skip it.
++
++ TODO: Handle this in a more constructive way, by f.i. waiting for streams
++ to finish before de-allocating them (PR88981), or by ensuring the CUDA
++ lib atexit handler is called before rather than after the libgomp plugin
++ atexit handler (PR83795). */
++ ;
++ else
++ CUDA_CALL_NOCHECK (cuMemFree, map->d);
++
++ free (map);
++}
++
++/* The following map_* routines manage the CUDA device memory that
++ contains the data mapping arguments for cuLaunchKernel. Each
++ asynchronous PTX stream may have multiple pending kernel
++ invocations, which are launched in a FIFO order. As such, the map
++ routines maintains a queue of cuLaunchKernel arguments.
++
++ Calls to map_push and map_pop must be guarded by ptx_event_lock.
++ Likewise, calls to map_init and map_fini are guarded by
++ ptx_dev_lock inside GOMP_OFFLOAD_init_device and
++ GOMP_OFFLOAD_fini_device, respectively. */
+
+ static bool
+ map_init (struct ptx_stream *s)
+@@ -229,109 +282,83 @@ map_init (struct ptx_stream *s)
+ int size = getpagesize ();
+
+ assert (s);
+- assert (!s->d);
+- assert (!s->h);
+-
+- CUDA_CALL (cuMemAllocHost, &s->h, size);
+- CUDA_CALL (cuMemHostGetDevicePointer, &s->d, s->h, 0);
+
+- assert (s->h);
++ s->map = cuda_map_create (size);
+
+- s->h_begin = s->h;
+- s->h_end = s->h_begin + size;
+- s->h_next = s->h_prev = s->h_tail = s->h_begin;
+-
+- assert (s->h_next);
+- assert (s->h_end);
+ return true;
+ }
+
+ static bool
+ map_fini (struct ptx_stream *s)
+ {
+- CUDA_CALL (cuMemFreeHost, s->h);
++ assert (s->map->next == NULL);
++
++ cuda_map_destroy (s->map);
++
+ return true;
+ }
+
+ static void
+ map_pop (struct ptx_stream *s)
+ {
+- struct map *m;
++ struct cuda_map *next;
+
+ assert (s != NULL);
+- assert (s->h_next);
+- assert (s->h_prev);
+- assert (s->h_tail);
+-
+- m = s->h_tail;
+-
+- s->h_tail += m->size;
+-
+- if (s->h_tail >= s->h_end)
+- s->h_tail = s->h_begin + (int) (s->h_tail - s->h_end);
+-
+- if (s->h_next == s->h_tail)
+- s->h_prev = s->h_next;
+
+- assert (s->h_next >= s->h_begin);
+- assert (s->h_tail >= s->h_begin);
+- assert (s->h_prev >= s->h_begin);
++ if (s->map->next == NULL)
++ {
++ s->map->active = false;
++ return;
++ }
+
+- assert (s->h_next <= s->h_end);
+- assert (s->h_tail <= s->h_end);
+- assert (s->h_prev <= s->h_end);
++ next = s->map->next;
++ cuda_map_destroy (s->map);
++ s->map = next;
+ }
+
+-static void
+-map_push (struct ptx_stream *s, int async, size_t size, void **h, void **d)
++static CUdeviceptr
++map_push (struct ptx_stream *s, size_t size)
+ {
+- int left;
+- int offset;
+- struct map *m;
++ struct cuda_map *map = NULL;
++ struct cuda_map **t;
+
+- assert (s != NULL);
+-
+- left = s->h_end - s->h_next;
+- size += sizeof (struct map);
+-
+- assert (s->h_prev);
+- assert (s->h_next);
++ assert (s);
++ assert (s->map);
+
+- if (size >= left)
++ /* Select an element to push. */
++ if (s->map->active)
++ map = cuda_map_create (size);
++ else
+ {
+- m = s->h_prev;
+- m->size += left;
+- s->h_next = s->h_begin;
+-
+- if (s->h_next + size > s->h_end)
+- GOMP_PLUGIN_fatal ("unable to push map");
+- }
+-
+- assert (s->h_next);
+-
+- m = s->h_next;
+- m->async = async;
+- m->size = size;
++ /* Pop the inactive front element. */
++ struct cuda_map *pop = s->map;
++ s->map = pop->next;
++ pop->next = NULL;
+
+- offset = (void *)&m->mappings[0] - s->h;
++ if (pop->size < size)
++ {
++ cuda_map_destroy (pop);
+
+- *d = (void *)(s->d + offset);
+- *h = (void *)(s->h + offset);
++ map = cuda_map_create (size);
++ }
++ else
++ map = pop;
++ }
+
+- s->h_prev = s->h_next;
+- s->h_next += size;
++ /* Check that the element is as expected. */
++ assert (map->next == NULL);
++ assert (!map->active);
+
+- assert (s->h_prev);
+- assert (s->h_next);
++ /* Mark the element active. */
++ map->active = true;
+
+- assert (s->h_next >= s->h_begin);
+- assert (s->h_tail >= s->h_begin);
+- assert (s->h_prev >= s->h_begin);
+- assert (s->h_next <= s->h_end);
+- assert (s->h_tail <= s->h_end);
+- assert (s->h_prev <= s->h_end);
++ /* Push the element to the back of the list. */
++ for (t = &s->map; (*t) != NULL; t = &(*t)->next)
++ ;
++ assert (t != NULL && *t == NULL);
++ *t = map;
+
+- return;
++ return map->d;
+ }
+
+ /* Target data function launch information. */
+@@ -411,6 +438,10 @@ struct ptx_device
+ int num_sms;
+ int regs_per_block;
+ int regs_per_sm;
++ int warp_size;
++ int max_threads_per_block;
++ int max_threads_per_multiprocessor;
++ int default_dims[GOMP_DIM_MAX];
+
+ struct ptx_image_data *images; /* Images loaded on device. */
+ pthread_mutex_t image_lock; /* Lock for above list. */
+@@ -458,8 +489,6 @@ init_streams_for_device (struct ptx_devi
+ null_stream->stream = NULL;
+ null_stream->host_thread = pthread_self ();
+ null_stream->multithreaded = true;
+- null_stream->d = (CUdeviceptr) NULL;
+- null_stream->h = NULL;
+ if (!map_init (null_stream))
+ return false;
+
+@@ -594,8 +623,6 @@ select_stream_for_async (int async, pthr
+ s->host_thread = thread;
+ s->multithreaded = false;
+
+- s->d = (CUdeviceptr) NULL;
+- s->h = NULL;
+ if (!map_init (s))
+ {
+ pthread_mutex_unlock (&ptx_dev->stream_lock);
+@@ -777,9 +804,11 @@ nvptx_open_device (int n)
+ &pi, CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK, dev);
+ ptx_dev->regs_per_block = pi;
+
+- /* CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR = 82 is defined only
++ /* CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR is defined only
+ in CUDA 6.0 and newer. */
+- r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &pi, 82, dev);
++ r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &pi,
++ CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR,
++ dev);
+ /* Fallback: use limit of registers per block, which is usually equal. */
+ if (r == CUDA_ERROR_INVALID_VALUE)
+ pi = ptx_dev->regs_per_block;
+@@ -797,12 +826,24 @@ nvptx_open_device (int n)
+ GOMP_PLUGIN_error ("Only warp size 32 is supported");
+ return NULL;
+ }
++ ptx_dev->warp_size = pi;
++
++ CUDA_CALL_ERET (NULL, cuDeviceGetAttribute, &pi,
++ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK, dev);
++ ptx_dev->max_threads_per_block = pi;
++
++ CUDA_CALL_ERET (NULL, cuDeviceGetAttribute, &pi,
++ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR, dev);
++ ptx_dev->max_threads_per_multiprocessor = pi;
+
+ r = CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &async_engines,
+ CU_DEVICE_ATTRIBUTE_ASYNC_ENGINE_COUNT, dev);
+ if (r != CUDA_SUCCESS)
+ async_engines = 1;
+
++ for (int i = 0; i != GOMP_DIM_MAX; i++)
++ ptx_dev->default_dims[i] = 0;
++
+ ptx_dev->images = NULL;
+ pthread_mutex_init (&ptx_dev->image_lock, NULL);
+
+@@ -876,12 +917,42 @@ notify_var (const char *var_name, const
+ GOMP_PLUGIN_debug (0, "%s: '%s'\n", var_name, env_var);
+ }
+
++static void
++process_GOMP_NVPTX_JIT (intptr_t *gomp_nvptx_o)
++{
++ const char *var_name = "GOMP_NVPTX_JIT";
++ const char *env_var = secure_getenv (var_name);
++ notify_var (var_name, env_var);
++
++ if (env_var == NULL)
++ return;
++
++ const char *c = env_var;
++ while (*c != '\0')
++ {
++ while (*c == ' ')
++ c++;
++
++ if (c[0] == '-' && c[1] == 'O'
++ && '0' <= c[2] && c[2] <= '4'
++ && (c[3] == '\0' || c[3] == ' '))
++ {
++ *gomp_nvptx_o = c[2] - '0';
++ c += 3;
++ continue;
++ }
++
++ GOMP_PLUGIN_error ("Error parsing %s", var_name);
++ break;
++ }
++}
++
+ static bool
+ link_ptx (CUmodule *module, const struct targ_ptx_obj *ptx_objs,
+ unsigned num_objs)
+ {
+- CUjit_option opts[6];
+- void *optvals[6];
++ CUjit_option opts[7];
++ void *optvals[7];
+ float elapsed = 0.0;
+ char elog[1024];
+ char ilog[16384];
+@@ -908,16 +979,41 @@ link_ptx (CUmodule *module, const struct
+ opts[5] = CU_JIT_LOG_VERBOSE;
+ optvals[5] = (void *) 1;
+
+- CUDA_CALL (cuLinkCreate, 6, opts, optvals, &linkstate);
++ static intptr_t gomp_nvptx_o = -1;
++
++ static bool init_done = false;
++ if (!init_done)
++ {
++ process_GOMP_NVPTX_JIT (&gomp_nvptx_o);
++ init_done = true;
++ }
++
++ int nopts = 6;
++ if (gomp_nvptx_o != -1)
++ {
++ opts[nopts] = CU_JIT_OPTIMIZATION_LEVEL;
++ optvals[nopts] = (void *) gomp_nvptx_o;
++ nopts++;
++ }
++
++ if (CUDA_CALL_EXISTS (cuLinkCreate_v2))
++ CUDA_CALL (cuLinkCreate_v2, nopts, opts, optvals, &linkstate);
++ else
++ CUDA_CALL (cuLinkCreate, nopts, opts, optvals, &linkstate);
+
+ for (; num_objs--; ptx_objs++)
+ {
+ /* cuLinkAddData's 'data' argument erroneously omits the const
+ qualifier. */
+ GOMP_PLUGIN_debug (0, "Loading:\n---\n%s\n---\n", ptx_objs->code);
+- r = CUDA_CALL_NOCHECK (cuLinkAddData, linkstate, CU_JIT_INPUT_PTX,
+- (char *) ptx_objs->code, ptx_objs->size,
+- 0, 0, 0, 0);
++ if (CUDA_CALL_EXISTS (cuLinkAddData_v2))
++ r = CUDA_CALL_NOCHECK (cuLinkAddData_v2, linkstate, CU_JIT_INPUT_PTX,
++ (char *) ptx_objs->code, ptx_objs->size,
++ 0, 0, 0, 0);
++ else
++ r = CUDA_CALL_NOCHECK (cuLinkAddData, linkstate, CU_JIT_INPUT_PTX,
++ (char *) ptx_objs->code, ptx_objs->size,
++ 0, 0, 0, 0);
+ if (r != CUDA_SUCCESS)
+ {
+ GOMP_PLUGIN_error ("Link error log %s\n", &elog[0]);
+@@ -1067,8 +1163,10 @@ nvptx_exec (void (*fn), size_t mapnum, v
+ int i;
+ struct ptx_stream *dev_str;
+ void *kargs[1];
+- void *hp, *dp;
++ void *hp;
++ CUdeviceptr dp = 0;
+ struct nvptx_thread *nvthd = nvptx_thread ();
++ int warp_size = nvthd->ptx_dev->warp_size;
+ const char *maybe_abort_msg = "(perhaps abort was called)";
+
+ function = targ_fn->fn;
+@@ -1090,68 +1188,36 @@ nvptx_exec (void (*fn), size_t mapnum, v
+
+ if (seen_zero)
+ {
+- /* See if the user provided GOMP_OPENACC_DIM environment
+- variable to specify runtime defaults. */
+- static int default_dims[GOMP_DIM_MAX];
+-
+ pthread_mutex_lock (&ptx_dev_lock);
+- if (!default_dims[0])
+- {
+- const char *var_name = "GOMP_OPENACC_DIM";
+- /* We only read the environment variable once. You can't
+- change it in the middle of execution. The syntax is
+- the same as for the -fopenacc-dim compilation option. */
+- const char *env_var = getenv (var_name);
+- notify_var (var_name, env_var);
+- if (env_var)
+- {
+- const char *pos = env_var;
+
+- for (i = 0; *pos && i != GOMP_DIM_MAX; i++)
+- {
+- if (i && *pos++ != ':')
+- break;
+- if (*pos != ':')
+- {
+- const char *eptr;
+-
+- errno = 0;
+- long val = strtol (pos, (char **)&eptr, 10);
+- if (errno || val < 0 || (unsigned)val != val)
+- break;
+- default_dims[i] = (int)val;
+- pos = eptr;
+- }
+- }
+- }
++ static int gomp_openacc_dims[GOMP_DIM_MAX];
++ if (!gomp_openacc_dims[0])
++ {
++ /* See if the user provided GOMP_OPENACC_DIM environment
++ variable to specify runtime defaults. */
++ for (int i = 0; i < GOMP_DIM_MAX; ++i)
++ gomp_openacc_dims[i] = GOMP_PLUGIN_acc_default_dim (i);
++ }
+
+- int warp_size, block_size, dev_size, cpu_size;
+- CUdevice dev = nvptx_thread()->ptx_dev->dev;
+- /* 32 is the default for known hardware. */
+- int gang = 0, worker = 32, vector = 32;
+- CUdevice_attribute cu_tpb, cu_ws, cu_mpc, cu_tpm;
+-
+- cu_tpb = CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK;
+- cu_ws = CU_DEVICE_ATTRIBUTE_WARP_SIZE;
+- cu_mpc = CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT;
+- cu_tpm = CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR;
+-
+- if (CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &block_size, cu_tpb,
+- dev) == CUDA_SUCCESS
+- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &warp_size, cu_ws,
+- dev) == CUDA_SUCCESS
+- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &dev_size, cu_mpc,
+- dev) == CUDA_SUCCESS
+- && CUDA_CALL_NOCHECK (cuDeviceGetAttribute, &cpu_size, cu_tpm,
+- dev) == CUDA_SUCCESS)
+- {
+- GOMP_PLUGIN_debug (0, " warp_size=%d, block_size=%d,"
+- " dev_size=%d, cpu_size=%d\n",
+- warp_size, block_size, dev_size, cpu_size);
+- gang = (cpu_size / block_size) * dev_size;
+- worker = block_size / warp_size;
+- vector = warp_size;
+- }
++ if (!nvthd->ptx_dev->default_dims[0])
++ {
++ int default_dims[GOMP_DIM_MAX];
++ for (int i = 0; i < GOMP_DIM_MAX; ++i)
++ default_dims[i] = gomp_openacc_dims[i];
++
++ int gang, worker, vector;
++ {
++ int block_size = nvthd->ptx_dev->max_threads_per_block;
++ int cpu_size = nvthd->ptx_dev->max_threads_per_multiprocessor;
++ int dev_size = nvthd->ptx_dev->num_sms;
++ GOMP_PLUGIN_debug (0, " warp_size=%d, block_size=%d,"
++ " dev_size=%d, cpu_size=%d\n",
++ warp_size, block_size, dev_size, cpu_size);
++
++ gang = (cpu_size / block_size) * dev_size;
++ worker = block_size / warp_size;
++ vector = warp_size;
++ }
+
+ /* There is no upper bound on the gang size. The best size
+ matches the hardware configuration. Logical gangs are
+@@ -1172,29 +1238,150 @@ nvptx_exec (void (*fn), size_t mapnum, v
+ default_dims[GOMP_DIM_GANG],
+ default_dims[GOMP_DIM_WORKER],
+ default_dims[GOMP_DIM_VECTOR]);
++
++ for (i = 0; i != GOMP_DIM_MAX; i++)
++ nvthd->ptx_dev->default_dims[i] = default_dims[i];
+ }
+ pthread_mutex_unlock (&ptx_dev_lock);
+
+- for (i = 0; i != GOMP_DIM_MAX; i++)
+- if (!dims[i])
+- dims[i] = default_dims[i];
+- }
+-
+- /* This reserves a chunk of a pre-allocated page of memory mapped on both
+- the host and the device. HP is a host pointer to the new chunk, and DP is
+- the corresponding device pointer. */
+- map_push (dev_str, async, mapnum * sizeof (void *), &hp, &dp);
+-
+- GOMP_PLUGIN_debug (0, " %s: prepare mappings\n", __FUNCTION__);
+-
+- /* Copy the array of arguments to the mapped page. */
+- for (i = 0; i < mapnum; i++)
+- ((void **) hp)[i] = devaddrs[i];
+-
+- /* Copy the (device) pointers to arguments to the device (dp and hp might in
+- fact have the same value on a unified-memory system). */
+- CUDA_CALL_ASSERT (cuMemcpy, (CUdeviceptr) dp, (CUdeviceptr) hp,
+- mapnum * sizeof (void *));
++ {
++ bool default_dim_p[GOMP_DIM_MAX];
++ for (i = 0; i != GOMP_DIM_MAX; i++)
++ default_dim_p[i] = !dims[i];
++
++ if (!CUDA_CALL_EXISTS (cuOccupancyMaxPotentialBlockSize))
++ {
++ for (i = 0; i != GOMP_DIM_MAX; i++)
++ if (default_dim_p[i])
++ dims[i] = nvthd->ptx_dev->default_dims[i];
++
++ if (default_dim_p[GOMP_DIM_VECTOR])
++ dims[GOMP_DIM_VECTOR]
++ = MIN (dims[GOMP_DIM_VECTOR],
++ (targ_fn->max_threads_per_block / warp_size
++ * warp_size));
++
++ if (default_dim_p[GOMP_DIM_WORKER])
++ dims[GOMP_DIM_WORKER]
++ = MIN (dims[GOMP_DIM_WORKER],
++ targ_fn->max_threads_per_block / dims[GOMP_DIM_VECTOR]);
++ }
++ else
++ {
++ /* Handle the case that the compiler allows the runtime to choose
++ the vector-length conservatively, by ignoring
++ gomp_openacc_dims[GOMP_DIM_VECTOR]. TODO: actually handle
++ it. */
++ int vectors = 0;
++ /* TODO: limit gomp_openacc_dims[GOMP_DIM_WORKER] such that that
++ gomp_openacc_dims[GOMP_DIM_WORKER] * actual_vectors does not
++ exceed targ_fn->max_threads_per_block. */
++ int workers = gomp_openacc_dims[GOMP_DIM_WORKER];
++ int gangs = gomp_openacc_dims[GOMP_DIM_GANG];
++ int grids, blocks;
++
++ CUDA_CALL_ASSERT (cuOccupancyMaxPotentialBlockSize, &grids,
++ &blocks, function, NULL, 0,
++ dims[GOMP_DIM_WORKER] * dims[GOMP_DIM_VECTOR]);
++ GOMP_PLUGIN_debug (0, "cuOccupancyMaxPotentialBlockSize: "
++ "grid = %d, block = %d\n", grids, blocks);
++
++ /* Keep the num_gangs proportional to the block size. In
++ the case were a block size is limited by shared-memory
++ or the register file capacity, the runtime will not
++ excessively over assign gangs to the multiprocessor
++ units if their state is going to be swapped out even
++ more than necessary. The constant factor 2 is there to
++ prevent threads from idling when there is insufficient
++ work for them. */
++ if (gangs == 0)
++ gangs = 2 * grids * (blocks / warp_size);
++
++ if (vectors == 0)
++ vectors = warp_size;
++
++ if (workers == 0)
++ {
++ int actual_vectors = (default_dim_p[GOMP_DIM_VECTOR]
++ ? vectors
++ : dims[GOMP_DIM_VECTOR]);
++ workers = blocks / actual_vectors;
++ workers = MAX (workers, 1);
++ /* If we need a per-worker barrier ... . */
++ if (actual_vectors > 32)
++ /* Don't use more barriers than available. */
++ workers = MIN (workers, 15);
++ }
++
++ for (i = 0; i != GOMP_DIM_MAX; i++)
++ if (default_dim_p[i])
++ switch (i)
++ {
++ case GOMP_DIM_GANG: dims[i] = gangs; break;
++ case GOMP_DIM_WORKER: dims[i] = workers; break;
++ case GOMP_DIM_VECTOR: dims[i] = vectors; break;
++ default: GOMP_PLUGIN_fatal ("invalid dim");
++ }
++ }
++ }
++ }
++
++ /* Check if the accelerator has sufficient hardware resources to
++ launch the offloaded kernel. */
++ if (dims[GOMP_DIM_WORKER] * dims[GOMP_DIM_VECTOR]
++ > targ_fn->max_threads_per_block)
++ {
++ const char *msg
++ = ("The Nvidia accelerator has insufficient resources to launch '%s'"
++ " with num_workers = %d and vector_length = %d"
++ "; "
++ "recompile the program with 'num_workers = x and vector_length = y'"
++ " on that offloaded region or '-fopenacc-dim=:x:y' where"
++ " x * y <= %d"
++ ".\n");
++ GOMP_PLUGIN_fatal (msg, targ_fn->launch->fn, dims[GOMP_DIM_WORKER],
++ dims[GOMP_DIM_VECTOR], targ_fn->max_threads_per_block);
++ }
++
++ /* Check if the accelerator has sufficient barrier resources to
++ launch the offloaded kernel. */
++ if (dims[GOMP_DIM_WORKER] > 15 && dims[GOMP_DIM_VECTOR] > 32)
++ {
++ const char *msg
++ = ("The Nvidia accelerator has insufficient barrier resources to launch"
++ " '%s' with num_workers = %d and vector_length = %d"
++ "; "
++ "recompile the program with 'num_workers = x' on that offloaded"
++ " region or '-fopenacc-dim=:x:' where x <= 15"
++ "; "
++ "or, recompile the program with 'vector_length = 32' on that"
++ " offloaded region or '-fopenacc-dim=::32'"
++ ".\n");
++ GOMP_PLUGIN_fatal (msg, targ_fn->launch->fn, dims[GOMP_DIM_WORKER],
++ dims[GOMP_DIM_VECTOR]);
++ }
++
++ if (mapnum > 0)
++ {
++ /* This reserves a chunk of a pre-allocated page of memory mapped on both
++ the host and the device. HP is a host pointer to the new chunk, and DP is
++ the corresponding device pointer. */
++ pthread_mutex_lock (&ptx_event_lock);
++ dp = map_push (dev_str, mapnum * sizeof (void *));
++ pthread_mutex_unlock (&ptx_event_lock);
++
++ GOMP_PLUGIN_debug (0, " %s: prepare mappings\n", __FUNCTION__);
++
++ /* Copy the array of arguments to the mapped page. */
++ hp = alloca(sizeof(void *) * mapnum);
++ for (i = 0; i < mapnum; i++)
++ ((void **) hp)[i] = devaddrs[i];
++
++ /* Copy the (device) pointers to arguments to the device */
++ CUDA_CALL_ASSERT (cuMemcpyHtoD, dp, hp,
++ mapnum * sizeof (void *));
++ }
++
+ GOMP_PLUGIN_debug (0, " %s: kernel %s: launch"
+ " gangs=%u, workers=%u, vectors=%u\n",
+ __FUNCTION__, targ_fn->launch->fn, dims[GOMP_DIM_GANG],
+@@ -1239,7 +1426,8 @@ nvptx_exec (void (*fn), size_t mapnum, v
+
+ CUDA_CALL_ASSERT (cuEventRecord, *e, dev_str->stream);
+
+- event_add (PTX_EVT_KNL, e, (void *)dev_str, 0);
++ if (mapnum > 0)
++ event_add (PTX_EVT_KNL, e, (void *)dev_str, 0);
+ }
+ #else
+ r = CUDA_CALL_NOCHECK (cuCtxSynchronize, );
+@@ -1256,7 +1444,10 @@ nvptx_exec (void (*fn), size_t mapnum, v
+ #ifndef DISABLE_ASYNC
+ if (async < acc_async_noval)
+ #endif
+- map_pop (dev_str);
++ {
++ if (mapnum > 0)
++ map_pop (dev_str);
++ }
+ }
+
+ void * openacc_get_current_cuda_context (void);
+@@ -1415,9 +1606,8 @@ nvptx_async_test (int async)
+ struct ptx_stream *s;
+
+ s = select_stream_for_async (async, pthread_self (), false, NULL);
+-
+ if (!s)
+- GOMP_PLUGIN_fatal ("unknown async %d", async);
++ return 1;
+
+ r = CUDA_CALL_NOCHECK (cuStreamQuery, s->stream);
+ if (r == CUDA_SUCCESS)
+@@ -1472,7 +1662,7 @@ nvptx_wait (int async)
+
+ s = select_stream_for_async (async, pthread_self (), false, NULL);
+ if (!s)
+- GOMP_PLUGIN_fatal ("unknown async %d", async);
++ return;
+
+ CUDA_CALL_ASSERT (cuStreamSynchronize, s->stream);
+
+@@ -1486,16 +1676,17 @@ nvptx_wait_async (int async1, int async2
+ struct ptx_stream *s1, *s2;
+ pthread_t self = pthread_self ();
+
++ s1 = select_stream_for_async (async1, self, false, NULL);
++ if (!s1)
++ return;
++
+ /* The stream that is waiting (rather than being waited for) doesn't
+ necessarily have to exist already. */
+ s2 = select_stream_for_async (async2, self, true, NULL);
+
+- s1 = select_stream_for_async (async1, self, false, NULL);
+- if (!s1)
+- GOMP_PLUGIN_fatal ("invalid async 1\n");
+-
++ /* A stream is always synchronized with itself. */
+ if (s1 == s2)
+- GOMP_PLUGIN_fatal ("identical parameters");
++ return;
+
+ e = (CUevent *) GOMP_PLUGIN_malloc (sizeof (CUevent));
+
+@@ -1629,8 +1820,14 @@ nvptx_set_cuda_stream (int async, void *
+ pthread_t self = pthread_self ();
+ struct nvptx_thread *nvthd = nvptx_thread ();
+
+- if (async < 0)
+- GOMP_PLUGIN_fatal ("bad async %d", async);
++ /* Due to the "null_stream" usage for "acc_async_sync", this cannot be used
++ to change the stream handle associated with "acc_async_sync". */
++ if (async == acc_async_sync)
++ {
++ GOMP_PLUGIN_debug (0, "Refusing request to set CUDA stream associated"
++ " with \"acc_async_sync\"\n");
++ return 0;
++ }
+
+ pthread_mutex_lock (&nvthd->ptx_dev->stream_lock);
+
+@@ -1739,6 +1936,12 @@ GOMP_OFFLOAD_fini_device (int n)
+ instantiated_devices--;
+ }
+
++ if (instantiated_devices == 0)
++ {
++ free (ptx_devices);
++ ptx_devices = NULL;
++ }
++
+ pthread_mutex_unlock (&ptx_dev_lock);
+ return true;
+ }
+--- libgomp/plugin/configfrag.ac.jj 2018-04-25 09:40:31.914655581 +0200
++++ libgomp/plugin/configfrag.ac 2019-05-07 18:46:36.533109624 +0200
+@@ -26,8 +26,6 @@
+ # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ # .
+
+-offload_targets=
+-AC_SUBST(offload_targets)
+ plugin_support=yes
+ AC_CHECK_LIB(dl, dlsym, , [plugin_support=no])
+ if test x"$plugin_support" = xyes; then
+@@ -59,7 +57,11 @@ AC_ARG_WITH(cuda-driver-lib,
+ [AS_HELP_STRING([--with-cuda-driver-lib=PATH],
+ [specify directory for the installed CUDA driver library])])
+ case "x$with_cuda_driver" in
+- x | xno) ;;
++ x) ;;
++ xno)
++ CUDA_DRIVER_INCLUDE=no
++ CUDA_DRIVER_LIB=no
++ ;;
+ *) CUDA_DRIVER_INCLUDE=$with_cuda_driver/include
+ CUDA_DRIVER_LIB=$with_cuda_driver/lib
+ ;;
+@@ -70,10 +72,12 @@ fi
+ if test "x$with_cuda_driver_lib" != x; then
+ CUDA_DRIVER_LIB=$with_cuda_driver_lib
+ fi
+-if test "x$CUDA_DRIVER_INCLUDE" != x; then
++if test "x$CUDA_DRIVER_INCLUDE" != x \
++ && test "x$CUDA_DRIVER_INCLUDE" != xno; then
+ CUDA_DRIVER_CPPFLAGS=-I$CUDA_DRIVER_INCLUDE
+ fi
+-if test "x$CUDA_DRIVER_LIB" != x; then
++if test "x$CUDA_DRIVER_LIB" != x \
++ && test "x$CUDA_DRIVER_LIB" != xno; then
+ CUDA_DRIVER_LDFLAGS=-L$CUDA_DRIVER_LIB
+ fi
+
+@@ -133,7 +137,13 @@ AC_SUBST(PLUGIN_HSA_CPPFLAGS)
+ AC_SUBST(PLUGIN_HSA_LDFLAGS)
+ AC_SUBST(PLUGIN_HSA_LIBS)
+
+-# Get offload targets and path to install tree of offloading compiler.
++# Parse '--enable-offload-targets', figure out the corresponding libgomp
++# plugins, and configure to find the corresponding offload compilers.
++# 'offload_plugins' and 'offload_targets' will be populated in the same order.
++offload_plugins=
++offload_targets=
++AC_SUBST(offload_plugins)
++AC_SUBST(offload_targets)
+ offload_additional_options=
+ offload_additional_lib_paths=
+ AC_SUBST(offload_additional_options)
+@@ -142,36 +152,41 @@ if test x"$enable_offload_targets" != x;
+ for tgt in `echo $enable_offload_targets | sed -e 's#,# #g'`; do
+ tgt_dir=`echo $tgt | grep '=' | sed 's/.*=//'`
+ tgt=`echo $tgt | sed 's/=.*//'`
+- tgt_name=
++ tgt_plugin=
+ case $tgt in
+ *-intelmic-* | *-intelmicemul-*)
+- tgt_name=intelmic
++ tgt_plugin=intelmic
+ ;;
+ nvptx*)
+- tgt_name=nvptx
++ tgt_plugin=nvptx
+ PLUGIN_NVPTX=$tgt
+- PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS
+- PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS
+- PLUGIN_NVPTX_LIBS='-lcuda'
+-
+- PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS
+- CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS"
+- PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS
+- LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS"
+- PLUGIN_NVPTX_save_LIBS=$LIBS
+- LIBS="$PLUGIN_NVPTX_LIBS $LIBS"
+- AC_LINK_IFELSE(
+- [AC_LANG_PROGRAM(
+- [#include "cuda.h"],
+- [CUresult r = cuCtxPushCurrent (NULL);])],
+- [PLUGIN_NVPTX=1])
+- CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS
+- LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS
+- LIBS=$PLUGIN_NVPTX_save_LIBS
++ if test "x$CUDA_DRIVER_LIB" != xno \
++ && test "x$CUDA_DRIVER_LIB" != xno; then
++ PLUGIN_NVPTX_CPPFLAGS=$CUDA_DRIVER_CPPFLAGS
++ PLUGIN_NVPTX_LDFLAGS=$CUDA_DRIVER_LDFLAGS
++ PLUGIN_NVPTX_LIBS='-lcuda'
++
++ PLUGIN_NVPTX_save_CPPFLAGS=$CPPFLAGS
++ CPPFLAGS="$PLUGIN_NVPTX_CPPFLAGS $CPPFLAGS"
++ PLUGIN_NVPTX_save_LDFLAGS=$LDFLAGS
++ LDFLAGS="$PLUGIN_NVPTX_LDFLAGS $LDFLAGS"
++ PLUGIN_NVPTX_save_LIBS=$LIBS
++ LIBS="$PLUGIN_NVPTX_LIBS $LIBS"
++ AC_LINK_IFELSE(
++ [AC_LANG_PROGRAM(
++ [#include "cuda.h"],
++ [CUresult r = cuCtxPushCurrent (NULL);])],
++ [PLUGIN_NVPTX=1])
++ CPPFLAGS=$PLUGIN_NVPTX_save_CPPFLAGS
++ LDFLAGS=$PLUGIN_NVPTX_save_LDFLAGS
++ LIBS=$PLUGIN_NVPTX_save_LIBS
++ fi
+ case $PLUGIN_NVPTX in
+ nvptx*)
+- if test "x$CUDA_DRIVER_INCLUDE" = x \
+- && test "x$CUDA_DRIVER_LIB" = x; then
++ if (test "x$CUDA_DRIVER_INCLUDE" = x \
++ || test "x$CUDA_DRIVER_INCLUDE" = xno) \
++ && (test "x$CUDA_DRIVER_LIB" = x \
++ || test "x$CUDA_DRIVER_LIB" = xno); then
+ PLUGIN_NVPTX=1
+ PLUGIN_NVPTX_CPPFLAGS='-I$(srcdir)/plugin/cuda'
+ PLUGIN_NVPTX_LIBS='-ldl'
+@@ -191,7 +206,7 @@ if test x"$enable_offload_targets" != x;
+ PLUGIN_HSA=0
+ ;;
+ *)
+- tgt_name=hsa
++ tgt_plugin=hsa
+ PLUGIN_HSA=$tgt
+ PLUGIN_HSA_CPPFLAGS=$HSA_RUNTIME_CPPFLAGS
+ PLUGIN_HSA_LDFLAGS="$HSA_RUNTIME_LDFLAGS"
+@@ -209,7 +224,7 @@ if test x"$enable_offload_targets" != x;
+ LDFLAGS=$PLUGIN_HSA_save_LDFLAGS
+ LIBS=$PLUGIN_HSA_save_LIBS
+ case $PLUGIN_HSA in
+- hsa*)
++ hsa*)
+ HSA_PLUGIN=0
+ AC_MSG_ERROR([HSA run-time package required for HSA support])
+ ;;
+@@ -226,16 +241,19 @@ if test x"$enable_offload_targets" != x;
+ AC_MSG_ERROR([unknown offload target specified])
+ ;;
+ esac
+- if test x"$tgt_name" = x; then
+- # Don't configure libgomp for this offloading target if we don't build
+- # the corresponding plugin.
++ if test x"$tgt_plugin" = x; then
++ # Not configuring libgomp for this offload target if we're not building
++ # the corresponding offload plugin.
+ continue
+- elif test x"$offload_targets" = x; then
+- offload_targets=$tgt_name
++ elif test x"$offload_plugins" = x; then
++ offload_plugins=$tgt_plugin
++ offload_targets=$tgt
+ else
+- offload_targets=$offload_targets,$tgt_name
++ offload_plugins=$offload_plugins,$tgt_plugin
++ offload_targets=$offload_targets,$tgt
+ fi
+- if test "$tgt_name" = hsa; then
++ # Configure additional search paths.
++ if test "$tgt_plugin" = hsa; then
+ # Offloading compilation is all handled by the target compiler.
+ :
+ elif test x"$tgt_dir" != x; then
+@@ -247,8 +265,8 @@ if test x"$enable_offload_targets" != x;
+ fi
+ done
+ fi
+-AC_DEFINE_UNQUOTED(OFFLOAD_TARGETS, "$offload_targets",
+- [Define to offload targets, separated by commas.])
++AC_DEFINE_UNQUOTED(OFFLOAD_PLUGINS, "$offload_plugins",
++ [Define to offload plugins, separated by commas.])
+ AM_CONDITIONAL([PLUGIN_NVPTX], [test $PLUGIN_NVPTX = 1])
+ AC_DEFINE_UNQUOTED([PLUGIN_NVPTX], [$PLUGIN_NVPTX],
+ [Define to 1 if the NVIDIA plugin is built, 0 if not.])
+--- libgomp/affinity-fmt.c.jj 2019-05-07 18:46:36.285113585 +0200
++++ libgomp/affinity-fmt.c 2019-05-07 18:46:36.285113585 +0200
+@@ -0,0 +1,495 @@
++/* Copyright (C) 2018-2019 Free Software Foundation, Inc.
++ Contributed by Jakub Jelinek .
++
++ This file is part of the GNU Offloading and Multi Processing Library
++ (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ . */
++
++#include "libgomp.h"
++#include
++#include
++#include
++#ifdef HAVE_UNISTD_H
++#include
++#endif
++#ifdef HAVE_INTTYPES_H
++# include /* For PRIx64. */
++#endif
++#ifdef HAVE_UNAME
++#include
++#endif
++
++void
++gomp_print_string (const char *str, size_t len)
++{
++ fwrite (str, 1, len, stderr);
++}
++
++void
++gomp_set_affinity_format (const char *format, size_t len)
++{
++ if (len < gomp_affinity_format_len)
++ memcpy (gomp_affinity_format_var, format, len);
++ else
++ {
++ char *p;
++ if (gomp_affinity_format_len)
++ p = gomp_realloc (gomp_affinity_format_var, len + 1);
++ else
++ p = gomp_malloc (len + 1);
++ memcpy (p, format, len);
++ gomp_affinity_format_var = p;
++ gomp_affinity_format_len = len + 1;
++ }
++ gomp_affinity_format_var[len] = '\0';
++}
++
++void
++omp_set_affinity_format (const char *format)
++{
++ gomp_set_affinity_format (format, strlen (format));
++}
++
++size_t
++omp_get_affinity_format (char *buffer, size_t size)
++{
++ size_t len = strlen (gomp_affinity_format_var);
++ if (size)
++ {
++ if (len < size)
++ memcpy (buffer, gomp_affinity_format_var, len + 1);
++ else
++ {
++ memcpy (buffer, gomp_affinity_format_var, size - 1);
++ buffer[size - 1] = '\0';
++ }
++ }
++ return len;
++}
++
++void
++gomp_display_string (char *buffer, size_t size, size_t *ret,
++ const char *str, size_t len)
++{
++ size_t r = *ret;
++ if (size && r < size)
++ {
++ size_t l = len;
++ if (size - r < len)
++ l = size - r;
++ memcpy (buffer + r, str, l);
++ }
++ *ret += len;
++ if (__builtin_expect (r > *ret, 0))
++ gomp_fatal ("overflow in omp_capture_affinity");
++}
++
++static void
++gomp_display_repeat (char *buffer, size_t size, size_t *ret,
++ char c, size_t len)
++{
++ size_t r = *ret;
++ if (size && r < size)
++ {
++ size_t l = len;
++ if (size - r < len)
++ l = size - r;
++ memset (buffer + r, c, l);
++ }
++ *ret += len;
++ if (__builtin_expect (r > *ret, 0))
++ gomp_fatal ("overflow in omp_capture_affinity");
++}
++
++static void
++gomp_display_num (char *buffer, size_t size, size_t *ret,
++ bool zero, bool right, size_t sz, char *buf)
++{
++ size_t l = strlen (buf);
++ if (sz == (size_t) -1 || l >= sz)
++ {
++ gomp_display_string (buffer, size, ret, buf, l);
++ return;
++ }
++ if (zero)
++ {
++ if (buf[0] == '-')
++ gomp_display_string (buffer, size, ret, buf, 1);
++ else if (buf[0] == '0' && buf[1] == 'x')
++ gomp_display_string (buffer, size, ret, buf, 2);
++ gomp_display_repeat (buffer, size, ret, '0', sz - l);
++ if (buf[0] == '-')
++ gomp_display_string (buffer, size, ret, buf + 1, l - 1);
++ else if (buf[0] == '0' && buf[1] == 'x')
++ gomp_display_string (buffer, size, ret, buf + 2, l - 2);
++ else
++ gomp_display_string (buffer, size, ret, buf, l);
++ }
++ else if (right)
++ {
++ gomp_display_repeat (buffer, size, ret, ' ', sz - l);
++ gomp_display_string (buffer, size, ret, buf, l);
++ }
++ else
++ {
++ gomp_display_string (buffer, size, ret, buf, l);
++ gomp_display_repeat (buffer, size, ret, ' ', sz - l);
++ }
++}
++
++static void
++gomp_display_int (char *buffer, size_t size, size_t *ret,
++ bool zero, bool right, size_t sz, int num)
++{
++ char buf[3 * sizeof (int) + 2];
++ sprintf (buf, "%d", num);
++ gomp_display_num (buffer, size, ret, zero, right, sz, buf);
++}
++
++static void
++gomp_display_string_len (char *buffer, size_t size, size_t *ret,
++ bool right, size_t sz, char *str, size_t len)
++{
++ if (sz == (size_t) -1 || len >= sz)
++ {
++ gomp_display_string (buffer, size, ret, str, len);
++ return;
++ }
++
++ if (right)
++ {
++ gomp_display_repeat (buffer, size, ret, ' ', sz - len);
++ gomp_display_string (buffer, size, ret, str, len);
++ }
++ else
++ {
++ gomp_display_string (buffer, size, ret, str, len);
++ gomp_display_repeat (buffer, size, ret, ' ', sz - len);
++ }
++}
++
++static void
++gomp_display_hostname (char *buffer, size_t size, size_t *ret,
++ bool right, size_t sz)
++{
++#ifdef HAVE_GETHOSTNAME
++ {
++ char buf[256];
++ char *b = buf;
++ size_t len = 256;
++ do
++ {
++ b[len - 1] = '\0';
++ if (gethostname (b, len - 1) == 0)
++ {
++ size_t l = strlen (b);
++ if (l < len - 1)
++ {
++ gomp_display_string_len (buffer, size, ret,
++ right, sz, b, l);
++ if (b != buf)
++ free (b);
++ return;
++ }
++ }
++ if (len == 1048576)
++ break;
++ len = len * 2;
++ if (len == 512)
++ b = gomp_malloc (len);
++ else
++ b = gomp_realloc (b, len);
++ }
++ while (1);
++ if (b != buf)
++ free (b);
++ }
++#endif
++#ifdef HAVE_UNAME
++ {
++ struct utsname buf;
++ if (uname (&buf) == 0)
++ {
++ gomp_display_string_len (buffer, size, ret, right, sz,
++ buf.nodename, strlen (buf.nodename));
++ return;
++ }
++ }
++#endif
++ gomp_display_string_len (buffer, size, ret, right, sz, "node", 4);
++}
++
++struct affinity_types_struct {
++ char long_str[18];
++ char long_len;
++ char short_c; };
++
++static struct affinity_types_struct affinity_types[] =
++{
++#define AFFINITY_TYPE(l, s) \
++ { #l, sizeof (#l) - 1, s }
++ AFFINITY_TYPE (team_num, 't'),
++ AFFINITY_TYPE (num_teams, 'T'),
++ AFFINITY_TYPE (nesting_level, 'L'),
++ AFFINITY_TYPE (thread_num, 'n'),
++ AFFINITY_TYPE (num_threads, 'N'),
++ AFFINITY_TYPE (ancestor_tnum, 'a'),
++ AFFINITY_TYPE (host, 'H'),
++ AFFINITY_TYPE (process_id, 'P'),
++ AFFINITY_TYPE (native_thread_id, 'i'),
++ AFFINITY_TYPE (thread_affinity, 'A')
++#undef AFFINITY_TYPE
++};
++
++size_t
++gomp_display_affinity (char *buffer, size_t size,
++ const char *format, gomp_thread_handle handle,
++ struct gomp_team_state *ts, unsigned int place)
++{
++ size_t ret = 0;
++ do
++ {
++ const char *p = strchr (format, '%');
++ bool zero = false;
++ bool right = false;
++ size_t sz = -1;
++ char c;
++ int val;
++ if (p == NULL)
++ p = strchr (format, '\0');
++ if (p != format)
++ gomp_display_string (buffer, size, &ret,
++ format, p - format);
++ if (*p == '\0')
++ break;
++ p++;
++ if (*p == '%')
++ {
++ gomp_display_string (buffer, size, &ret, "%", 1);
++ format = p + 1;
++ continue;
++ }
++ if (*p == '0')
++ {
++ zero = true;
++ p++;
++ if (*p != '.')
++ gomp_fatal ("leading zero not followed by dot in affinity format");
++ }
++ if (*p == '.')
++ {
++ right = true;
++ p++;
++ }
++ if (*p >= '1' && *p <= '9')
++ {
++ char *end;
++ sz = strtoul (p, &end, 10);
++ p = end;
++ }
++ else if (zero || right)
++ gomp_fatal ("leading zero or right justification in affinity format "
++ "requires size");
++ c = *p;
++ if (c == '{')
++ {
++ int i;
++ for (i = 0;
++ i < sizeof (affinity_types) / sizeof (affinity_types[0]); ++i)
++ if (strncmp (p + 1, affinity_types[i].long_str,
++ affinity_types[i].long_len) == 0
++ && p[affinity_types[i].long_len + 1] == '}')
++ {
++ c = affinity_types[i].short_c;
++ p += affinity_types[i].long_len + 1;
++ break;
++ }
++ if (c == '{')
++ {
++ char *q = strchr (p + 1, '}');
++ if (q)
++ gomp_fatal ("unsupported long type name '%.*s' in affinity "
++ "format", (int) (q - (p + 1)), p + 1);
++ else
++ gomp_fatal ("unterminated long type name '%s' in affinity "
++ "format", p + 1);
++ }
++ }
++ switch (c)
++ {
++ case 't':
++ val = omp_get_team_num ();
++ goto do_int;
++ case 'T':
++ val = omp_get_num_teams ();
++ goto do_int;
++ case 'L':
++ val = ts->level;
++ goto do_int;
++ case 'n':
++ val = ts->team_id;
++ goto do_int;
++ case 'N':
++ val = ts->team ? ts->team->nthreads : 1;
++ goto do_int;
++ case 'a':
++ val = ts->team ? ts->team->prev_ts.team_id : -1;
++ goto do_int;
++ case 'H':
++ gomp_display_hostname (buffer, size, &ret, right, sz);
++ break;
++ case 'P':
++#ifdef HAVE_GETPID
++ val = getpid ();
++#else
++ val = 0;
++#endif
++ goto do_int;
++ case 'i':
++#if defined(LIBGOMP_USE_PTHREADS) && defined(__GNUC__)
++ {
++ char buf[3 * (sizeof (handle) + sizeof (uintptr_t) + sizeof (int))
++ + 4];
++ /* This macro returns expr unmodified for integral or pointer
++ types and 0 for anything else (e.g. aggregates). */
++#define gomp_nonaggregate(expr) \
++ __builtin_choose_expr (__builtin_classify_type (expr) == 1 \
++ || __builtin_classify_type (expr) == 5, expr, 0)
++ /* This macro returns expr unmodified for integral types,
++ (uintptr_t) (expr) for pointer types and 0 for anything else
++ (e.g. aggregates). */
++#define gomp_integral(expr) \
++ __builtin_choose_expr (__builtin_classify_type (expr) == 5, \
++ (uintptr_t) gomp_nonaggregate (expr), \
++ gomp_nonaggregate (expr))
++
++ if (sizeof (gomp_integral (handle)) == sizeof (unsigned long))
++ sprintf (buf, "0x%lx", (unsigned long) gomp_integral (handle));
++#if defined (HAVE_INTTYPES_H) && defined (PRIx64)
++ else if (sizeof (gomp_integral (handle)) == sizeof (uint64_t))
++ sprintf (buf, "0x%" PRIx64, (uint64_t) gomp_integral (handle));
++#else
++ else if (sizeof (gomp_integral (handle))
++ == sizeof (unsigned long long))
++ sprintf (buf, "0x%llx",
++ (unsigned long long) gomp_integral (handle));
++#endif
++ else
++ sprintf (buf, "0x%x", (unsigned int) gomp_integral (handle));
++ gomp_display_num (buffer, size, &ret, zero, right, sz, buf);
++ break;
++ }
++#else
++ val = 0;
++ goto do_int;
++#endif
++ case 'A':
++ if (sz == (size_t) -1)
++ gomp_display_affinity_place (buffer, size, &ret,
++ place - 1);
++ else if (right)
++ {
++ size_t len = 0;
++ gomp_display_affinity_place (NULL, 0, &len, place - 1);
++ if (len < sz)
++ gomp_display_repeat (buffer, size, &ret, ' ', sz - len);
++ gomp_display_affinity_place (buffer, size, &ret, place - 1);
++ }
++ else
++ {
++ size_t start = ret;
++ gomp_display_affinity_place (buffer, size, &ret, place - 1);
++ if (ret - start < sz)
++ gomp_display_repeat (buffer, size, &ret, ' ', sz - (ret - start));
++ }
++ break;
++ do_int:
++ gomp_display_int (buffer, size, &ret, zero, right, sz, val);
++ break;
++ default:
++ gomp_fatal ("unsupported type %c in affinity format", c);
++ }
++ format = p + 1;
++ }
++ while (1);
++ return ret;
++}
++
++size_t
++omp_capture_affinity (char *buffer, size_t size, const char *format)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ size_t ret
++ = gomp_display_affinity (buffer, size,
++ format && *format
++ ? format : gomp_affinity_format_var,
++ gomp_thread_self (), &thr->ts, thr->place);
++ if (size)
++ {
++ if (ret >= size)
++ buffer[size - 1] = '\0';
++ else
++ buffer[ret] = '\0';
++ }
++ return ret;
++}
++ialias (omp_capture_affinity)
++
++void
++omp_display_affinity (const char *format)
++{
++ char buf[512];
++ char *b;
++ size_t ret = ialias_call (omp_capture_affinity) (buf, sizeof buf, format);
++ if (ret < sizeof buf)
++ {
++ buf[ret] = '\n';
++ gomp_print_string (buf, ret + 1);
++ return;
++ }
++ b = gomp_malloc (ret + 1);
++ ialias_call (omp_capture_affinity) (b, ret + 1, format);
++ b[ret] = '\n';
++ gomp_print_string (b, ret + 1);
++ free (b);
++}
++
++void
++gomp_display_affinity_thread (gomp_thread_handle handle,
++ struct gomp_team_state *ts, unsigned int place)
++{
++ char buf[512];
++ char *b;
++ size_t ret = gomp_display_affinity (buf, sizeof buf, gomp_affinity_format_var,
++ handle, ts, place);
++ if (ret < sizeof buf)
++ {
++ buf[ret] = '\n';
++ gomp_print_string (buf, ret + 1);
++ return;
++ }
++ b = gomp_malloc (ret + 1);
++ gomp_display_affinity (b, ret + 1, gomp_affinity_format_var,
++ handle, ts, place);
++ b[ret] = '\n';
++ gomp_print_string (b, ret + 1);
++ free (b);
++}
+--- libgomp/single.c.jj 2018-04-25 09:40:31.870655561 +0200
++++ libgomp/single.c 2019-05-07 18:46:36.536109576 +0200
+@@ -47,7 +47,7 @@ GOMP_single_start (void)
+ return __sync_bool_compare_and_swap (&team->single_count, single_count,
+ single_count + 1L);
+ #else
+- bool ret = gomp_work_share_start (false);
++ bool ret = gomp_work_share_start (0);
+ if (ret)
+ gomp_work_share_init_done ();
+ gomp_work_share_end_nowait ();
+@@ -68,7 +68,7 @@ GOMP_single_copy_start (void)
+ bool first;
+ void *ret;
+
+- first = gomp_work_share_start (false);
++ first = gomp_work_share_start (0);
+
+ if (first)
+ {
+--- libgomp/oacc-cuda.c.jj 2018-04-25 09:40:31.321655307 +0200
++++ libgomp/oacc-cuda.c 2019-05-07 18:46:36.528109704 +0200
+@@ -58,7 +58,7 @@ acc_get_cuda_stream (int async)
+ {
+ struct goacc_thread *thr = goacc_thread ();
+
+- if (async < 0)
++ if (!async_valid_p (async))
+ return NULL;
+
+ if (thr && thr->dev && thr->dev->openacc.cuda.get_stream_func)
+@@ -72,7 +72,7 @@ acc_set_cuda_stream (int async, void *st
+ {
+ struct goacc_thread *thr;
+
+- if (async < 0 || stream == NULL)
++ if (!async_valid_p (async) || stream == NULL)
+ return 0;
+
+ goacc_lazy_initialize ();
+--- libgomp/work.c.jj 2018-04-25 09:40:31.925655587 +0200
++++ libgomp/work.c 2019-05-07 18:46:36.548109384 +0200
+@@ -76,7 +76,15 @@ alloc_work_share (struct gomp_team *team
+ #endif
+
+ team->work_share_chunk *= 2;
++ /* Allocating gomp_work_share structures aligned is just an
++ optimization, don't do it when using the fallback method. */
++#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC
++ ws = gomp_aligned_alloc (__alignof (struct gomp_work_share),
++ team->work_share_chunk
++ * sizeof (struct gomp_work_share));
++#else
+ ws = gomp_malloc (team->work_share_chunk * sizeof (struct gomp_work_share));
++#endif
+ ws->next_alloc = team->work_shares[0].next_alloc;
+ team->work_shares[0].next_alloc = ws;
+ team->work_share_list_alloc = &ws[1];
+@@ -90,30 +98,35 @@ alloc_work_share (struct gomp_team *team
+ This shouldn't touch the next_alloc field. */
+
+ void
+-gomp_init_work_share (struct gomp_work_share *ws, bool ordered,
++gomp_init_work_share (struct gomp_work_share *ws, size_t ordered,
+ unsigned nthreads)
+ {
+ gomp_mutex_init (&ws->lock);
+ if (__builtin_expect (ordered, 0))
+ {
+-#define INLINE_ORDERED_TEAM_IDS_CNT \
+- ((sizeof (struct gomp_work_share) \
+- - offsetof (struct gomp_work_share, inline_ordered_team_ids)) \
+- / sizeof (((struct gomp_work_share *) 0)->inline_ordered_team_ids[0]))
+-
+- if (nthreads > INLINE_ORDERED_TEAM_IDS_CNT)
+- ws->ordered_team_ids
+- = gomp_malloc (nthreads * sizeof (*ws->ordered_team_ids));
++#define INLINE_ORDERED_TEAM_IDS_SIZE \
++ (sizeof (struct gomp_work_share) \
++ - offsetof (struct gomp_work_share, inline_ordered_team_ids))
++
++ if (__builtin_expect (ordered != 1, 0))
++ {
++ ordered += nthreads * sizeof (*ws->ordered_team_ids) - 1;
++ ordered = ordered + __alignof__ (long long) - 1;
++ ordered &= ~(__alignof__ (long long) - 1);
++ }
++ else
++ ordered = nthreads * sizeof (*ws->ordered_team_ids);
++ if (ordered > INLINE_ORDERED_TEAM_IDS_SIZE)
++ ws->ordered_team_ids = gomp_malloc (ordered);
+ else
+ ws->ordered_team_ids = ws->inline_ordered_team_ids;
+- memset (ws->ordered_team_ids, '\0',
+- nthreads * sizeof (*ws->ordered_team_ids));
++ memset (ws->ordered_team_ids, '\0', ordered);
+ ws->ordered_num_used = 0;
+ ws->ordered_owner = -1;
+ ws->ordered_cur = 0;
+ }
+ else
+- ws->ordered_team_ids = NULL;
++ ws->ordered_team_ids = ws->inline_ordered_team_ids;
+ gomp_ptrlock_init (&ws->next_ws, NULL);
+ ws->threads_completed = 0;
+ }
+@@ -166,7 +179,7 @@ free_work_share (struct gomp_team *team,
+ if this was the first thread to reach this point. */
+
+ bool
+-gomp_work_share_start (bool ordered)
++gomp_work_share_start (size_t ordered)
+ {
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+@@ -178,7 +191,7 @@ gomp_work_share_start (bool ordered)
+ ws = gomp_malloc (sizeof (*ws));
+ gomp_init_work_share (ws, ordered, 1);
+ thr->ts.work_share = ws;
+- return ws;
++ return true;
+ }
+
+ ws = thr->ts.work_share;
+--- include/gomp-constants.h.jj 2018-04-25 09:40:39.757659209 +0200
++++ include/gomp-constants.h 2019-05-07 18:57:33.333627031 +0200
+@@ -189,6 +189,7 @@ enum gomp_map_kind
+ #define GOMP_TASK_FLAG_GRAINSIZE (1 << 9)
+ #define GOMP_TASK_FLAG_IF (1 << 10)
+ #define GOMP_TASK_FLAG_NOGROUP (1 << 11)
++#define GOMP_TASK_FLAG_REDUCTION (1 << 12)
+
+ /* GOMP_target{_ext,update_ext,enter_exit_data} flags argument. */
+ #define GOMP_TARGET_FLAG_NOWAIT (1 << 0)
+@@ -196,6 +197,18 @@ enum gomp_map_kind
+ /* Internal to libgomp. */
+ #define GOMP_TARGET_FLAG_UPDATE (1U << 31)
+
++
++/* OpenACC construct flags. */
++
++/* Force host fallback execution. */
++#define GOACC_FLAG_HOST_FALLBACK (1 << 0)
++
++/* For legacy reasons, in the ABI, the GOACC_FLAGs are encoded as an inverted
++ bitmask. */
++#define GOACC_FLAGS_MARSHAL_OP BIT_NOT_EXPR
++#define GOACC_FLAGS_UNMARSHAL(X) (~(X))
++
++
+ /* Versions of libgomp and device-specific plugins. GOMP_VERSION
+ should be incremented whenever an ABI-incompatible change is introduced
+ to the plugin interface defined in libgomp/libgomp.h. */
+@@ -251,6 +264,12 @@ enum gomp_map_kind
+ at most and shifted by this many bits. */
+ #define GOMP_TARGET_ARG_VALUE_SHIFT 16
+
++/* Dependence types in omp_depend_t objects. */
++#define GOMP_DEPEND_IN 1
++#define GOMP_DEPEND_OUT 2
++#define GOMP_DEPEND_INOUT 3
++#define GOMP_DEPEND_MUTEXINOUTSET 4
++
+ /* HSA specific data structures. */
+
+ /* Identifiers of device-specific target arguments. */
diff --git a/SOURCES/gcc8-libgomp-omp_h-multilib.patch b/SOURCES/gcc8-libgomp-omp_h-multilib.patch
new file mode 100644
index 0000000..d0e98d1
--- /dev/null
+++ b/SOURCES/gcc8-libgomp-omp_h-multilib.patch
@@ -0,0 +1,17 @@
+2008-06-09 Jakub Jelinek
+
+ * omp.h.in (omp_nest_lock_t): Fix up for Linux multilibs.
+
+--- libgomp/omp.h.in.jj 2008-06-09 13:34:05.000000000 +0200
++++ libgomp/omp.h.in 2008-06-09 13:34:48.000000000 +0200
+@@ -42,8 +42,8 @@ typedef struct
+
+ typedef struct
+ {
+- unsigned char _x[@OMP_NEST_LOCK_SIZE@]
+- __attribute__((__aligned__(@OMP_NEST_LOCK_ALIGN@)));
++ unsigned char _x[8 + sizeof (void *)]
++ __attribute__((__aligned__(sizeof (void *))));
+ } omp_nest_lock_t;
+ #endif
+
diff --git a/SOURCES/gcc8-libgomp-testsuite.patch b/SOURCES/gcc8-libgomp-testsuite.patch
new file mode 100644
index 0000000..502ee22
--- /dev/null
+++ b/SOURCES/gcc8-libgomp-testsuite.patch
@@ -0,0 +1,41 @@
+--- libgomp/testsuite/libgomp-test-support.exp.in.jj 2018-04-25 09:40:31.323655308 +0200
++++ libgomp/testsuite/libgomp-test-support.exp.in 2019-04-25 20:01:50.028243827 +0200
+@@ -2,4 +2,5 @@ set cuda_driver_include "@CUDA_DRIVER_IN
+ set cuda_driver_lib "@CUDA_DRIVER_LIB@"
+ set hsa_runtime_lib "@HSA_RUNTIME_LIB@"
+
++set offload_plugins "@offload_plugins@"
+ set offload_targets "@offload_targets@"
+--- libgomp/testsuite/lib/libgomp.exp.jj 2018-04-25 09:40:31.584655429 +0200
++++ libgomp/testsuite/lib/libgomp.exp 2019-05-24 11:41:51.015822702 +0200
+@@ -40,7 +40,7 @@ load_file libgomp-test-support.exp
+ # Populate offload_targets_s (offloading targets separated by a space), and
+ # offload_targets_s_openacc (the same, but with OpenACC names; OpenACC spells
+ # some of them a little differently).
+-set offload_targets_s [split $offload_targets ","]
++set offload_targets_s [split $offload_plugins ","]
+ set offload_targets_s_openacc {}
+ foreach offload_target_openacc $offload_targets_s {
+ # Translate to OpenACC names, or skip if not yet supported.
+@@ -137,8 +137,8 @@ proc libgomp_init { args } {
+
+ # Add liboffloadmic build directory in LD_LIBRARY_PATH to support
+ # non-fallback testing for Intel MIC targets
+- global offload_targets
+- if { [string match "*,intelmic,*" ",$offload_targets,"] } {
++ global offload_plugins
++ if { [string match "*,intelmic,*" ",$offload_plugins,"] } {
+ append always_ld_library_path ":${blddir}/../liboffloadmic/.libs"
+ append always_ld_library_path ":${blddir}/../liboffloadmic/plugin/.libs"
+ # libstdc++ is required by liboffloadmic
+@@ -362,8 +362,8 @@ proc check_effective_target_offload_devi
+ # Return 1 if configured for nvptx offloading.
+
+ proc check_effective_target_openacc_nvidia_accel_configured { } {
+- global offload_targets
+- if { ![string match "*,nvptx,*" ",$offload_targets,"] } {
++ global offload_plugins
++ if { ![string match "*,nvptx,*" ",$offload_plugins,"] } {
+ return 0
+ }
+ # PR libgomp/65099: Currently, we only support offloading in 64-bit
diff --git a/SOURCES/gcc8-libstdc++-docs.patch b/SOURCES/gcc8-libstdc++-docs.patch
new file mode 100644
index 0000000..594ce19
--- /dev/null
+++ b/SOURCES/gcc8-libstdc++-docs.patch
@@ -0,0 +1,24 @@
+--- libstdc++-v3/doc/html/index.html.jj 2011-01-03 12:53:21.282829010 +0100
++++ libstdc++-v3/doc/html/index.html 2011-01-04 18:06:28.999851145 +0100
+@@ -5,6 +5,8 @@
+ FSF
+
+
++ Release 8.1.1
++
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation
+ License, Version 1.2 or any later version published by the
+--- libstdc++-v3/doc/html/api.html.jj 2011-01-03 12:53:21.000000000 +0100
++++ libstdc++-v3/doc/html/api.html 2011-01-04 18:12:01.672757784 +0100
+@@ -20,7 +20,9 @@
+ member functions for the library classes, finding out what is in a
+ particular include file, looking at inheritance diagrams, etc.
+
+- The API documentation, rendered into HTML, can be viewed online
++ The API documentation, rendered into HTML, can be viewed locally
++ for the 8.1.1 release,
++ online
+ for each GCC release
+ and
+
diff --git a/SOURCES/gcc8-libtool-no-rpath.patch b/SOURCES/gcc8-libtool-no-rpath.patch
new file mode 100644
index 0000000..466c661
--- /dev/null
+++ b/SOURCES/gcc8-libtool-no-rpath.patch
@@ -0,0 +1,27 @@
+libtool sucks.
+--- ltmain.sh.jj 2007-12-07 14:53:21.000000000 +0100
++++ ltmain.sh 2008-09-05 21:51:48.000000000 +0200
+@@ -5394,6 +5394,7 @@ EOF
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
++ case "$libdir" in /usr/lib|/usr/lib64|/usr/lib/../lib|/usr/lib/../lib64) continue;; esac
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+@@ -6071,6 +6072,7 @@ EOF
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
++ case "$libdir" in /usr/lib|/usr/lib64|/usr/lib/../lib|/usr/lib/../lib64) continue;; esac
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+@@ -6120,6 +6122,7 @@ EOF
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
++ case "$libdir" in /usr/lib|/usr/lib64|/usr/lib/../lib|/usr/lib/../lib64) continue;; esac
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
diff --git a/SOURCES/gcc8-mcet.patch b/SOURCES/gcc8-mcet.patch
new file mode 100644
index 0000000..6fb78ca
--- /dev/null
+++ b/SOURCES/gcc8-mcet.patch
@@ -0,0 +1,17 @@
+2018-04-24 Jakub Jelinek
+
+ * config/i386/i386.opt (mcet): Remporarily re-add as alias to -mshstk.
+
+--- gcc/config/i386/i386.opt (revision 259613)
++++ gcc/config/i386/i386.opt (revision 259612)
+@@ -1006,6 +1006,10 @@ mgeneral-regs-only
+ Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
+ Generate code which uses only the general registers.
+
++mcet
++Target Undocumented Alias(mshstk)
++;; Deprecated
++
+ mshstk
+ Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
+ Enable shadow stack built-in functions from Control-flow Enforcement
diff --git a/SOURCES/gcc8-no-add-needed.patch b/SOURCES/gcc8-no-add-needed.patch
new file mode 100644
index 0000000..aa2f52d
--- /dev/null
+++ b/SOURCES/gcc8-no-add-needed.patch
@@ -0,0 +1,50 @@
+2010-02-08 Roland McGrath
+
+ * config/rs6000/sysv4.h (LINK_EH_SPEC): Pass --no-add-needed to the
+ linker.
+ * config/gnu-user.h (LINK_EH_SPEC): Likewise.
+ * config/alpha/elf.h (LINK_EH_SPEC): Likewise.
+ * config/ia64/linux.h (LINK_EH_SPEC): Likewise.
+
+--- gcc/config/alpha/elf.h.jj 2011-01-03 12:52:31.118056764 +0100
++++ gcc/config/alpha/elf.h 2011-01-04 18:14:10.931874160 +0100
+@@ -168,5 +168,5 @@ extern int alpha_this_gpdisp_sequence_nu
+ I imagine that other systems will catch up. In the meantime, it
+ doesn't harm to make sure that the data exists to be used later. */
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+-#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
++#define LINK_EH_SPEC "--no-add-needed %{!static|static-pie:--eh-frame-hdr} "
+ #endif
+--- gcc/config/ia64/linux.h.jj 2011-01-03 13:02:11.462994522 +0100
++++ gcc/config/ia64/linux.h 2011-01-04 18:14:10.931874160 +0100
+@@ -76,7 +76,7 @@ do { \
+ Signalize that because we have fde-glibc, we don't need all C shared libs
+ linked against -lgcc_s. */
+ #undef LINK_EH_SPEC
+-#define LINK_EH_SPEC ""
++#define LINK_EH_SPEC "--no-add-needed "
+
+ #undef TARGET_INIT_LIBFUNCS
+ #define TARGET_INIT_LIBFUNCS ia64_soft_fp_init_libfuncs
+--- gcc/config/gnu-user.h.jj 2011-01-03 12:53:03.739057299 +0100
++++ gcc/config/gnu-user.h 2011-01-04 18:14:10.932814884 +0100
+@@ -133,7 +133,7 @@ see the files COPYING3 and COPYING.RUNTI
+ #define LIB_SPEC GNU_USER_TARGET_LIB_SPEC
+
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+-#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
++#define LINK_EH_SPEC "--no-add-needed %{!static|static-pie:--eh-frame-hdr} "
+ #endif
+
+ #undef LINK_GCC_C_SEQUENCE_SPEC
+--- gcc/config/rs6000/sysv4.h.jj 2011-01-03 13:02:18.255994215 +0100
++++ gcc/config/rs6000/sysv4.h 2011-01-04 18:14:10.933888871 +0100
+@@ -816,7 +816,7 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEF
+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER "}}"
+
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+-# define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
++# define LINK_EH_SPEC "--no-add-needed %{!static|static-pie:--eh-frame-hdr} "
+ #endif
+
+ #define CPP_OS_LINUX_SPEC "-D__unix__ -D__gnu_linux__ -D__linux__ \
diff --git a/SOURCES/gcc8-pr85400.patch b/SOURCES/gcc8-pr85400.patch
new file mode 100644
index 0000000..0c0d887
--- /dev/null
+++ b/SOURCES/gcc8-pr85400.patch
@@ -0,0 +1,94 @@
+2018-05-10 Eric Botcazou
+
+ PR c++/85400
+ * c-attribs.c (handle_visibility_attribute): Do not set no_add_attrs.
+
+ * decl2.c (adjust_var_decl_tls_model): New static function.
+ (comdat_linkage): Call it on a variable.
+ (maybe_make_one_only): Likewise.
+
+--- gcc/c-family/c-attribs.c
++++ gcc/c-family/c-attribs.c
+@@ -2299,14 +2299,13 @@ handle_visibility_attribute (tree *node, tree name, tree args,
+
+ static tree
+ handle_tls_model_attribute (tree *node, tree name, tree args,
+- int ARG_UNUSED (flags), bool *no_add_attrs)
++ int ARG_UNUSED (flags),
++ bool *ARG_UNUSED (no_add_attrs))
+ {
+ tree id;
+ tree decl = *node;
+ enum tls_model kind;
+
+- *no_add_attrs = true;
+-
+ if (!VAR_P (decl) || !DECL_THREAD_LOCAL_P (decl))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+--- gcc/cp/decl2.c
++++ gcc/cp/decl2.c
+@@ -1838,6 +1838,17 @@ mark_vtable_entries (tree decl)
+ }
+ }
+
++/* Adjust the TLS model on variable DECL if need be, typically after
++ the linkage of DECL has been modified. */
++
++static void
++adjust_var_decl_tls_model (tree decl)
++{
++ if (CP_DECL_THREAD_LOCAL_P (decl)
++ && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)))
++ set_decl_tls_model (decl, decl_default_tls_model (decl));
++}
++
+ /* Set DECL up to have the closest approximation of "initialized common"
+ linkage available. */
+
+@@ -1888,6 +1899,9 @@ comdat_linkage (tree decl)
+
+ if (TREE_PUBLIC (decl))
+ DECL_COMDAT (decl) = 1;
++
++ if (VAR_P (decl))
++ adjust_var_decl_tls_model (decl);
+ }
+
+ /* For win32 we also want to put explicit instantiations in
+@@ -1926,6 +1940,8 @@ maybe_make_one_only (tree decl)
+ /* Mark it needed so we don't forget to emit it. */
+ node->forced_by_abi = true;
+ TREE_USED (decl) = 1;
++
++ adjust_var_decl_tls_model (decl);
+ }
+ }
+ }
+--- /dev/null
++++ gcc/testsuite/g++.dg/tls/pr85400.C
+@@ -0,0 +1,24 @@
++// PR c++/85400
++// Testcase by Brian Vandenberg
++
++// { dg-do link { target c++11 } }
++// { dg-require-effective-target fpic }
++// { dg-require-effective-target shared }
++// { dg-require-effective-target tls }
++// { dg-options "-shared -fPIC -O" }
++// { dg-add-options tls }
++
++struct Test
++{
++ int blah (int y)
++ {
++ thread_local int mything = 3;
++ mything = y > 0 ? y : mything;
++ return mything;
++ }
++};
++
++int stuff (Test& test, int y)
++{
++ return test.blah(y);
++}
diff --git a/SOURCES/gcc8-pr86747.patch b/SOURCES/gcc8-pr86747.patch
new file mode 100644
index 0000000..78e4a76
--- /dev/null
+++ b/SOURCES/gcc8-pr86747.patch
@@ -0,0 +1,30 @@
+2018-12-06 Alexandre Oliva
+
+ PR c++/86747
+ * pt.c (tsubst_friend_class): Enter tsubsted class context.
+
+--- gcc/cp/pt.c
++++ gcc/cp/pt.c
+@@ -10558,7 +10558,10 @@ tsubst_friend_class (tree friend_tmpl, tree args)
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ push_nested_namespace (context);
+ else
+- push_nested_class (context);
++ {
++ context = tsubst (context, args, tf_error, NULL_TREE);
++ push_nested_class (context);
++ }
+
+ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), /*prefer_type=*/false,
+ /*non_class=*/false, /*block_p=*/false,
+--- /dev/null
++++ gcc/testsuite/g++.dg/pr86747.C
+@@ -0,0 +1,8 @@
++// { dg-do compile }
++
++template class A {
++ template class C; // #1
++ template friend class C; // #2
++};
++
++A a;
diff --git a/SOURCES/gcc8-rh1512529-aarch64.patch b/SOURCES/gcc8-rh1512529-aarch64.patch
new file mode 100644
index 0000000..4030027
--- /dev/null
+++ b/SOURCES/gcc8-rh1512529-aarch64.patch
@@ -0,0 +1,445 @@
+--- gcc/config/aarch64/aarch64.c
++++ gcc/config/aarch64/aarch64.c
+@@ -3799,7 +3799,14 @@ aarch64_output_probe_stack_range (rtx reg1, rtx reg2)
+ output_asm_insn ("sub\t%0, %0, %1", xops);
+
+ /* Probe at TEST_ADDR. */
+- output_asm_insn ("str\txzr, [%0]", xops);
++ if (flag_stack_clash_protection)
++ {
++ gcc_assert (xops[0] == stack_pointer_rtx);
++ xops[1] = GEN_INT (PROBE_INTERVAL - 8);
++ output_asm_insn ("str\txzr, [%0, %1]", xops);
++ }
++ else
++ output_asm_insn ("str\txzr, [%0]", xops);
+
+ /* Test if TEST_ADDR == LAST_ADDR. */
+ xops[1] = reg2;
+@@ -4589,6 +4596,133 @@ aarch64_set_handled_components (sbitmap components)
+ cfun->machine->reg_is_wrapped_separately[regno] = true;
+ }
+
++/* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
++ registers. */
++
++static void
++aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
++ poly_int64 poly_size)
++{
++ HOST_WIDE_INT size;
++ if (!poly_size.is_constant (&size))
++ {
++ sorry ("stack probes for SVE frames");
++ return;
++ }
++
++ HOST_WIDE_INT probe_interval
++ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++ HOST_WIDE_INT guard_size
++ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
++ HOST_WIDE_INT guard_used_by_caller = 1024;
++
++ /* SIZE should be large enough to require probing here. ie, it
++ must be larger than GUARD_SIZE - GUARD_USED_BY_CALLER.
++
++ We can allocate GUARD_SIZE - GUARD_USED_BY_CALLER as a single chunk
++ without any probing. */
++ gcc_assert (size >= guard_size - guard_used_by_caller);
++ aarch64_sub_sp (temp1, temp2, guard_size - guard_used_by_caller, true);
++ HOST_WIDE_INT orig_size = size;
++ size -= (guard_size - guard_used_by_caller);
++
++ HOST_WIDE_INT rounded_size = size & -probe_interval;
++ HOST_WIDE_INT residual = size - rounded_size;
++
++ /* We can handle a small number of allocations/probes inline. Otherwise
++ punt to a loop. */
++ if (rounded_size && rounded_size <= 4 * probe_interval)
++ {
++ /* We don't use aarch64_sub_sp here because we don't want to
++ repeatedly load TEMP1. */
++ rtx step = GEN_INT (-probe_interval);
++ if (probe_interval > ARITH_FACTOR)
++ {
++ emit_move_insn (temp1, step);
++ step = temp1;
++ }
++
++ for (HOST_WIDE_INT i = 0; i < rounded_size; i += probe_interval)
++ {
++ rtx_insn *insn = emit_insn (gen_add2_insn (stack_pointer_rtx, step));
++ add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
++
++ if (probe_interval > ARITH_FACTOR)
++ {
++ RTX_FRAME_RELATED_P (insn) = 1;
++ rtx adj = plus_constant (Pmode, stack_pointer_rtx, -probe_interval);
++ add_reg_note (insn, REG_CFA_ADJUST_CFA,
++ gen_rtx_SET (stack_pointer_rtx, adj));
++ }
++
++ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++ (probe_interval
++ - GET_MODE_SIZE (word_mode))));
++ emit_insn (gen_blockage ());
++ }
++ dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
++ }
++ else if (rounded_size)
++ {
++ /* Compute the ending address. */
++ unsigned int scratchreg = REGNO (temp1);
++ emit_move_insn (temp1, GEN_INT (-rounded_size));
++ rtx_insn *insn
++ = emit_insn (gen_add3_insn (temp1, stack_pointer_rtx, temp1));
++
++ /* For the initial allocation, we don't have a frame pointer
++ set up, so we always need CFI notes. If we're doing the
++ final allocation, then we may have a frame pointer, in which
++ case it is the CFA, otherwise we need CFI notes.
++
++ We can determine which allocation we are doing by looking at
++ the temporary register. IP0 is the initial allocation, IP1
++ is the final allocation. */
++ if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
++ {
++ /* We want the CFA independent of the stack pointer for the
++ duration of the loop. */
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (Pmode, temp1,
++ (rounded_size + (orig_size - size))));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++
++ /* This allocates and probes the stack.
++
++ It also probes at a 4k interval regardless of the value of
++ PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL. */
++ insn = emit_insn (gen_probe_stack_range (stack_pointer_rtx,
++ stack_pointer_rtx, temp1));
++
++ /* Now reset the CFA register if needed. */
++ if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
++ {
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (Pmode, stack_pointer_rtx,
++ (rounded_size + (orig_size - size))));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++
++ emit_insn (gen_blockage ());
++ dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
++ }
++ else
++ dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
++
++ /* Handle any residuals.
++ Note that any residual must be probed. */
++ if (residual)
++ {
++ aarch64_sub_sp (temp1, temp2, residual, true);
++ add_reg_note (get_last_insn (), REG_STACK_CHECK, const0_rtx);
++ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++ (residual - GET_MODE_SIZE (word_mode))));
++ emit_insn (gen_blockage ());
++ }
++ return;
++}
++
+ /* Add a REG_CFA_EXPRESSION note to INSN to say that register REG
+ is saved at BASE + OFFSET. */
+
+@@ -4686,7 +4820,54 @@ aarch64_expand_prologue (void)
+ rtx ip0_rtx = gen_rtx_REG (Pmode, IP0_REGNUM);
+ rtx ip1_rtx = gen_rtx_REG (Pmode, IP1_REGNUM);
+
+- aarch64_sub_sp (ip0_rtx, ip1_rtx, initial_adjust, true);
++ /* We do not fully protect aarch64 against stack clash style attacks
++ as doing so would be prohibitively expensive with less utility over
++ time as newer compilers are deployed.
++
++ We assume the guard is at least 64k. Furthermore, we assume that
++ the caller has not pushed the stack pointer more than 1k into
++ the guard. A caller that pushes the stack pointer than 1k into
++ the guard is considered invalid.
++
++ Note that the caller's ability to push the stack pointer into the
++ guard is a function of the number and size of outgoing arguments and/or
++ dynamic stack allocations due to the mandatory save of the link register
++ in the caller's frame.
++
++ With those assumptions the callee can allocate up to 63k of stack
++ space without probing.
++
++ When probing is needed, we emit a probe at the start of the prologue
++ and every PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes thereafter.
++
++ We have to track how much space has been allocated, but we do not
++ track stores into the stack as implicit probes except for the
++ fp/lr store. */
++ HOST_WIDE_INT guard_size
++ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
++ HOST_WIDE_INT guard_used_by_caller = 1024;
++ if (flag_stack_clash_protection)
++ {
++ if (known_eq (frame_size, 0))
++ dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
++ else if (known_lt (initial_adjust, guard_size - guard_used_by_caller)
++ && known_lt (final_adjust, guard_size - guard_used_by_caller))
++ dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++ }
++
++ /* In theory we should never have both an initial adjustment
++ and a callee save adjustment. Verify that is the case since the
++ code below does not handle it for -fstack-clash-protection. */
++ gcc_assert (known_eq (initial_adjust, 0) || callee_adjust == 0);
++
++ /* Only probe if the initial adjustment is larger than the guard
++ less the amount of the guard reserved for use by the caller's
++ outgoing args. */
++ if (flag_stack_clash_protection
++ && maybe_ge (initial_adjust, guard_size - guard_used_by_caller))
++ aarch64_allocate_and_probe_stack_space (ip0_rtx, ip1_rtx, initial_adjust);
++ else
++ aarch64_sub_sp (ip0_rtx, ip1_rtx, initial_adjust, true);
+
+ if (callee_adjust != 0)
+ aarch64_push_regs (reg1, reg2, callee_adjust);
+@@ -4742,7 +4923,31 @@ aarch64_expand_prologue (void)
+ callee_adjust != 0 || emit_frame_chain);
+ aarch64_save_callee_saves (DFmode, callee_offset, V0_REGNUM, V31_REGNUM,
+ callee_adjust != 0 || emit_frame_chain);
+- aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
++
++ /* We may need to probe the final adjustment as well. */
++ if (flag_stack_clash_protection && maybe_ne (final_adjust, 0))
++ {
++ /* First probe if the final adjustment is larger than the guard size
++ less the amount of the guard reserved for use by the caller's
++ outgoing args. */
++ if (maybe_ge (final_adjust, guard_size - guard_used_by_caller))
++ aarch64_allocate_and_probe_stack_space (ip1_rtx, ip0_rtx,
++ final_adjust);
++ else
++ aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
++
++ /* We must also probe if the final adjustment is larger than the guard
++ that is assumed used by the caller. This may be sub-optimal. */
++ if (maybe_ge (final_adjust, guard_used_by_caller))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "Stack clash aarch64 large outgoing arg, probing\n");
++ emit_stack_probe (stack_pointer_rtx);
++ }
++ }
++ else
++ aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
+ }
+
+ /* Return TRUE if we can use a simple_return insn.
+@@ -10476,6 +10681,12 @@ aarch64_override_options_internal (struct gcc_options *opts)
+ && opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
+ opts->x_flag_prefetch_loop_arrays = 1;
+
++ /* We assume the guard page is 64k. */
++ maybe_set_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE,
++ 16,
++ opts->x_param_values,
++ global_options_set.x_param_values);
++
+ aarch64_override_options_after_change_1 (opts);
+ }
+
+@@ -17161,6 +17372,28 @@ aarch64_sched_can_speculate_insn (rtx_insn *insn)
+ }
+ }
+
++/* It has been decided that to allow up to 1kb of outgoing argument
++ space to be allocated w/o probing. If more than 1kb of outgoing
++ argment space is allocated, then it must be probed and the last
++ probe must occur no more than 1kbyte away from the end of the
++ allocated space.
++
++ This implies that the residual part of an alloca allocation may
++ need probing in cases where the generic code might not otherwise
++ think a probe is needed.
++
++ This target hook returns TRUE when allocating RESIDUAL bytes of
++ alloca space requires an additional probe, otherwise FALSE is
++ returned. */
++
++static bool
++aarch64_stack_clash_protection_final_dynamic_probe (rtx residual)
++{
++ return (residual == CONST0_RTX (Pmode)
++ || GET_CODE (residual) != CONST_INT
++ || INTVAL (residual) >= 1024);
++}
++
+ /* Implement TARGET_COMPUTE_PRESSURE_CLASSES. */
+
+ static int
+@@ -17669,6 +17902,10 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_CONSTANT_ALIGNMENT
+ #define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment
+
++#undef TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE
++#define TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE \
++ aarch64_stack_clash_protection_final_dynamic_probe
++
+ #undef TARGET_COMPUTE_PRESSURE_CLASSES
+ #define TARGET_COMPUTE_PRESSURE_CLASSES aarch64_compute_pressure_classes
+
+--- gcc/config/aarch64/aarch64.md
++++ gcc/config/aarch64/aarch64.md
+@@ -5812,7 +5812,7 @@
+ )
+
+ (define_insn "probe_stack_range"
+- [(set (match_operand:DI 0 "register_operand" "=r")
++ [(set (match_operand:DI 0 "register_operand" "=rk")
+ (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "register_operand" "r")]
+ UNSPECV_PROBE_STACK_RANGE))]
+--- gcc/testsuite/gcc.target/aarch64/stack-check-12.c
++++ gcc/testsuite/gcc.target/aarch64/stack-check-12.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++extern void arf (unsigned long int *, unsigned long int *);
++void
++frob ()
++{
++ unsigned long int num[1000];
++ unsigned long int den[1000];
++ arf (den, num);
++}
++
++/* This verifies that the scheduler did not break the dependencies
++ by adjusting the offsets within the probe and that the scheduler
++ did not reorder around the stack probes. */
++/* { dg-final { scan-assembler-times "sub\\tsp, sp, #4096\\n\\tstr\\txzr, .sp, 4088." 3 } } */
++
++
++
+--- gcc/testsuite/gcc.target/aarch64/stack-check-13.c
++++ gcc/testsuite/gcc.target/aarch64/stack-check-13.c
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++#define ARG32(X) X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
++#define ARG192(X) ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X)
++void out1(ARG192(__int128));
++int t1(int);
++
++int t3(int x)
++{
++ if (x < 1000)
++ return t1 (x) + 1;
++
++ out1 (ARG192(1));
++ return 0;
++}
++
++
++
++/* This test creates a large (> 1k) outgoing argument area that needs
++ to be probed. We don't test the exact size of the space or the
++ exact offset to make the test a little less sensitive to trivial
++ output changes. */
++/* { dg-final { scan-assembler-times "sub\\tsp, sp, #....\\n\\tstr\\txzr, \\\[sp" 1 } } */
++
++
++
+--- gcc/testsuite/gcc.target/aarch64/stack-check-14.c
++++ gcc/testsuite/gcc.target/aarch64/stack-check-14.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++int t1(int);
++
++int t2(int x)
++{
++ char *p = __builtin_alloca (4050);
++ x = t1 (x);
++ return p[x];
++}
++
++
++/* This test has a constant sized alloca that is smaller than the
++ probe interval. But it actually requires two probes instead
++ of one because of the optimistic assumptions we made in the
++ aarch64 prologue code WRT probing state.
++
++ The form can change quite a bit so we just check for two
++ probes without looking at the actual address. */
++/* { dg-final { scan-assembler-times "str\\txzr," 2 } } */
++
++
++
+--- gcc/testsuite/gcc.target/aarch64/stack-check-15.c
++++ gcc/testsuite/gcc.target/aarch64/stack-check-15.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++int t1(int);
++
++int t2(int x)
++{
++ char *p = __builtin_alloca (x);
++ x = t1 (x);
++ return p[x];
++}
++
++
++/* This test has a variable sized alloca. It requires 3 probes.
++ One in the loop, one for the residual and at the end of the
++ alloca area.
++
++ The form can change quite a bit so we just check for two
++ probes without looking at the actual address. */
++/* { dg-final { scan-assembler-times "str\\txzr," 3 } } */
++
++
++
+--- gcc/testsuite/lib/target-supports.exp
++++ gcc/testsuite/lib/target-supports.exp
+@@ -9201,14 +9201,9 @@ proc check_effective_target_autoincdec { } {
+ #
+ proc check_effective_target_supports_stack_clash_protection { } {
+
+- # Temporary until the target bits are fully ACK'd.
+-# if { [istarget aarch*-*-*] } {
+-# return 1
+-# }
+-
+ if { [istarget x86_64-*-*] || [istarget i?86-*-*]
+ || [istarget powerpc*-*-*] || [istarget rs6000*-*-*]
+- || [istarget s390*-*-*] } {
++ || [istarget aarch64*-**] || [istarget s390*-*-*] } {
+ return 1
+ }
+ return 0
+@@ -9217,9 +9212,9 @@ proc check_effective_target_supports_stack_clash_protection { } {
+ # Return 1 if the target creates a frame pointer for non-leaf functions
+ # Note we ignore cases where we apply tail call optimization here.
+ proc check_effective_target_frame_pointer_for_non_leaf { } {
+- if { [istarget aarch*-*-*] } {
+- return 1
+- }
++# if { [istarget aarch*-*-*] } {
++# return 1
++# }
+
+ # Solaris/x86 defaults to -fno-omit-frame-pointer.
+ if { [istarget i?86-*-solaris*] || [istarget x86_64-*-solaris*] } {
diff --git a/SOURCES/gcc8-rh1574936.patch b/SOURCES/gcc8-rh1574936.patch
new file mode 100644
index 0000000..32db990
--- /dev/null
+++ b/SOURCES/gcc8-rh1574936.patch
@@ -0,0 +1,31 @@
+crt files and statically linked libgcc objects cause false positives
+in annobin coverage, so we add the assembler flag to generate notes
+for them.
+
+The patch also adds notes to libgcc_s.so, but this is harmless because
+these notes only confer that there is no other annobin markup.
+
+2018-07-25 Florian Weimer
+
+ * Makefile.in (LIBGCC2_CFLAGS, CRTSTUFF_CFLAGS): Add
+ -Wa,--generate-missing-build-notes=yes.
+
+--- libgcc/Makefile.in 2018-01-13 13:05:41.000000000 +0100
++++ libgcc/Makefile.in 2018-07-25 13:15:02.036226940 +0200
+@@ -244,6 +244,7 @@
+ LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
+ $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \
+ -fbuilding-libgcc -fno-stack-protector \
++ -Wa,--generate-missing-build-notes=yes \
+ $(INHIBIT_LIBC_CFLAGS)
+
+ # Additional options to use when compiling libgcc2.a.
+@@ -297,6 +298,7 @@
+ $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \
+ -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
+ -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \
++ -Wa,--generate-missing-build-notes=yes \
+ $(INHIBIT_LIBC_CFLAGS)
+
+ # Extra flags to use when compiling crt{begin,end}.o.
+
diff --git a/SOURCES/gcc8-rh1668903-1.patch b/SOURCES/gcc8-rh1668903-1.patch
new file mode 100644
index 0000000..9ffff09
--- /dev/null
+++ b/SOURCES/gcc8-rh1668903-1.patch
@@ -0,0 +1,406 @@
+commit 126dab7c9d84294f256b1f7bf91c24a9e7103249
+Author: qinzhao
+Date: Thu Nov 29 16:06:03 2018 +0000
+
+ Add a new option -flive-patching={inline-only-static|inline-clone}
+ to support live patching in GCC.
+
+ 2018-11-29 qing zhao
+
+ gcc/ChangeLog:
+
+ * cif-code.def (EXTERN_LIVE_ONLY_STATIC): New CIF code.
+ * common.opt: Add -flive-patching flag.
+ * doc/invoke.texi: Document -flive-patching.
+ * flag-types.h (enum live_patching_level): New enum.
+ * ipa-inline.c (can_inline_edge_p): Disable external functions from
+ inlining when flag_live_patching is LIVE_PATCHING_INLINE_ONLY_STATIC.
+ * opts.c (control_options_for_live_patching): New function.
+ (finish_options): Make flag_live_patching incompatible with flag_lto.
+ Control IPA optimizations based on different levels of
+ flag_live_patching.
+
+ gcc/testsuite/ChangeLog:
+
+ * gcc.dg/live-patching-1.c: New test.
+ * gcc.dg/live-patching-2.c: New test.
+ * gcc.dg/live-patching-3.c: New test.
+ * gcc.dg/tree-ssa/writeonly-3.c: New test.
+ * gcc.target/i386/ipa-stack-alignment-2.c: New test.
+
+
+ git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266627 138bc75d-0d04-0410-961f-82ee72b054a4
+
+--- gcc/cif-code.def
++++ gcc/cif-code.def
+@@ -132,6 +132,12 @@ DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR,
+ DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
+ N_("function attribute mismatch"))
+
++/* We can't inline because the user requests only static functions
++ but the function has external linkage for live patching purpose. */
++DEFCIFCODE(EXTERN_LIVE_ONLY_STATIC, CIF_FINAL_ERROR,
++ N_("function has external linkage when the user requests only"
++ " inlining static for live patching"))
++
+ /* We proved that the call is unreachable. */
+ DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
+ N_("unreachable"))
+--- gcc/common.opt
++++ gcc/common.opt
+@@ -2181,6 +2181,24 @@ starts and when the destructor finishes.
+ flifetime-dse=
+ Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2)
+
++flive-patching
++Common RejectNegative Alias(flive-patching=,inline-clone) Optimization
++
++flive-patching=
++Common Report Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
++-flive-patching=[inline-only-static|inline-clone] Control IPA
++optimizations to provide a safe compilation for live-patching. At the same
++time, provides multiple-level control on the enabled IPA optimizations.
++
++Enum
++Name(live_patching_level) Type(enum live_patching_level) UnknownError(unknown Live-Patching Level %qs)
++
++EnumValue
++Enum(live_patching_level) String(inline-only-static) Value(LIVE_PATCHING_INLINE_ONLY_STATIC)
++
++EnumValue
++Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
++
+ flive-range-shrinkage
+ Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
+ Relief of register pressure through live range shrinkage.
+--- gcc/doc/invoke.texi
++++ gcc/doc/invoke.texi
+@@ -389,6 +389,7 @@ Objective-C and Objective-C++ Dialects}.
+ -fipa-bit-cp -fipa-vrp @gol
+ -fipa-pta -fipa-profile -fipa-pure-const -fipa-reference -fipa-icf @gol
+ -fira-algorithm=@var{algorithm} @gol
++-flive-patching=@var{level} @gol
+ -fira-region=@var{region} -fira-hoist-pressure @gol
+ -fira-loop-pressure -fno-ira-share-save-slots @gol
+ -fno-ira-share-spill-slots @gol
+@@ -9291,6 +9292,65 @@ equivalences that are found only by GCC and equivalences found only by Gold.
+
+ This flag is enabled by default at @option{-O2} and @option{-Os}.
+
++@item -flive-patching=@var{level}
++@opindex flive-patching
++Control GCC's optimizations to provide a safe compilation for live-patching.
++
++If the compiler's optimization uses a function's body or information extracted
++from its body to optimize/change another function, the latter is called an
++impacted function of the former. If a function is patched, its impacted
++functions should be patched too.
++
++The impacted functions are decided by the compiler's interprocedural
++optimizations. For example, inlining a function into its caller, cloning
++a function and changing its caller to call this new clone, or extracting
++a function's pureness/constness information to optimize its direct or
++indirect callers, etc.
++
++Usually, the more IPA optimizations enabled, the larger the number of
++impacted functions for each function. In order to control the number of
++impacted functions and computed the list of impacted function easily,
++we provide control to partially enable IPA optimizations on two different
++levels.
++
++The @var{level} argument should be one of the following:
++
++@table @samp
++
++@item inline-clone
++
++Only enable inlining and cloning optimizations, which includes inlining,
++cloning, interprocedural scalar replacement of aggregates and partial inlining.
++As a result, when patching a function, all its callers and its clones'
++callers need to be patched as well.
++
++@option{-flive-patching=inline-clone} disables the following optimization flags:
++@gccoptlist{-fwhole-program -fipa-pta -fipa-reference -fipa-ra @gol
++-fipa-icf -fipa-icf-functions -fipa-icf-variables @gol
++-fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable @gol
++-fipa-stack-alignment}
++
++@item inline-only-static
++
++Only enable inlining of static functions.
++As a result, when patching a static function, all its callers need to be
++patches as well.
++
++In addition to all the flags that -flive-patching=inline-clone disables,
++@option{-flive-patching=inline-only-static} disables the following additional
++optimization flags:
++@gccoptlist{-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp}
++
++@end table
++
++When -flive-patching specified without any value, the default value
++is "inline-clone".
++
++This flag is disabled by default.
++
++Note that -flive-patching is not supported with link-time optimizer.
++(@option{-flto}).
++
+ @item -fisolate-erroneous-paths-dereference
+ @opindex fisolate-erroneous-paths-dereference
+ Detect paths that trigger erroneous or undefined behavior due to
+--- gcc/flag-types.h
++++ gcc/flag-types.h
+@@ -123,6 +123,14 @@ enum stack_reuse_level
+ SR_ALL
+ };
+
++/* The live patching level. */
++enum live_patching_level
++{
++ LIVE_PATCHING_NONE = 0,
++ LIVE_PATCHING_INLINE_ONLY_STATIC,
++ LIVE_PATCHING_INLINE_CLONE
++};
++
+ /* The algorithm used for basic block reordering. */
+ enum reorder_blocks_algorithm
+ {
+--- gcc/ipa-inline.c
++++ gcc/ipa-inline.c
+@@ -379,6 +379,12 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
+ e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
+ inlinable = false;
+ }
++ else if (callee->externally_visible
++ && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
++ {
++ e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
++ inlinable = false;
++ }
+ if (!inlinable && report)
+ report_inline_failed_reason (e);
+ return inlinable;
+--- gcc/opts.c
++++ gcc/opts.c
+@@ -699,6 +699,152 @@ default_options_optimization (struct gcc
+ lang_mask, handlers, loc, dc);
+ }
+
++/* Control IPA optimizations based on different live patching LEVEL. */
++static void
++control_options_for_live_patching (struct gcc_options *opts,
++ struct gcc_options *opts_set,
++ enum live_patching_level level,
++ location_t loc)
++{
++ gcc_assert (level > LIVE_PATCHING_NONE);
++
++ switch (level)
++ {
++ case LIVE_PATCHING_INLINE_ONLY_STATIC:
++ if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
++ error_at (loc,
++ "%<-fipa-cp-clone%> is incompatible with "
++ "%<-flive-patching=inline-only-static%>");
++ else
++ opts->x_flag_ipa_cp_clone = 0;
++
++ if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
++ error_at (loc,
++ "%<-fipa-sra%> is incompatible with "
++ "%<-flive-patching=inline-only-static%>");
++ else
++ opts->x_flag_ipa_sra = 0;
++
++ if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
++ error_at (loc,
++ "%<-fpartial-inlining%> is incompatible with "
++ "%<-flive-patching=inline-only-static%>");
++ else
++ opts->x_flag_partial_inlining = 0;
++
++ if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
++ error_at (loc,
++ "%<-fipa-cp%> is incompatible with "
++ "%<-flive-patching=inline-only-static%>");
++ else
++ opts->x_flag_ipa_cp = 0;
++
++ /* FALLTHROUGH. */
++ case LIVE_PATCHING_INLINE_CLONE:
++ /* live patching should disable whole-program optimization. */
++ if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
++ error_at (loc,
++ "%<-fwhole-program%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_whole_program = 0;
++
++ /* visibility change should be excluded by !flag_whole_program
++ && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra
++ && !flag_partial_inlining. */
++
++ if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
++ error_at (loc,
++ "%<-fipa-pta%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_pta = 0;
++
++ if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
++ error_at (loc,
++ "%<-fipa-reference%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_reference = 0;
++
++ if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra)
++ error_at (loc,
++ "%<-fipa-ra%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_ra = 0;
++
++ if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
++ error_at (loc,
++ "%<-fipa-icf%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_icf = 0;
++
++ if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
++ error_at (loc,
++ "%<-fipa-icf-functions%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_icf_functions = 0;
++
++ if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
++ error_at (loc,
++ "%<-fipa-icf-variables%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_icf_variables = 0;
++
++ if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
++ error_at (loc,
++ "%<-fipa-bit-cp%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_bit_cp = 0;
++
++ if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
++ error_at (loc,
++ "%<-fipa-vrp%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_vrp = 0;
++
++ if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
++ error_at (loc,
++ "%<-fipa-pure-const%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_pure_const = 0;
++
++ /* FIXME: disable unreachable code removal. */
++
++ /* discovery of functions/variables with no address taken. */
++// GCC 8 doesn't have these options.
++#if 0
++ if (opts_set->x_flag_ipa_reference_addressable
++ && opts->x_flag_ipa_reference_addressable)
++ error_at (loc,
++ "%<-fipa-reference-addressable%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_reference_addressable = 0;
++
++ /* ipa stack alignment propagation. */
++ if (opts_set->x_flag_ipa_stack_alignment
++ && opts->x_flag_ipa_stack_alignment)
++ error_at (loc,
++ "%<-fipa-stack-alignment%> is incompatible with "
++ "%<-flive-patching=inline-only-static|inline-clone%>");
++ else
++ opts->x_flag_ipa_stack_alignment = 0;
++#endif
++
++ break;
++ default:
++ gcc_unreachable ();
++ }
++}
++
+ /* After all options at LOC have been read into OPTS and OPTS_SET,
+ finalize settings of those options and diagnose incompatible
+ combinations. */
+@@ -1057,6 +1203,18 @@ finish_options (struct gcc_options *opts
+ sorry ("transactional memory is not supported with "
+ "%<-fsanitize=kernel-address%>");
+
++ /* Currently live patching is not support for LTO. */
++ if (opts->x_flag_live_patching && opts->x_flag_lto)
++ sorry ("live patching is not supported with LTO");
++
++ /* Control IPA optimizations based on different -flive-patching level. */
++ if (opts->x_flag_live_patching)
++ {
++ control_options_for_live_patching (opts, opts_set,
++ opts->x_flag_live_patching,
++ loc);
++ }
++
+ /* Comes from final.c -- no real reason to change it. */
+ #define MAX_CODE_ALIGN 16
+ #define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
+--- /dev/null
++++ gcc/testsuite/gcc.dg/live-patching-1.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-ipa-inline" } */
++
++extern int sum, n, m;
++
++int foo (int a)
++{
++ return a + n;
++}
++
++static int bar (int b)
++{
++ return b * m;
++}
++
++int main()
++{
++ sum = foo (m) + bar (n);
++ return 0;
++}
++
++/* { dg-final { scan-ipa-dump "foo/0 function has external linkage when the user requests only inlining static for live patching" "inline" } } */
+--- /dev/null
++++ gcc/testsuite/gcc.dg/live-patching-2.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -flive-patching -flto" } */
++
++int main()
++{
++ return 0;
++}
++
++/* { dg-message "sorry, unimplemented: live patching is not supported with LTO" "-flive-patching and -flto together" { target *-*-* } 0 } */
+--- /dev/null
++++ gcc/testsuite/gcc.dg/live-patching-3.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-O1 -flive-patching -fwhole-program" } */
++
++int main()
++{
++ return 0;
++}
++
++/* { dg-message "'-fwhole-program' is incompatible with '-flive-patching=inline-only-static|inline-clone’" "" {target "*-*-*"} 0 } */
diff --git a/SOURCES/gcc8-rh1668903-2.patch b/SOURCES/gcc8-rh1668903-2.patch
new file mode 100644
index 0000000..92eaf54
--- /dev/null
+++ b/SOURCES/gcc8-rh1668903-2.patch
@@ -0,0 +1,73 @@
+commit 9939b2f79bd9b75b99080a17f3d6f1214d543477
+Author: qinzhao
+Date: Wed Apr 3 19:00:25 2019 +0000
+
+ 2019-04-03 qing zhao
+
+ PR tree-optimization/89730
+ * ipa-inline.c (can_inline_edge_p): Delete the checking for
+ -flive-patching=inline-only-static.
+ (can_inline_edge_by_limits_p): Add the checking for
+ -flive-patching=inline-only-static and grant always_inline
+ even when -flive-patching=inline-only-static is specified.
+
+ * gcc.dg/live-patching-4.c: New test.
+
+
+ git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270134 138bc75d-0d04-0410-961f-82ee72b054a4
+
+--- gcc/ipa-inline.c
++++ gcc/ipa-inline.c
+@@ -385,12 +385,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
+ e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
+ inlinable = false;
+ }
+- else if (callee->externally_visible
+- && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
+- {
+- e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
+- inlinable = false;
+- }
+ if (!inlinable && report)
+ report_inline_failed_reason (e);
+ return inlinable;
+@@ -433,6 +427,13 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
+ DECL_ATTRIBUTES (caller->decl))
+ && !caller_growth_limits (e))
+ inlinable = false;
++ else if (callee->externally_visible
++ && !DECL_DISREGARD_INLINE_LIMITS (callee->decl)
++ && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
++ {
++ e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
++ inlinable = false;
++ }
+ /* Don't inline a function with a higher optimization level than the
+ caller. FIXME: this is really just tip of iceberg of handling
+ optimization attribute. */
+--- /dev/null
++++ gcc/testsuite/gcc.dg/live-patching-4.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-tree-einline-optimized" } */
++
++extern int sum, n, m;
++
++extern inline __attribute__((always_inline)) int foo (int a);
++inline __attribute__((always_inline)) int foo (int a)
++{
++ return a + n;
++}
++
++static int bar (int b)
++{
++ return b * m;
++}
++
++int main()
++{
++ sum = foo (m) + bar (n);
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump "Inlining foo into main" "einline" } } */
diff --git a/SOURCES/gcc8-rh1668903-3.patch b/SOURCES/gcc8-rh1668903-3.patch
new file mode 100644
index 0000000..129d037
--- /dev/null
+++ b/SOURCES/gcc8-rh1668903-3.patch
@@ -0,0 +1,85 @@
+commit 77e6311332590004c5aec82ceeb45e4d4d93f690
+Author: redi
+Date: Thu Apr 11 08:52:22 2019 +0000
+
+ Clarify documentation for -flive-patching
+
+ * doc/invoke.texi (Optimize Options): Clarify -flive-patching docs.
+
+ git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270276 138bc75d-0d04-0410-961f-82ee72b054a4
+
+--- gcc/doc/invoke.texi
++++ gcc/doc/invoke.texi
+@@ -9367,24 +9367,24 @@ This flag is enabled by default at @option{-O2} and @option{-Os}.
+
+ @item -flive-patching=@var{level}
+ @opindex flive-patching
+-Control GCC's optimizations to provide a safe compilation for live-patching.
++Control GCC's optimizations to produce output suitable for live-patching.
+
+ If the compiler's optimization uses a function's body or information extracted
+ from its body to optimize/change another function, the latter is called an
+ impacted function of the former. If a function is patched, its impacted
+ functions should be patched too.
+
+-The impacted functions are decided by the compiler's interprocedural
+-optimizations. For example, inlining a function into its caller, cloning
+-a function and changing its caller to call this new clone, or extracting
+-a function's pureness/constness information to optimize its direct or
+-indirect callers, etc.
++The impacted functions are determined by the compiler's interprocedural
++optimizations. For example, a caller is impacted when inlining a function
++into its caller,
++cloning a function and changing its caller to call this new clone,
++or extracting a function's pureness/constness information to optimize
++its direct or indirect callers, etc.
+
+ Usually, the more IPA optimizations enabled, the larger the number of
+ impacted functions for each function. In order to control the number of
+-impacted functions and computed the list of impacted function easily,
+-we provide control to partially enable IPA optimizations on two different
+-levels.
++impacted functions and more easily compute the list of impacted function,
++IPA optimizations can be partially enabled at two different levels.
+
+ The @var{level} argument should be one of the following:
+
+@@ -9395,7 +9395,7 @@ The @var{level} argument should be one of the following:
+ Only enable inlining and cloning optimizations, which includes inlining,
+ cloning, interprocedural scalar replacement of aggregates and partial inlining.
+ As a result, when patching a function, all its callers and its clones'
+-callers need to be patched as well.
++callers are impacted, therefore need to be patched as well.
+
+ @option{-flive-patching=inline-clone} disables the following optimization flags:
+ @gccoptlist{-fwhole-program -fipa-pta -fipa-reference -fipa-ra @gol
+@@ -9406,22 +9406,23 @@ callers need to be patched as well.
+ @item inline-only-static
+
+ Only enable inlining of static functions.
+-As a result, when patching a static function, all its callers need to be
+-patches as well.
++As a result, when patching a static function, all its callers are impacted
++and so need to be patched as well.
+
+-In addition to all the flags that -flive-patching=inline-clone disables,
++In addition to all the flags that @option{-flive-patching=inline-clone}
++disables,
+ @option{-flive-patching=inline-only-static} disables the following additional
+ optimization flags:
+ @gccoptlist{-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp}
+
+ @end table
+
+-When -flive-patching specified without any value, the default value
+-is "inline-clone".
++When @option{-flive-patching} is specified without any value, the default value
++is @var{inline-clone}.
+
+ This flag is disabled by default.
+
+-Note that -flive-patching is not supported with link-time optimizer.
++Note that @option{-flive-patching} is not supported with link-time optimization
+ (@option{-flto}).
+
+ @item -fisolate-erroneous-paths-dereference
diff --git a/SOURCES/gcc8-rh1670535.patch b/SOURCES/gcc8-rh1670535.patch
new file mode 100644
index 0000000..961c278
--- /dev/null
+++ b/SOURCES/gcc8-rh1670535.patch
@@ -0,0 +1,93 @@
+2018-11-08 Roman Geissler
+
+ * collect2.c (linker_select): Add USE_LLD_LD.
+ (ld_suffixes): Add ld.lld.
+ (main): Handle -fuse-ld=lld.
+ * common.opt (-fuse-ld=lld): New option.
+ * doc/invoke.texi (-fuse-ld=lld): Document.
+ * opts.c (common_handle_option): Handle OPT_fuse_ld_lld.
+
+--- gcc/collect2.c
++++ gcc/collect2.c
+@@ -831,6 +831,7 @@ main (int argc, char **argv)
+ USE_PLUGIN_LD,
+ USE_GOLD_LD,
+ USE_BFD_LD,
++ USE_LLD_LD,
+ USE_LD_MAX
+ } selected_linker = USE_DEFAULT_LD;
+ static const char *const ld_suffixes[USE_LD_MAX] =
+@@ -838,7 +839,8 @@ main (int argc, char **argv)
+ "ld",
+ PLUGIN_LD_SUFFIX,
+ "ld.gold",
+- "ld.bfd"
++ "ld.bfd",
++ "ld.lld"
+ };
+ static const char *const real_ld_suffix = "real-ld";
+ static const char *const collect_ld_suffix = "collect-ld";
+@@ -1007,6 +1009,8 @@ main (int argc, char **argv)
+ selected_linker = USE_BFD_LD;
+ else if (strcmp (argv[i], "-fuse-ld=gold") == 0)
+ selected_linker = USE_GOLD_LD;
++ else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
++ selected_linker = USE_LLD_LD;
+
+ #ifdef COLLECT_EXPORT_LIST
+ /* These flags are position independent, although their order
+@@ -1096,7 +1100,8 @@ main (int argc, char **argv)
+ /* Maybe we know the right file to use (if not cross). */
+ ld_file_name = 0;
+ #ifdef DEFAULT_LINKER
+- if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD)
++ if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD ||
++ selected_linker == USE_LLD_LD)
+ {
+ char *linker_name;
+ # ifdef HOST_EXECUTABLE_SUFFIX
+@@ -1315,7 +1320,7 @@ main (int argc, char **argv)
+ else if (!use_collect_ld
+ && strncmp (arg, "-fuse-ld=", 9) == 0)
+ {
+- /* Do not pass -fuse-ld={bfd|gold} to the linker. */
++ /* Do not pass -fuse-ld={bfd|gold|lld} to the linker. */
+ ld1--;
+ ld2--;
+ }
+--- gcc/common.opt
++++ gcc/common.opt
+@@ -2732,6 +2732,10 @@ fuse-ld=gold
+ Common Driver Negative(fuse-ld=bfd)
+ Use the gold linker instead of the default linker.
+
++fuse-ld=lld
++Common Driver Negative(fuse-ld=lld)
++Use the lld LLVM linker instead of the default linker.
++
+ fuse-linker-plugin
+ Common Undocumented Var(flag_use_linker_plugin)
+
+--- gcc/doc/invoke.texi
++++ gcc/doc/invoke.texi
+@@ -12610,6 +12610,10 @@ Use the @command{bfd} linker instead of the default linker.
+ @opindex fuse-ld=gold
+ Use the @command{gold} linker instead of the default linker.
+
++@item -fuse-ld=lld
++@opindex fuse-ld=lld
++Use the LLVM @command{lld} linker instead of the default linker.
++
+ @cindex Libraries
+ @item -l@var{library}
+ @itemx -l @var{library}
+--- gcc/opts.c
++++ gcc/opts.c
+@@ -2557,6 +2557,7 @@ common_handle_option (struct gcc_options *opts,
+
+ case OPT_fuse_ld_bfd:
+ case OPT_fuse_ld_gold:
++ case OPT_fuse_ld_lld:
+ case OPT_fuse_linker_plugin:
+ /* No-op. Used by the driver and passed to us because it starts with f.*/
+ break;
diff --git a/SOURCES/gcc8-rh1711346.patch b/SOURCES/gcc8-rh1711346.patch
new file mode 100644
index 0000000..0d9017a
--- /dev/null
+++ b/SOURCES/gcc8-rh1711346.patch
@@ -0,0 +1,279 @@
+2019-05-29 Jakub Jelinek
+
+ PR fortran/90329
+ * lto-streamer.h (LTO_minor_version): Bump to 2.
+
+ Backported from mainline
+ 2019-05-16 Jakub Jelinek
+
+ PR fortran/90329
+ * tree-core.h (struct tree_decl_common): Document
+ decl_nonshareable_flag for PARM_DECLs.
+ * tree.h (DECL_HIDDEN_STRING_LENGTH): Define.
+ * calls.c (expand_call): Don't try tail call if caller
+ has any DECL_HIDDEN_STRING_LENGTH PARM_DECLs that are or might be
+ passed on the stack and callee needs to pass any arguments on the
+ stack.
+ * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use
+ else if instead of series of mutually exclusive ifs. Handle
+ DECL_HIDDEN_STRING_LENGTH for PARM_DECLs.
+ * tree-streamer-out.c (pack_ts_decl_common_value_fields): Likewise.
+
+ * lang.opt (fbroken-callers): Remove.
+ (ftail-call-workaround, ftail-call-workaround=): New options.
+ * gfortran.h (struct gfc_namespace): Add implicit_interface_calls.
+ * interface.c (gfc_procedure_use): Set implicit_interface_calls
+ for calls to implicit interface procedures.
+ * trans-decl.c (create_function_arglist): Use flag_tail_call_workaround
+ instead of flag_broken_callers. If it is not 2, also require
+ sym->ns->implicit_interface_calls.
+ * invoke.texi (fbroken-callers): Remove documentation.
+ (ftail-call-workaround, ftail-call-workaround=): Document.
+
+ 2019-05-19 Thomas Koenig
+
+ PR fortran/90329
+ * invoke.texi: Document -fbroken-callers.
+ * lang.opt: Add -fbroken-callers.
+ * trans-decl.c (create_function_arglist): Only set
+ DECL_HIDDEN_STRING_LENGTH if flag_broken_callers is set.
+
+ 2019-05-16 Jakub Jelinek
+
+ PR fortran/90329
+ * trans-decl.c (create_function_arglist): Set
+ DECL_HIDDEN_STRING_LENGTH on hidden string length PARM_DECLs if
+ len is constant.
+
+--- gcc/calls.c
++++ gcc/calls.c
+@@ -3754,6 +3754,28 @@ expand_call (tree exp, rtx target, int ignore)
+ || dbg_cnt (tail_call) == false)
+ try_tail_call = 0;
+
++ /* Workaround buggy C/C++ wrappers around Fortran routines with
++ character(len=constant) arguments if the hidden string length arguments
++ are passed on the stack; if the callers forget to pass those arguments,
++ attempting to tail call in such routines leads to stack corruption.
++ Avoid tail calls in functions where at least one such hidden string
++ length argument is passed (partially or fully) on the stack in the
++ caller and the callee needs to pass any arguments on the stack.
++ See PR90329. */
++ if (try_tail_call && maybe_ne (args_size.constant, 0))
++ for (tree arg = DECL_ARGUMENTS (current_function_decl);
++ arg; arg = DECL_CHAIN (arg))
++ if (DECL_HIDDEN_STRING_LENGTH (arg) && DECL_INCOMING_RTL (arg))
++ {
++ subrtx_iterator::array_type array;
++ FOR_EACH_SUBRTX (iter, array, DECL_INCOMING_RTL (arg), NONCONST)
++ if (MEM_P (*iter))
++ {
++ try_tail_call = 0;
++ break;
++ }
++ }
++
+ /* If the user has marked the function as requiring tail-call
+ optimization, attempt it. */
+ if (must_tail_call)
+--- gcc/fortran/gfortran.h
++++ gcc/fortran/gfortran.h
+@@ -1857,6 +1857,9 @@ typedef struct gfc_namespace
+
+ /* Set to 1 for !$ACC ROUTINE namespaces. */
+ unsigned oacc_routine:1;
++
++ /* Set to 1 if there are any calls to procedures with implicit interface. */
++ unsigned implicit_interface_calls:1;
+ }
+ gfc_namespace;
+
+--- gcc/fortran/interface.c
++++ gcc/fortran/interface.c
+@@ -3657,6 +3657,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
+ gfc_warning (OPT_Wimplicit_procedure,
+ "Procedure %qs called at %L is not explicitly declared",
+ sym->name, where);
++ gfc_find_proc_namespace (sym->ns)->implicit_interface_calls = 1;
+ }
+
+ if (sym->attr.if_source == IFSRC_UNKNOWN)
+--- gcc/fortran/invoke.texi
++++ gcc/fortran/invoke.texi
+@@ -181,7 +181,8 @@ and warnings}.
+ @item Code Generation Options
+ @xref{Code Gen Options,,Options for code generation conventions}.
+ @gccoptlist{-faggressive-function-elimination -fblas-matmul-limit=@var{n} @gol
+--fbounds-check -fcheck-array-temporaries @gol
++-fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol
++-fcheck-array-temporaries @gol
+ -fcheck=@var{} @gol
+ -fcoarray=@var{} -fexternal-blas -ff2c
+ -ffrontend-loop-interchange @gol
+@@ -1580,6 +1581,39 @@ warnings for generated array temporaries.
+ @c Note: This option is also referred in gcc's manpage
+ Deprecated alias for @option{-fcheck=bounds}.
+
++@item -ftail-call-workaround
++@itemx -ftail-call-workaround=@var{n}
++@opindex @code{tail-call-workaround}
++Some C interfaces to Fortran codes violate the gfortran ABI by
++omitting the hidden character length arguments as described in
++@xref{Argument passing conventions}. This can lead to crashes
++because pushing arguments for tail calls can overflow the stack.
++
++To provide a workaround for existing binary packages, this option
++disables tail call optimization for gfortran procedures with character
++arguments. With @option{-ftail-call-workaround=2} tail call optimization
++is disabled in all gfortran procedures with character arguments,
++with @option{-ftail-call-workaround=1} or equivalent
++@option{-ftail-call-workaround} only in gfortran procedures with character
++arguments that call implicitly prototyped procedures.
++
++Using this option can lead to problems including crashes due to
++insufficient stack space.
++
++It is @emph{very strongly} recommended to fix the code in question.
++The @option{-fc-prototypes-external} option can be used to generate
++prototypes which conform to gfortran's ABI, for inclusion in the
++source code.
++
++Support for this option will likely be withdrawn in a future release
++of gfortran.
++
++The negative form, @option{-fno-tail-call-workaround} or equivalent
++@option{-ftail-call-workaround=0}, can be used to disable this option.
++
++Default is currently @option{-ftail-call-workaround}, this will change
++in future releases.
++
+ @item -fcheck-array-temporaries
+ @opindex @code{fcheck-array-temporaries}
+ Deprecated alias for @option{-fcheck=array-temps}.
+--- gcc/fortran/lang.opt
++++ gcc/fortran/lang.opt
+@@ -742,6 +742,13 @@ fsign-zero
+ Fortran Var(flag_sign_zero) Init(1)
+ Apply negative sign to zero values.
+
++ftail-call-workaround
++Fortran Alias(ftail-call-workaround=,1,0)
++
++ftail-call-workaround=
++Fortran RejectNegative Joined UInteger IntegerRange(0, 2) Var(flag_tail_call_workaround) Init(1)
++Disallow tail call optimization when a calling routine may have omitted character lengths.
++
+ funderscoring
+ Fortran Var(flag_underscoring) Init(1)
+ Append underscores to externally visible names.
+--- gcc/fortran/trans-decl.c
++++ gcc/fortran/trans-decl.c
+@@ -2513,6 +2513,17 @@ create_function_arglist (gfc_symbol * sym)
+ TREE_READONLY (length) = 1;
+ gfc_finish_decl (length);
+
++ /* Marking the length DECL_HIDDEN_STRING_LENGTH will lead
++ to tail calls being disabled. Only do that if we
++ potentially have broken callers. */
++ if (flag_tail_call_workaround
++ && f->sym->ts.u.cl
++ && f->sym->ts.u.cl->length
++ && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
++ && (flag_tail_call_workaround == 2
++ || f->sym->ns->implicit_interface_calls))
++ DECL_HIDDEN_STRING_LENGTH (length) = 1;
++
+ /* Remember the passed value. */
+ if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length)
+ {
+--- gcc/lto-streamer.h
++++ gcc/lto-streamer.h
+@@ -121,7 +121,7 @@ along with GCC; see the file COPYING3. If not see
+ form followed by the data for the string. */
+
+ #define LTO_major_version 7
+-#define LTO_minor_version 1
++#define LTO_minor_version 2
+
+ typedef unsigned char lto_decl_flags_t;
+
+--- gcc/tree-core.h
++++ gcc/tree-core.h
+@@ -1644,6 +1644,7 @@ struct GTY(()) tree_decl_common {
+ /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P. */
+ unsigned decl_read_flag : 1;
+ /* In a VAR_DECL or RESULT_DECL, this is DECL_NONSHAREABLE. */
++ /* In a PARM_DECL, this is DECL_HIDDEN_STRING_LENGTH. */
+ unsigned decl_nonshareable_flag : 1;
+
+ /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
+--- gcc/tree-streamer-in.c
++++ gcc/tree-streamer-in.c
+@@ -252,7 +252,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
+ LABEL_DECL_UID (expr) = -1;
+ }
+
+- if (TREE_CODE (expr) == FIELD_DECL)
++ else if (TREE_CODE (expr) == FIELD_DECL)
+ {
+ DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
+ DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+@@ -260,12 +260,15 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
+ expr->decl_common.off_align = bp_unpack_value (bp, 8);
+ }
+
+- if (VAR_P (expr))
++ else if (VAR_P (expr))
+ {
+ DECL_HAS_DEBUG_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+ DECL_NONLOCAL_FRAME (expr) = (unsigned) bp_unpack_value (bp, 1);
+ }
+
++ else if (TREE_CODE (expr) == PARM_DECL)
++ DECL_HIDDEN_STRING_LENGTH (expr) = (unsigned) bp_unpack_value (bp, 1);
++
+ if (TREE_CODE (expr) == RESULT_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || VAR_P (expr))
+--- gcc/tree-streamer-out.c
++++ gcc/tree-streamer-out.c
+@@ -212,7 +212,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
+ bp_pack_var_len_unsigned (bp, EH_LANDING_PAD_NR (expr));
+ }
+
+- if (TREE_CODE (expr) == FIELD_DECL)
++ else if (TREE_CODE (expr) == FIELD_DECL)
+ {
+ bp_pack_value (bp, DECL_PACKED (expr), 1);
+ bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
+@@ -220,12 +220,15 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
+ bp_pack_value (bp, expr->decl_common.off_align, 8);
+ }
+
+- if (VAR_P (expr))
++ else if (VAR_P (expr))
+ {
+ bp_pack_value (bp, DECL_HAS_DEBUG_EXPR_P (expr), 1);
+ bp_pack_value (bp, DECL_NONLOCAL_FRAME (expr), 1);
+ }
+
++ else if (TREE_CODE (expr) == PARM_DECL)
++ bp_pack_value (bp, DECL_HIDDEN_STRING_LENGTH (expr), 1);
++
+ if (TREE_CODE (expr) == RESULT_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || VAR_P (expr))
+--- gcc/tree.h
++++ gcc/tree.h
+@@ -909,6 +909,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
+ (TREE_CHECK2 (NODE, VAR_DECL, \
+ RESULT_DECL)->decl_common.decl_nonshareable_flag)
+
++/* In a PARM_DECL, set for Fortran hidden string length arguments that some
++ buggy callers don't pass to the callee. */
++#define DECL_HIDDEN_STRING_LENGTH(NODE) \
++ (TREE_CHECK (NODE, PARM_DECL)->decl_common.decl_nonshareable_flag)
++
+ /* In a CALL_EXPR, means that the call is the jump from a thunk to the
+ thunked-to function. */
+ #define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag)
diff --git a/SOURCES/gcc8-sparc-config-detection.patch b/SOURCES/gcc8-sparc-config-detection.patch
new file mode 100644
index 0000000..bb06b35
--- /dev/null
+++ b/SOURCES/gcc8-sparc-config-detection.patch
@@ -0,0 +1,40 @@
+--- gcc/config.gcc.jj 2008-04-24 15:42:46.000000000 -0500
++++ gcc/config.gcc 2008-04-24 15:44:51.000000000 -0500
+@@ -2790,7 +2790,7 @@ sparc-*-rtems*)
+ tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h"
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems"
+ ;;
+-sparc-*-linux*)
++sparc-*-linux* | sparcv9-*-linux*)
+ tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h"
+ extra_options="${extra_options} sparc/long-double-switch.opt"
+ case ${target} in
+@@ -2844,7 +2844,7 @@ sparc64-*-rtems*)
+ extra_options="${extra_options}"
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems-64"
+ ;;
+-sparc64-*-linux*)
++sparc64*-*-linux*)
+ tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default64.h sparc/linux64.h sparc/tso.h"
+ extra_options="${extra_options} sparc/long-double-switch.opt"
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux64"
+--- libgcc/config.host.jj 2008-04-24 15:46:19.000000000 -0500
++++ libgcc/config.host 2008-04-24 15:46:49.000000000 -0500
+@@ -1002,7 +1002,7 @@ sparc-*-elf*)
+ tmake_file="${tmake_file} t-fdpbit t-crtfm"
+ extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
+ ;;
+-sparc-*-linux*) # SPARC's running GNU/Linux, libc6
++sparc-*-linux* | sparcv9-*-linux*) # SPARC's running GNU/Linux, libc6
+ tmake_file="${tmake_file} t-crtfm"
+ if test "${host_address}" = 64; then
+ tmake_file="$tmake_file sparc/t-linux64"
+@@ -1050,7 +1050,7 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*
+ tmake_file="$tmake_file t-crtfm"
+ extra_parts="$extra_parts crtfastmath.o"
+ ;;
+-sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux
++sparc64*-*-linux*) # 64-bit SPARC's running GNU/Linux
+ extra_parts="$extra_parts crtfastmath.o"
+ tmake_file="${tmake_file} t-crtfm sparc/t-linux"
+ if test "${host_address}" = 64; then
diff --git a/SOURCES/nvptx-tools-build.patch b/SOURCES/nvptx-tools-build.patch
new file mode 100644
index 0000000..53d7483
--- /dev/null
+++ b/SOURCES/nvptx-tools-build.patch
@@ -0,0 +1,11 @@
+--- nvptx-tools/nvptx-as.c.jj 2017-01-20 12:40:18.000000000 +0100
++++ nvptx-tools/nvptx-as.c 2017-01-20 12:43:53.864271442 +0100
+@@ -939,7 +939,7 @@ fork_execute (const char *prog, char *co
+ fatal_error ("%s: %m", errmsg);
+ }
+ else
+- fatal_error (errmsg);
++ fatal_error ("%s", errmsg);
+ }
+ do_wait (prog, pex);
+ }
diff --git a/SOURCES/nvptx-tools-glibc.patch b/SOURCES/nvptx-tools-glibc.patch
new file mode 100644
index 0000000..4b50114
--- /dev/null
+++ b/SOURCES/nvptx-tools-glibc.patch
@@ -0,0 +1,32 @@
+--- nvptx-tools/configure.ac.jj 2017-01-13 12:48:31.000000000 +0100
++++ nvptx-tools/configure.ac 2017-05-03 10:26:57.076092259 +0200
+@@ -66,6 +66,8 @@ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+
++AC_CHECK_DECLS(getopt)
++
+ AC_CONFIG_SUBDIRS([libiberty])
+ AC_CONFIG_FILES([Makefile dejagnu.exp])
+ AC_OUTPUT
+--- nvptx-tools/configure.jj 2017-01-13 12:48:54.000000000 +0100
++++ nvptx-tools/configure 2017-05-03 10:27:13.503876809 +0200
+@@ -3963,6 +3963,18 @@ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+
++ac_fn_c_check_decl "$LINENO" "getopt" "ac_cv_have_decl_getopt" "$ac_includes_default"
++if test "x$ac_cv_have_decl_getopt" = x""yes; then :
++ ac_have_decl=1
++else
++ ac_have_decl=0
++fi
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_DECL_GETOPT $ac_have_decl
++_ACEOF
++
++
+
+
+ subdirs="$subdirs libiberty"
diff --git a/SOURCES/nvptx-tools-no-ptxas.patch b/SOURCES/nvptx-tools-no-ptxas.patch
new file mode 100644
index 0000000..28bc597
--- /dev/null
+++ b/SOURCES/nvptx-tools-no-ptxas.patch
@@ -0,0 +1,947 @@
+--- nvptx-tools/configure.ac
++++ nvptx-tools/configure.ac
+@@ -51,6 +51,7 @@ LIBS="$LIBS -lcuda"
+ AC_CHECK_FUNCS([[cuGetErrorName] [cuGetErrorString]])
+ AC_CHECK_DECLS([[cuGetErrorName], [cuGetErrorString]],
+ [], [], [[#include ]])
++AC_CHECK_HEADERS(unistd.h sys/stat.h)
+
+ AC_MSG_CHECKING([for extra programs to build requiring -lcuda])
+ NVPTX_RUN=
+--- nvptx-tools/include/libiberty.h
++++ nvptx-tools/include/libiberty.h
+@@ -390,6 +390,17 @@ extern void hex_init (void);
+ /* Save files used for communication between processes. */
+ #define PEX_SAVE_TEMPS 0x4
+
++/* Max number of alloca bytes per call before we must switch to malloc.
++
++ ?? Swiped from gnulib's regex_internal.h header. Is this actually
++ the case? This number seems arbitrary, though sane.
++
++ The OS usually guarantees only one guard page at the bottom of the stack,
++ and a page size can be as small as 4096 bytes. So we cannot safely
++ allocate anything larger than 4096 bytes. Also care for the possibility
++ of a few compiler-allocated temporary stack slots. */
++#define MAX_ALLOCA_SIZE 4032
++
+ /* Prepare to execute one or more programs, with standard output of
+ each program fed to standard input of the next.
+ FLAGS As above.
+--- nvptx-tools/nvptx-as.c
++++ nvptx-tools/nvptx-as.c
+@@ -30,6 +30,9 @@
+ #include
+ #include
+ #include
++#ifdef HAVE_SYS_STAT_H
++#include
++#endif
+ #include
+ #define obstack_chunk_alloc malloc
+ #define obstack_chunk_free free
+@@ -42,6 +45,38 @@
+
+ #include "version.h"
+
++#ifndef R_OK
++#define R_OK 4
++#define W_OK 2
++#define X_OK 1
++#endif
++
++#ifndef DIR_SEPARATOR
++# define DIR_SEPARATOR '/'
++#endif
++
++#if defined (_WIN32) || defined (__MSDOS__) \
++ || defined (__DJGPP__) || defined (__OS2__)
++# define HAVE_DOS_BASED_FILE_SYSTEM
++# define HAVE_HOST_EXECUTABLE_SUFFIX
++# define HOST_EXECUTABLE_SUFFIX ".exe"
++# ifndef DIR_SEPARATOR_2
++# define DIR_SEPARATOR_2 '\\'
++# endif
++# define PATH_SEPARATOR ';'
++#else
++# define PATH_SEPARATOR ':'
++#endif
++
++#ifndef DIR_SEPARATOR_2
++# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
++#else
++# define IS_DIR_SEPARATOR(ch) \
++ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
++#endif
++
++#define DIR_UP ".."
++
+ static const char *outname = NULL;
+
+ static void __attribute__ ((format (printf, 1, 2)))
+@@ -816,7 +851,7 @@ traverse (void **slot, void *data)
+ }
+
+ static void
+-process (FILE *in, FILE *out)
++process (FILE *in, FILE *out, int verify, const char *outname)
+ {
+ symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+@@ -824,6 +859,18 @@ process (FILE *in, FILE *out)
+ const char *input = read_file (in);
+ Token *tok = tokenize (input);
+
++ /* By default, when ptxas is not in PATH, do minimalistic verification,
++ just require that the first non-comment directive is .version. */
++ if (verify < 0)
++ {
++ size_t i;
++ for (i = 0; tok[i].kind == K_comment; i++)
++ ;
++ if (tok[i].kind != K_dotted || !is_keyword (&tok[i], "version"))
++ fatal_error ("missing .version directive at start of file '%s'",
++ outname);
++ }
++
+ do
+ tok = parse_file (tok);
+ while (tok->kind);
+@@ -897,9 +944,83 @@ fork_execute (const char *prog, char *const *argv)
+ do_wait (prog, pex);
+ }
+
++/* Determine if progname is available in PATH. */
++static bool
++program_available (const char *progname)
++{
++ char *temp = getenv ("PATH");
++ if (temp)
++ {
++ char *startp, *endp, *nstore, *alloc_ptr = NULL;
++ size_t prefixlen = strlen (temp) + 1;
++ size_t len;
++ if (prefixlen < 2)
++ prefixlen = 2;
++
++ len = prefixlen + strlen (progname) + 1;
++#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
++ len += strlen (HOST_EXECUTABLE_SUFFIX);
++#endif
++ if (len < MAX_ALLOCA_SIZE)
++ nstore = (char *) alloca (len);
++ else
++ alloc_ptr = nstore = (char *) malloc (len);
++
++ startp = endp = temp;
++ while (1)
++ {
++ if (*endp == PATH_SEPARATOR || *endp == 0)
++ {
++ if (endp == startp)
++ {
++ nstore[0] = '.';
++ nstore[1] = DIR_SEPARATOR;
++ nstore[2] = '\0';
++ }
++ else
++ {
++ memcpy (nstore, startp, endp - startp);
++ if (! IS_DIR_SEPARATOR (endp[-1]))
++ {
++ nstore[endp - startp] = DIR_SEPARATOR;
++ nstore[endp - startp + 1] = 0;
++ }
++ else
++ nstore[endp - startp] = 0;
++ }
++ strcat (nstore, progname);
++ if (! access (nstore, X_OK)
++#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
++ || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
++#endif
++ )
++ {
++#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
++ struct stat st;
++ if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
++#endif
++ {
++ free (alloc_ptr);
++ return true;
++ }
++ }
++
++ if (*endp == 0)
++ break;
++ endp = startp = endp + 1;
++ }
++ else
++ endp++;
++ }
++ free (alloc_ptr);
++ }
++ return false;
++}
++
+ static struct option long_options[] = {
+ {"traditional-format", no_argument, 0, 0 },
+ {"save-temps", no_argument, 0, 0 },
++ {"verify", no_argument, 0, 0 },
+ {"no-verify", no_argument, 0, 0 },
+ {"help", no_argument, 0, 'h' },
+ {"version", no_argument, 0, 'V' },
+@@ -912,7 +1033,7 @@ main (int argc, char **argv)
+ FILE *in = stdin;
+ FILE *out = stdout;
+ bool verbose __attribute__((unused)) = false;
+- bool verify = true;
++ int verify = -1;
+ const char *smver = "sm_30";
+
+ int o;
+@@ -923,7 +1044,9 @@ main (int argc, char **argv)
+ {
+ case 0:
+ if (option_index == 2)
+- verify = false;
++ verify = 1;
++ else if (option_index == 3)
++ verify = 0;
+ break;
+ case 'v':
+ verbose = true;
+@@ -948,7 +1071,8 @@ Usage: nvptx-none-as [option...] [asmfile]\n\
+ Options:\n\
+ -o FILE Write output to FILE\n\
+ -v Be verbose\n\
++ --verify Do verify output is acceptable to ptxas\n\
+ --no-verify Do not verify output is acceptable to ptxas\n\
+ --help Print this help and exit\n\
+ --version Print version number and exit\n\
+ \n\
+@@ -983,11 +1108,17 @@ This program has absolutely no warranty.\n",
+ if (!in)
+ fatal_error ("cannot open input ptx file");
+
+- process (in, out);
+- if (outname)
++ if (outname == NULL)
++ verify = 0;
++ else if (verify == -1)
++ if (program_available ("ptxas"))
++ verify = 1;
++
++ process (in, out, verify, outname);
++ if (outname)
+ fclose (out);
+
+- if (verify && outname)
++ if (verify > 0)
+ {
+ struct obstack argv_obstack;
+ obstack_init (&argv_obstack);
+--- nvptx-tools/configure
++++ nvptx-tools/configure
+@@ -168,7 +168,8 @@ test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
++ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
++test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+ else
+@@ -552,11 +553,50 @@ PACKAGE_URL=
+
+ ac_unique_file="nvptx-tools"
+ ac_unique_file="nvptx-as.c"
++# Factoring default headers for most tests.
++ac_includes_default="\
++#include
++#ifdef HAVE_SYS_TYPES_H
++# include
++#endif
++#ifdef HAVE_SYS_STAT_H
++# include
++#endif
++#ifdef STDC_HEADERS
++# include
++# include
++#else
++# ifdef HAVE_STDLIB_H
++# include
++# endif
++#endif
++#ifdef HAVE_STRING_H
++# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
++# include
++# endif
++# include
++#endif
++#ifdef HAVE_STRINGS_H
++# include
++#endif
++#ifdef HAVE_INTTYPES_H
++# include
++#endif
++#ifdef HAVE_STDINT_H
++# include
++#endif
++#ifdef HAVE_UNISTD_H
++# include
++#endif"
++
+ enable_option_checking=no
+ ac_subst_vars='LTLIBOBJS
+ LIBOBJS
+ subdirs
+ NVPTX_RUN
++EGREP
++GREP
++CPP
+ CUDA_DRIVER_LDFLAGS
+ CUDA_DRIVER_CPPFLAGS
+ AR
+@@ -635,7 +675,8 @@ LIBS
+ CPPFLAGS
+ CXX
+ CXXFLAGS
+-CCC'
++CCC
++CPP'
+ ac_subdirs_all='libiberty'
+
+ # Initialize some variables set by options.
+@@ -1267,6 +1308,7 @@ Some influential environment variables:
+ you have headers in a nonstandard directory
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
++ CPP C preprocessor
+
+ Use these variables to override the choices made by `configure' or to help
+ it to find libraries and programs with nonstandard names/locations.
+@@ -1575,6 +1617,203 @@ $as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+ } # ac_fn_c_check_decl
++
++# ac_fn_c_try_cpp LINENO
++# ----------------------
++# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
++ac_fn_c_try_cpp ()
++{
++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++ if { { ac_try="$ac_cpp conftest.$ac_ext"
++case "(($ac_try" in
++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++ *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
++ ac_status=$?
++ if test -s conftest.err; then
++ grep -v '^ *+' conftest.err >conftest.er1
++ cat conftest.er1 >&5
++ mv -f conftest.er1 conftest.err
++ fi
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; } >/dev/null && {
++ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
++ test ! -s conftest.err
++ }; then :
++ ac_retval=0
++else
++ $as_echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ ac_retval=1
++fi
++ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
++ return $ac_retval
++
++} # ac_fn_c_try_cpp
++
++# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
++# -------------------------------------------------------
++# Tests whether HEADER exists, giving a warning if it cannot be compiled using
++# the include files in INCLUDES and setting the cache variable VAR
++# accordingly.
++ac_fn_c_check_header_mongrel ()
++{
++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++ if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
++ $as_echo_n "(cached) " >&6
++fi
++eval ac_res=\$$3
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++else
++ # Is the header compilable?
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
++$as_echo_n "checking $2 usability... " >&6; }
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++$4
++#include <$2>
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ ac_header_compiler=yes
++else
++ ac_header_compiler=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
++$as_echo "$ac_header_compiler" >&6; }
++
++# Is the header present?
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
++$as_echo_n "checking $2 presence... " >&6; }
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include <$2>
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++ ac_header_preproc=yes
++else
++ ac_header_preproc=no
++fi
++rm -f conftest.err conftest.$ac_ext
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
++$as_echo "$ac_header_preproc" >&6; }
++
++# So? What about this header?
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
++ yes:no: )
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
++$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
++ ;;
++ no:yes:* )
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
++$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
++$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
++$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
++$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
++ ;;
++esac
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
++ $as_echo_n "(cached) " >&6
++else
++ eval "$3=\$ac_header_compiler"
++fi
++eval ac_res=\$$3
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++fi
++ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
++
++} # ac_fn_c_check_header_mongrel
++
++# ac_fn_c_try_run LINENO
++# ----------------------
++# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
++# that executables *can* be run.
++ac_fn_c_try_run ()
++{
++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++ if { { ac_try="$ac_link"
++case "(($ac_try" in
++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++ *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++ (eval "$ac_link") 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
++ { { case "(($ac_try" in
++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++ *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++ (eval "$ac_try") 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; }; then :
++ ac_retval=0
++else
++ $as_echo "$as_me: program exited with status $ac_status" >&5
++ $as_echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ ac_retval=$ac_status
++fi
++ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
++ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
++ return $ac_retval
++
++} # ac_fn_c_try_run
++
++# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
++# -------------------------------------------------------
++# Tests whether HEADER exists and can be compiled using the include files in
++# INCLUDES, setting the cache variable VAR accordingly.
++ac_fn_c_check_header_compile ()
++{
++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
++ $as_echo_n "(cached) " >&6
++else
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++$4
++#include <$2>
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ eval "$3=yes"
++else
++ eval "$3=no"
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++eval ac_res=\$$3
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
++
++} # ac_fn_c_check_header_compile
+ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+@@ -3284,6 +3523,418 @@ cat >>confdefs.h <<_ACEOF
+ #define HAVE_DECL_CUGETERRORSTRING $ac_have_decl
+ _ACEOF
+
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
++$as_echo_n "checking how to run the C preprocessor... " >&6; }
++# On Suns, sometimes $CPP names a directory.
++if test -n "$CPP" && test -d "$CPP"; then
++ CPP=
++fi
++if test -z "$CPP"; then
++ if test "${ac_cv_prog_CPP+set}" = set; then :
++ $as_echo_n "(cached) " >&6
++else
++ # Double quotes because CPP needs to be expanded
++ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
++ do
++ ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
++do
++ # Use a header file that comes with gcc, so configuring glibc
++ # with a fresh cross-compiler works.
++ # Prefer to if __STDC__ is defined, since
++ # exists even on freestanding compilers.
++ # On the NeXT, cc -E runs the code through the compiler's parser,
++ # not just through cpp. "Syntax error" is here to catch this case.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#ifdef __STDC__
++# include
++#else
++# include
++#endif
++ Syntax error
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++
++else
++ # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.$ac_ext
++
++ # OK, works on sane cases. Now check whether nonexistent headers
++ # can be detected and how.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++ # Broken: success on invalid input.
++continue
++else
++ # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then :
++ break
++fi
++
++ done
++ ac_cv_prog_CPP=$CPP
++
++fi
++ CPP=$ac_cv_prog_CPP
++else
++ ac_cv_prog_CPP=$CPP
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
++$as_echo "$CPP" >&6; }
++ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
++do
++ # Use a header file that comes with gcc, so configuring glibc
++ # with a fresh cross-compiler works.
++ # Prefer to if __STDC__ is defined, since
++ # exists even on freestanding compilers.
++ # On the NeXT, cc -E runs the code through the compiler's parser,
++ # not just through cpp. "Syntax error" is here to catch this case.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#ifdef __STDC__
++# include
++#else
++# include
++#endif
++ Syntax error
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++
++else
++ # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.$ac_ext
++
++ # OK, works on sane cases. Now check whether nonexistent headers
++ # can be detected and how.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++ # Broken: success on invalid input.
++continue
++else
++ # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then :
++
++else
++ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error "C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details." "$LINENO" 5; }
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
++$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
++if test "${ac_cv_path_GREP+set}" = set; then :
++ $as_echo_n "(cached) " >&6
++else
++ if test -z "$GREP"; then
++ ac_path_GREP_found=false
++ # Loop through the user's path and test for each of PROGNAME-LIST
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for ac_prog in grep ggrep; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
++ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
++# Check for GNU ac_path_GREP and select it if it is found.
++ # Check for GNU $ac_path_GREP
++case `"$ac_path_GREP" --version 2>&1` in
++*GNU*)
++ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
++*)
++ ac_count=0
++ $as_echo_n 0123456789 >"conftest.in"
++ while :
++ do
++ cat "conftest.in" "conftest.in" >"conftest.tmp"
++ mv "conftest.tmp" "conftest.in"
++ cp "conftest.in" "conftest.nl"
++ $as_echo 'GREP' >> "conftest.nl"
++ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++ as_fn_arith $ac_count + 1 && ac_count=$as_val
++ if test $ac_count -gt ${ac_path_GREP_max-0}; then
++ # Best one so far, save it but keep looking for a better one
++ ac_cv_path_GREP="$ac_path_GREP"
++ ac_path_GREP_max=$ac_count
++ fi
++ # 10*(2^10) chars as input seems more than enough
++ test $ac_count -gt 10 && break
++ done
++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++ $ac_path_GREP_found && break 3
++ done
++ done
++ done
++IFS=$as_save_IFS
++ if test -z "$ac_cv_path_GREP"; then
++ as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++ fi
++else
++ ac_cv_path_GREP=$GREP
++fi
++
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
++$as_echo "$ac_cv_path_GREP" >&6; }
++ GREP="$ac_cv_path_GREP"
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
++$as_echo_n "checking for egrep... " >&6; }
++if test "${ac_cv_path_EGREP+set}" = set; then :
++ $as_echo_n "(cached) " >&6
++else
++ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
++ then ac_cv_path_EGREP="$GREP -E"
++ else
++ if test -z "$EGREP"; then
++ ac_path_EGREP_found=false
++ # Loop through the user's path and test for each of PROGNAME-LIST
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for ac_prog in egrep; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
++ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
++# Check for GNU ac_path_EGREP and select it if it is found.
++ # Check for GNU $ac_path_EGREP
++case `"$ac_path_EGREP" --version 2>&1` in
++*GNU*)
++ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
++*)
++ ac_count=0
++ $as_echo_n 0123456789 >"conftest.in"
++ while :
++ do
++ cat "conftest.in" "conftest.in" >"conftest.tmp"
++ mv "conftest.tmp" "conftest.in"
++ cp "conftest.in" "conftest.nl"
++ $as_echo 'EGREP' >> "conftest.nl"
++ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++ as_fn_arith $ac_count + 1 && ac_count=$as_val
++ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
++ # Best one so far, save it but keep looking for a better one
++ ac_cv_path_EGREP="$ac_path_EGREP"
++ ac_path_EGREP_max=$ac_count
++ fi
++ # 10*(2^10) chars as input seems more than enough
++ test $ac_count -gt 10 && break
++ done
++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++ $ac_path_EGREP_found && break 3
++ done
++ done
++ done
++IFS=$as_save_IFS
++ if test -z "$ac_cv_path_EGREP"; then
++ as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++ fi
++else
++ ac_cv_path_EGREP=$EGREP
++fi
++
++ fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
++$as_echo "$ac_cv_path_EGREP" >&6; }
++ EGREP="$ac_cv_path_EGREP"
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
++$as_echo_n "checking for ANSI C header files... " >&6; }
++if test "${ac_cv_header_stdc+set}" = set; then :
++ $as_echo_n "(cached) " >&6
++else
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++#include
++#include
++#include
++
++int
++main ()
++{
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ ac_cv_header_stdc=yes
++else
++ ac_cv_header_stdc=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
++if test $ac_cv_header_stdc = yes; then
++ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "memchr" >/dev/null 2>&1; then :
++
++else
++ ac_cv_header_stdc=no
++fi
++rm -f conftest*
++
++fi
++
++if test $ac_cv_header_stdc = yes; then
++ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "free" >/dev/null 2>&1; then :
++
++else
++ ac_cv_header_stdc=no
++fi
++rm -f conftest*
++
++fi
++
++if test $ac_cv_header_stdc = yes; then
++ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
++ if test "$cross_compiling" = yes; then :
++ :
++else
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include
++#include
++#if ((' ' & 0x0FF) == 0x020)
++# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
++# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
++#else
++# define ISLOWER(c) \
++ (('a' <= (c) && (c) <= 'i') \
++ || ('j' <= (c) && (c) <= 'r') \
++ || ('s' <= (c) && (c) <= 'z'))
++# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
++#endif
++
++#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
++int
++main ()
++{
++ int i;
++ for (i = 0; i < 256; i++)
++ if (XOR (islower (i), ISLOWER (i))
++ || toupper (i) != TOUPPER (i))
++ return 2;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_run "$LINENO"; then :
++
++else
++ ac_cv_header_stdc=no
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++ conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++
++fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
++$as_echo "$ac_cv_header_stdc" >&6; }
++if test $ac_cv_header_stdc = yes; then
++
++$as_echo "#define STDC_HEADERS 1" >>confdefs.h
++
++fi
++
++# On IRIX 5.3, sys/types and inttypes.h are conflicting.
++for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
++ inttypes.h stdint.h unistd.h
++do :
++ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
++ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
++"
++eval as_val=\$$as_ac_Header
++ if test "x$as_val" = x""yes; then :
++ cat >>confdefs.h <<_ACEOF
++#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
++
++for ac_header in unistd.h sys/stat.h
++do :
++ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
++ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
++eval as_val=\$$as_ac_Header
++ if test "x$as_val" = x""yes; then :
++ cat >>confdefs.h <<_ACEOF
++#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++
++done
++
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra programs to build requiring -lcuda" >&5
+ $as_echo_n "checking for extra programs to build requiring -lcuda... " >&6; }
diff --git a/SPECS/gcc.spec b/SPECS/gcc.spec
new file mode 100644
index 0000000..ae502e7
--- /dev/null
+++ b/SPECS/gcc.spec
@@ -0,0 +1,3249 @@
+%global DATE 20190507
+%global SVNREV 270976
+%global gcc_version 8.3.1
+%global gcc_major 8
+# Note, gcc_release must be integer, if you want to add suffixes to
+# %%{release}, append them after %%{gcc_release} on Release: line.
+%global gcc_release 4
+%global nvptx_tools_gitrev c28050f60193b3b95a18866a96f03334e874e78f
+%global nvptx_newlib_gitrev aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24
+%global _unpackaged_files_terminate_build 0
+%global _performance_build 1
+%if 0%{?fedora} > 27 || 0%{?rhel} > 7
+# Until annobin is fixed (#1519165).
+%undefine _annotated_build
+%endif
+%global multilib_64_archs sparc64 ppc64 ppc64p7 x86_64
+%if 0%{?rhel} > 7
+%global build_ada 0
+%global build_objc 0
+%global build_go 0
+%global build_libgccjit 0
+%else
+%ifarch %{ix86} x86_64 ia64 ppc %{power64} alpha s390x %{arm} aarch64
+%global build_ada 1
+%else
+%global build_ada 0
+%endif
+%global build_objc 1
+%global build_libgccjit 1
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips}
+%global build_go 1
+%else
+%global build_go 0
+%endif
+%endif
+%ifarch %{ix86} x86_64 ia64 ppc64le
+%global build_libquadmath 1
+%else
+%global build_libquadmath 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64
+%global build_libasan 1
+%else
+%global build_libasan 0
+%endif
+%ifarch x86_64 ppc64 ppc64le aarch64
+%global build_libtsan 1
+%else
+%global build_libtsan 0
+%endif
+%ifarch x86_64 ppc64 ppc64le aarch64
+%global build_liblsan 1
+%else
+%global build_liblsan 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64
+%global build_libubsan 1
+%else
+%global build_libubsan 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips}
+%global build_libatomic 1
+%else
+%global build_libatomic 0
+%endif
+%ifarch %{ix86} x86_64 %{arm} alpha ppc ppc64 ppc64le ppc64p7 s390 s390x aarch64
+%global build_libitm 1
+%else
+%global build_libitm 0
+%endif
+%if 0%{?rhel} > 7
+%global build_libmpx 0
+%else
+%ifarch %{ix86} x86_64
+%global build_libmpx 1
+%else
+%global build_libmpx 0
+%endif
+%endif
+%global build_isl 1
+%global build_libstdcxx_docs 1
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips}
+%global attr_ifunc 1
+%else
+%global attr_ifunc 0
+%endif
+%ifarch x86_64 ppc64le
+%global build_offload_nvptx 1
+%else
+%global build_offload_nvptx 0
+%endif
+%ifarch s390x
+%global multilib_32_arch s390
+%endif
+%ifarch sparc64
+%global multilib_32_arch sparcv9
+%endif
+%ifarch ppc64 ppc64p7
+%global multilib_32_arch ppc
+%endif
+%ifarch x86_64
+%global multilib_32_arch i686
+%endif
+Summary: Various compilers (C, C++, Objective-C, ...)
+Name: gcc
+Version: %{gcc_version}
+Release: %{gcc_release}.4%{?dist}
+# libgcc, libgfortran, libgomp, libstdc++ and crtstuff have
+# GCC Runtime Exception.
+License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD
+Group: Development/Languages
+# The source for this package was pulled from upstream's vcs. Use the
+# following commands to generate the tarball:
+# svn export svn://gcc.gnu.org/svn/gcc/branches/redhat/gcc-8-branch@%%{SVNREV} gcc-%%{version}-%%{DATE}
+# tar cf - gcc-%%{version}-%%{DATE} | xz -9e > gcc-%%{version}-%%{DATE}.tar.xz
+Source0: gcc-%{version}-%{DATE}.tar.xz
+# The source for nvptx-tools package was pulled from upstream's vcs. Use the
+# following commands to generate the tarball:
+# git clone https://github.com/MentorEmbedded/nvptx-tools.git
+# cd nvptx-tools
+# git archive origin/master --prefix=nvptx-tools-%%{nvptx_tools_gitrev}/ | xz -9e > ../nvptx-tools-%%{nvptx_tools_gitrev}.tar.xz
+# cd ..; rm -rf nvptx-tools
+Source1: nvptx-tools-%{nvptx_tools_gitrev}.tar.xz
+# The source for nvptx-newlib package was pulled from upstream's vcs. Use the
+# following commands to generate the tarball:
+# git clone https://github.com/MentorEmbedded/nvptx-newlib.git
+# cd nvptx-newlib
+# git archive origin/master --prefix=nvptx-newlib-%%{nvptx_newlib_gitrev}/ | xz -9 > ../nvptx-newlib-%%{nvptx_newlib_gitrev}.tar.xz
+# cd ..; rm -rf nvptx-newlib
+Source2: nvptx-newlib-%{nvptx_newlib_gitrev}.tar.xz
+%global isl_version 0.16.1
+URL: http://gcc.gnu.org
+# Need binutils with -pie support >= 2.14.90.0.4-4
+# Need binutils which can omit dot symbols and overlap .opd on ppc64 >= 2.15.91.0.2-4
+# Need binutils which handle -msecure-plt on ppc >= 2.16.91.0.2-2
+# Need binutils which support .weakref >= 2.16.91.0.3-1
+# Need binutils which support --hash-style=gnu >= 2.17.50.0.2-7
+# Need binutils which support mffgpr and mftgpr >= 2.17.50.0.2-8
+# Need binutils which support --build-id >= 2.17.50.0.17-3
+# Need binutils which support %%gnu_unique_object >= 2.19.51.0.14
+# Need binutils which support .cfi_sections >= 2.19.51.0.14-33
+# Need binutils which support --no-add-needed >= 2.20.51.0.2-12
+# Need binutils which support -plugin
+# Need binutils which support .loc view >= 2.30
+# Need binutils which support --generate-missing-build-notes=yes >= 2.31
+%if 0%{?fedora} >= 29
+BuildRequires: binutils >= 2.31
+%else
+%if 0%{?rhel} > 7
+BuildRequires: binutils >= 2.30-17
+%else
+BuildRequires: binutils >= 2.24
+%endif
+%endif
+# While gcc doesn't include statically linked binaries, during testing
+# -static is used several times.
+BuildRequires: glibc-static
+BuildRequires: zlib-devel, gettext, dejagnu, bison, flex, sharutils
+BuildRequires: texinfo, texinfo-tex, /usr/bin/pod2man
+BuildRequires: systemtap-sdt-devel >= 1.3
+BuildRequires: gmp-devel >= 4.1.2-8, mpfr-devel >= 2.2.1, libmpc-devel >= 0.8.1
+BuildRequires: python3-devel
+BuildRequires: gcc, gcc-c++
+%if %{build_go}
+BuildRequires: hostname, procps
+%endif
+# For VTA guality testing
+BuildRequires: gdb
+# Make sure pthread.h doesn't contain __thread tokens
+# Make sure glibc supports stack protector
+# Make sure glibc supports DT_GNU_HASH
+BuildRequires: glibc-devel >= 2.4.90-13
+BuildRequires: elfutils-devel >= 0.147
+BuildRequires: elfutils-libelf-devel >= 0.147
+%ifarch ppc ppc64 ppc64le ppc64p7 s390 s390x sparc sparcv9 alpha
+# Make sure glibc supports TFmode long double
+BuildRequires: glibc >= 2.3.90-35
+%endif
+%ifarch %{multilib_64_archs} sparcv9 ppc
+# Ensure glibc{,-devel} is installed for both multilib arches
+BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so
+%endif
+%if %{build_ada}
+# Ada requires Ada to build
+BuildRequires: gcc-gnat >= 3.1, libgnat >= 3.1
+%endif
+%ifarch ia64
+BuildRequires: libunwind >= 0.98
+%endif
+%if %{build_isl}
+BuildRequires: isl = %{isl_version}
+BuildRequires: isl-devel = %{isl_version}
+%if 0%{?__isa_bits} == 64
+Requires: libisl.so.15()(64bit)
+%else
+Requires: libisl.so.15
+%endif
+%endif
+%if %{build_libstdcxx_docs}
+BuildRequires: doxygen >= 1.7.1
+BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook5-style-xsl
+%endif
+Requires: cpp = %{version}-%{release}
+# Need .eh_frame ld optimizations
+# Need proper visibility support
+# Need -pie support
+# Need --as-needed/--no-as-needed support
+# On ppc64, need omit dot symbols support and --non-overlapping-opd
+# Need binutils that owns /usr/bin/c++filt
+# Need binutils that support .weakref
+# Need binutils that supports --hash-style=gnu
+# Need binutils that support mffgpr/mftgpr
+# Need binutils that support --build-id
+# Need binutils that support %%gnu_unique_object
+# Need binutils that support .cfi_sections
+# Need binutils that support --no-add-needed
+# Need binutils that support -plugin
+# Need binutils that support .loc view >= 2.30
+# Need binutils which support --generate-missing-build-notes=yes >= 2.31
+%if 0%{?fedora} >= 29
+Requires: binutils >= 2.31
+%else
+%if 0%{?rhel} > 7
+Requires: binutils >= 2.30-17
+%else
+Requires: binutils >= 2.24
+%endif
+%endif
+# Make sure gdb will understand DW_FORM_strp
+Conflicts: gdb < 5.1-2
+Requires: glibc-devel >= 2.2.90-12
+%ifarch ppc ppc64 ppc64le ppc64p7 s390 s390x sparc sparcv9 alpha
+# Make sure glibc supports TFmode long double
+Requires: glibc >= 2.3.90-35
+%endif
+%if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+%ifarch %{arm}
+Requires: glibc >= 2.16
+%endif
+%endif
+Requires: libgcc >= %{version}-%{release}
+Requires: libgomp = %{version}-%{release}
+%if !%{build_ada}
+Obsoletes: gcc-gnat < %{version}-%{release}
+%endif
+Obsoletes: gcc-java < %{version}-%{release}
+%ifarch %{ix86} x86_64
+Obsoletes: libcilkrts
+Obsoletes: libcilkrts-static
+%endif
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+AutoReq: true
+Provides: bundled(libiberty)
+Provides: gcc(major) = %{gcc_major}
+
+Patch0: gcc8-hack.patch
+Patch2: gcc8-i386-libgomp.patch
+Patch3: gcc8-sparc-config-detection.patch
+Patch4: gcc8-libgomp-omp_h-multilib.patch
+Patch5: gcc8-libtool-no-rpath.patch
+Patch6: gcc8-isl-dl.patch
+Patch7: gcc8-libstdc++-docs.patch
+Patch8: gcc8-no-add-needed.patch
+Patch9: gcc8-foffload-default.patch
+Patch10: gcc8-Wno-format-security.patch
+Patch11: gcc8-rh1512529-aarch64.patch
+Patch12: gcc8-mcet.patch
+Patch13: gcc8-rh1574936.patch
+Patch14: gcc8-libgcc-hardened.patch
+Patch15: gcc8-rh1670535.patch
+Patch16: gcc8-pr85400.patch
+Patch17: gcc8-libgomp-20190503.patch
+Patch18: gcc8-pr86747.patch
+Patch19: gcc8-libgomp-testsuite.patch
+Patch20: gcc8-rh1711346.patch
+
+Patch30: gcc8-rh1668903-1.patch
+Patch31: gcc8-rh1668903-2.patch
+Patch32: gcc8-rh1668903-3.patch
+
+Patch1000: nvptx-tools-no-ptxas.patch
+Patch1001: nvptx-tools-build.patch
+Patch1002: nvptx-tools-glibc.patch
+
+
+# On ARM EABI systems, we do want -gnueabi to be part of the
+# target triple.
+%ifnarch %{arm}
+%global _gnu %{nil}
+%else
+%global _gnu -gnueabi
+%endif
+%ifarch sparcv9
+%global gcc_target_platform sparc64-%{_vendor}-%{_target_os}
+%endif
+%ifarch ppc ppc64p7
+%global gcc_target_platform ppc64-%{_vendor}-%{_target_os}
+%endif
+%ifnarch sparcv9 ppc ppc64p7
+%global gcc_target_platform %{_target_platform}
+%endif
+
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+%global __os_install_post \
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.13.* \
+chmod 644 %{buildroot}%{_prefix}/bin/go.gcc \
+chmod 644 %{buildroot}%{_prefix}/bin/gofmt.gcc \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet \
+%__os_install_post \
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgo.so.13.* \
+chmod 755 %{buildroot}%{_prefix}/bin/go.gcc \
+chmod 755 %{buildroot}%{_prefix}/bin/gofmt.gcc \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet \
+%{nil}
+%endif
+
+%description
+The gcc package contains the GNU Compiler Collection version 8.
+You'll need this package in order to compile C code.
+
+%package -n libgcc
+Summary: GCC version 8 shared support library
+Group: System Environment/Libraries
+Autoreq: false
+%if !%{build_ada}
+Obsoletes: libgnat < %{version}-%{release}
+%endif
+Obsoletes: libmudflap
+Obsoletes: libmudflap-devel
+Obsoletes: libmudflap-static
+Obsoletes: libgcj < %{version}-%{release}
+Obsoletes: libgcj-devel < %{version}-%{release}
+Obsoletes: libgcj-src < %{version}-%{release}
+
+%description -n libgcc
+This package contains GCC shared support library which is needed
+e.g. for exception handling support.
+
+%package c++
+Summary: C++ support for GCC
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libstdc++ = %{version}-%{release}
+Requires: libstdc++-devel = %{version}-%{release}
+Autoreq: true
+
+%description c++
+This package adds C++ support to the GNU Compiler Collection.
+It includes support for most of the current C++ specification,
+including templates and exception handling.
+
+%package -n libstdc++
+Summary: GNU Standard C++ Library
+Group: System Environment/Libraries
+Autoreq: true
+Requires: glibc >= 2.10.90-7
+
+%description -n libstdc++
+The libstdc++ package contains a rewritten standard compliant GCC Standard
+C++ Library.
+
+%package -n libstdc++-devel
+Summary: Header files and libraries for C++ development
+Group: Development/Libraries
+Requires: libstdc++%{?_isa} = %{version}-%{release}
+Autoreq: true
+
+%description -n libstdc++-devel
+This is the GNU implementation of the standard C++ libraries. This
+package includes the header files and libraries needed for C++
+development. This includes rewritten implementation of STL.
+
+%package -n libstdc++-static
+Summary: Static libraries for the GNU standard C++ library
+Group: Development/Libraries
+Requires: libstdc++-devel = %{version}-%{release}
+Autoreq: true
+
+%description -n libstdc++-static
+Static libraries for the GNU standard C++ library.
+
+%package -n libstdc++-docs
+Summary: Documentation for the GNU standard C++ library
+Group: Development/Libraries
+Autoreq: true
+
+%description -n libstdc++-docs
+Manual, doxygen generated API information and Frequently Asked Questions
+for the GNU standard C++ library.
+
+%package objc
+Summary: Objective-C support for GCC
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libobjc = %{version}-%{release}
+Autoreq: true
+
+%description objc
+gcc-objc provides Objective-C support for the GCC.
+Mainly used on systems running NeXTSTEP, Objective-C is an
+object-oriented derivative of the C language.
+
+%package objc++
+Summary: Objective-C++ support for GCC
+Group: Development/Languages
+Requires: gcc-c++ = %{version}-%{release}, gcc-objc = %{version}-%{release}
+Autoreq: true
+
+%description objc++
+gcc-objc++ package provides Objective-C++ support for the GCC.
+
+%package -n libobjc
+Summary: Objective-C runtime
+Group: System Environment/Libraries
+Autoreq: true
+
+%description -n libobjc
+This package contains Objective-C shared library which is needed to run
+Objective-C dynamically linked programs.
+
+%package gfortran
+Summary: Fortran support
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libgfortran = %{version}-%{release}
+%if %{build_libquadmath}
+Requires: libquadmath = %{version}-%{release}
+Requires: libquadmath-devel = %{version}-%{release}
+%endif
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+Autoreq: true
+
+%description gfortran
+The gcc-gfortran package provides support for compiling Fortran
+programs with the GNU Compiler Collection.
+
+%package -n libgfortran
+Summary: Fortran runtime
+Group: System Environment/Libraries
+Autoreq: true
+%if %{build_libquadmath}
+Requires: libquadmath = %{version}-%{release}
+%endif
+
+%description -n libgfortran
+This package contains Fortran shared library which is needed to run
+Fortran dynamically linked programs.
+
+%package -n libgfortran-static
+Summary: Static Fortran libraries
+Group: Development/Libraries
+Requires: libgfortran = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+%if %{build_libquadmath}
+Requires: libquadmath-static = %{version}-%{release}
+%endif
+
+%description -n libgfortran-static
+This package contains static Fortran libraries.
+
+%package -n libgomp
+Summary: GCC OpenMP v4.5 shared support library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libgomp
+This package contains GCC shared support library which is needed
+for OpenMP v4.5 support.
+
+%package -n libgomp-offload-nvptx
+Summary: GCC OpenMP v4.5 plugin for offloading to NVPTX
+Group: System Environment/Libraries
+Requires: libgomp = %{version}-%{release}
+
+%description -n libgomp-offload-nvptx
+This package contains libgomp plugin for offloading to NVidia
+PTX. The plugin needs libcuda.so.1 shared library that has to be
+installed separately.
+
+%package gdb-plugin
+Summary: GCC plugin for GDB
+Group: Development/Debuggers
+Requires: gcc = %{version}-%{release}
+
+%description gdb-plugin
+This package contains GCC plugin for GDB C expression evaluation.
+
+%package -n libgccjit
+Summary: Library for embedding GCC inside programs and libraries
+Group: System Environment/Libraries
+Requires: gcc = %{version}-%{release}
+
+%description -n libgccjit
+This package contains shared library with GCC JIT front-end.
+
+%package -n libgccjit-devel
+Summary: Support for embedding GCC inside programs and libraries
+Group: Development/Libraries
+%if 0%{?fedora} > 27 || 0%{?rhel} > 7
+BuildRequires: python3-sphinx
+%else
+BuildRequires: python-sphinx
+%endif
+Requires: libgccjit = %{version}-%{release}
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libgccjit-devel
+This package contains header files and documentation for GCC JIT front-end.
+
+%package -n libquadmath
+Summary: GCC __float128 shared support library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libquadmath
+This package contains GCC shared support library which is needed
+for __float128 math support and for Fortran REAL*16 support.
+
+%package -n libquadmath-devel
+Summary: GCC __float128 support
+Group: Development/Libraries
+Requires: libquadmath = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libquadmath-devel
+This package contains headers for building Fortran programs using
+REAL*16 and programs using __float128 math.
+
+%package -n libquadmath-static
+Summary: Static libraries for __float128 support
+Group: Development/Libraries
+Requires: libquadmath-devel = %{version}-%{release}
+
+%description -n libquadmath-static
+This package contains static libraries for building Fortran programs
+using REAL*16 and programs using __float128 math.
+
+%package -n libitm
+Summary: The GNU Transactional Memory library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libitm
+This package contains the GNU Transactional Memory library
+which is a GCC transactional memory support runtime library.
+
+%package -n libitm-devel
+Summary: The GNU Transactional Memory support
+Group: Development/Libraries
+Requires: libitm = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libitm-devel
+This package contains headers and support files for the
+GNU Transactional Memory library.
+
+%package -n libitm-static
+Summary: The GNU Transactional Memory static library
+Group: Development/Libraries
+Requires: libitm-devel = %{version}-%{release}
+
+%description -n libitm-static
+This package contains GNU Transactional Memory static libraries.
+
+%package -n libatomic
+Summary: The GNU Atomic library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libatomic
+This package contains the GNU Atomic library
+which is a GCC support runtime library for atomic operations not supported
+by hardware.
+
+%package -n libatomic-static
+Summary: The GNU Atomic static library
+Group: Development/Libraries
+Requires: libatomic = %{version}-%{release}
+
+%description -n libatomic-static
+This package contains GNU Atomic static libraries.
+
+%package -n libasan
+Summary: The Address Sanitizer runtime library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libasan
+This package contains the Address Sanitizer library
+which is used for -fsanitize=address instrumented programs.
+
+%package -n libasan-static
+Summary: The Address Sanitizer static library
+Group: Development/Libraries
+Requires: libasan = %{version}-%{release}
+
+%description -n libasan-static
+This package contains Address Sanitizer static runtime library.
+
+%package -n libtsan
+Summary: The Thread Sanitizer runtime library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libtsan
+This package contains the Thread Sanitizer library
+which is used for -fsanitize=thread instrumented programs.
+
+%package -n libtsan-static
+Summary: The Thread Sanitizer static library
+Group: Development/Libraries
+Requires: libtsan = %{version}-%{release}
+
+%description -n libtsan-static
+This package contains Thread Sanitizer static runtime library.
+
+%package -n libubsan
+Summary: The Undefined Behavior Sanitizer runtime library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libubsan
+This package contains the Undefined Behavior Sanitizer library
+which is used for -fsanitize=undefined instrumented programs.
+
+%package -n libubsan-static
+Summary: The Undefined Behavior Sanitizer static library
+Group: Development/Libraries
+Requires: libubsan = %{version}-%{release}
+
+%description -n libubsan-static
+This package contains Undefined Behavior Sanitizer static runtime library.
+
+%package -n liblsan
+Summary: The Leak Sanitizer runtime library
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n liblsan
+This package contains the Leak Sanitizer library
+which is used for -fsanitize=leak instrumented programs.
+
+%package -n liblsan-static
+Summary: The Leak Sanitizer static library
+Group: Development/Libraries
+Requires: liblsan = %{version}-%{release}
+
+%description -n liblsan-static
+This package contains Leak Sanitizer static runtime library.
+
+%package -n libmpx
+Summary: The Memory Protection Extensions runtime libraries
+Group: System Environment/Libraries
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description -n libmpx
+This package contains the Memory Protection Extensions runtime libraries
+which is used for -fcheck-pointer-bounds -mmpx instrumented programs.
+
+%package -n libmpx-static
+Summary: The Memory Protection Extensions static libraries
+Group: Development/Libraries
+Requires: libmpx = %{version}-%{release}
+
+%description -n libmpx-static
+This package contains the Memory Protection Extensions static runtime libraries.
+
+%package -n cpp
+Summary: The C Preprocessor
+Group: Development/Languages
+Requires: filesystem >= 3
+Provides: /lib/cpp
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+Autoreq: true
+
+%description -n cpp
+Cpp is the GNU C-Compatible Compiler Preprocessor.
+Cpp is a macro processor which is used automatically
+by the C compiler to transform your program before actual
+compilation. It is called a macro processor because it allows
+you to define macros, abbreviations for longer
+constructs.
+
+The C preprocessor provides four separate functionalities: the
+inclusion of header files (files of declarations that can be
+substituted into your program); macro expansion (you can define macros,
+and the C preprocessor will replace the macros with their definitions
+throughout the program); conditional compilation (using special
+preprocessing directives, you can include or exclude parts of the
+program according to various conditions); and line control (if you use
+a program to combine or rearrange source files into an intermediate
+file which is then compiled, you can use line control to inform the
+compiler about where each source line originated).
+
+You should install this package if you are a C programmer and you use
+macros.
+
+%package gnat
+Summary: Ada 83, 95, 2005 and 2012 support for GCC
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libgnat = %{version}-%{release}, libgnat-devel = %{version}-%{release}
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+Autoreq: true
+
+%description gnat
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+development tools, the documents and Ada compiler.
+
+%package -n libgnat
+Summary: GNU Ada 83, 95, 2005 and 2012 runtime shared libraries
+Group: System Environment/Libraries
+Autoreq: true
+
+%description -n libgnat
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+shared libraries, which are required to run programs compiled with the GNAT.
+
+%package -n libgnat-devel
+Summary: GNU Ada 83, 95, 2005 and 2012 libraries
+Group: Development/Languages
+Autoreq: true
+
+%description -n libgnat-devel
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+libraries, which are required to compile with the GNAT.
+
+%package -n libgnat-static
+Summary: GNU Ada 83, 95, 2005 and 2012 static libraries
+Group: Development/Languages
+Requires: libgnat-devel = %{version}-%{release}
+Autoreq: true
+
+%description -n libgnat-static
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+static libraries.
+
+%package go
+Summary: Go support
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libgo = %{version}-%{release}
+Requires: libgo-devel = %{version}-%{release}
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+Requires(post): %{_sbindir}/update-alternatives
+Requires(postun): %{_sbindir}/update-alternatives
+Autoreq: true
+
+%description go
+The gcc-go package provides support for compiling Go programs
+with the GNU Compiler Collection.
+
+%package -n libgo
+Summary: Go runtime
+Group: System Environment/Libraries
+Autoreq: true
+
+%description -n libgo
+This package contains Go shared library which is needed to run
+Go dynamically linked programs.
+
+%package -n libgo-devel
+Summary: Go development libraries
+Group: Development/Languages
+Requires: libgo = %{version}-%{release}
+Autoreq: true
+
+%description -n libgo-devel
+This package includes libraries and support files for compiling
+Go programs.
+
+%package -n libgo-static
+Summary: Static Go libraries
+Group: Development/Libraries
+Requires: libgo = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libgo-static
+This package contains static Go libraries.
+
+%package plugin-devel
+Summary: Support for compiling GCC plugins
+Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: gmp-devel >= 4.1.2-8, mpfr-devel >= 2.2.1, libmpc-devel >= 0.8.1
+
+%description plugin-devel
+This package contains header files and other support files
+for compiling GCC plugins. The GCC plugin ABI is currently
+not stable, so plugins must be rebuilt any time GCC is updated.
+
+%package offload-nvptx
+Summary: Offloading compiler to NVPTX
+Group: Group: Development/Languages
+Requires: gcc = %{version}-%{release}
+Requires: libgomp-offload-nvptx = %{version}-%{release}
+
+%description offload-nvptx
+The gcc-offload-nvptx package provides offloading support for
+NVidia PTX. OpenMP and OpenACC programs linked with -fopenmp will
+by default add PTX code into the binaries, which can be offloaded
+to NVidia PTX capable devices if available.
+
+%prep
+%setup -q -n gcc-%{version}-%{DATE} -a 1 -a 2
+%patch0 -p0 -b .hack~
+%patch2 -p0 -b .i386-libgomp~
+%patch3 -p0 -b .sparc-config-detection~
+%patch4 -p0 -b .libgomp-omp_h-multilib~
+%patch5 -p0 -b .libtool-no-rpath~
+%if %{build_isl}
+%patch6 -p0 -b .isl-dl~
+%endif
+%if %{build_libstdcxx_docs}
+%patch7 -p0 -b .libstdc++-docs~
+%endif
+%patch8 -p0 -b .no-add-needed~
+%patch9 -p0 -b .foffload-default~
+%patch10 -p0 -b .Wno-format-security~
+%patch11 -p0 -b .rh1512529-aarch64~
+%if 0%{?fedora} == 28
+%patch12 -p0 -b .mcet~
+%endif
+%if 0%{?fedora} >= 29 || 0%{?rhel} > 7
+%patch13 -p0 -b .rh1574936~
+%patch14 -p0 -b .libgcc-hardened~
+%endif
+%patch15 -p0 -b .rh1670535~
+%patch16 -p0 -b .pr85400~
+%patch17 -p0 -b .libgomp-20190503~
+%patch18 -p0 -b .pr86747~
+%patch19 -p0 -b .libgomp-testsuite~
+%patch20 -p0 -b .rh1711346~
+
+%patch30 -p0 -b .rh1668903-1~
+%patch31 -p0 -b .rh1668903-2~
+%patch32 -p0 -b .rh1668903-3~
+
+cd nvptx-tools-%{nvptx_tools_gitrev}
+%patch1000 -p1 -b .nvptx-tools-no-ptxas~
+%patch1001 -p1 -b .nvptx-tools-build~
+%patch1002 -p1 -b .nvptx-tools-glibc~
+cd ..
+
+echo 'Red Hat %{version}-%{gcc_release}' > gcc/DEV-PHASE
+
+cp -a libstdc++-v3/config/cpu/i{4,3}86/atomicity.h
+
+echo 'TM_H += $(srcdir)/config/rs6000/rs6000-modes.h' >> gcc/config/rs6000/t-rs6000
+
+./contrib/gcc_update --touch
+
+LC_ALL=C sed -i -e 's/\xa0/ /' gcc/doc/options.texi
+
+sed -i -e 's/Common Driver Var(flag_report_bug)/& Init(1)/' gcc/common.opt
+
+%ifarch ppc
+if [ -d libstdc++-v3/config/abi/post/powerpc64-linux-gnu ]; then
+ mkdir -p libstdc++-v3/config/abi/post/powerpc64-linux-gnu/64
+ mv libstdc++-v3/config/abi/post/powerpc64-linux-gnu/{,64/}baseline_symbols.txt
+ mv libstdc++-v3/config/abi/post/powerpc64-linux-gnu/{32/,}baseline_symbols.txt
+ rm -rf libstdc++-v3/config/abi/post/powerpc64-linux-gnu/32
+fi
+%endif
+%ifarch sparc
+if [ -d libstdc++-v3/config/abi/post/sparc64-linux-gnu ]; then
+ mkdir -p libstdc++-v3/config/abi/post/sparc64-linux-gnu/64
+ mv libstdc++-v3/config/abi/post/sparc64-linux-gnu/{,64/}baseline_symbols.txt
+ mv libstdc++-v3/config/abi/post/sparc64-linux-gnu/{32/,}baseline_symbols.txt
+ rm -rf libstdc++-v3/config/abi/post/sparc64-linux-gnu/32
+fi
+%endif
+
+# This test causes fork failures, because it spawns way too many threads
+rm -f gcc/testsuite/go.test/test/chan/goroutines.go
+
+%build
+
+# Undo the broken autoconf change in recent Fedora versions
+export CONFIG_SITE=NONE
+
+CC=gcc
+CXX=g++
+OPT_FLAGS=`echo %{optflags}|sed -e 's/\(-Wp,\)\?-D_FORTIFY_SOURCE=[12]//g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-m64//g;s/-m32//g;s/-m31//g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mfpmath=sse/-mfpmath=sse -msse2/g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/ -pipe / /g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-Werror=format-security/-Wformat-security/g'`
+%ifarch sparc
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mcpu=ultrasparc/-mtune=ultrasparc/g;s/-mcpu=v[78]//g'`
+%endif
+%ifarch %{ix86}
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-march=i.86//g'`
+%endif
+OPT_FLAGS=`echo "$OPT_FLAGS" | sed -e 's/[[:blank:]]\+/ /g'`
+case "$OPT_FLAGS" in
+ *-fasynchronous-unwind-tables*)
+ sed -i -e 's/-fno-exceptions /-fno-exceptions -fno-asynchronous-unwind-tables /' \
+ libgcc/Makefile.in
+ ;;
+esac
+
+%if %{build_offload_nvptx}
+mkdir obji
+IROOT=`pwd`/obji
+cd nvptx-tools-%{nvptx_tools_gitrev}
+rm -rf obj-%{gcc_target_platform}
+mkdir obj-%{gcc_target_platform}
+cd obj-%{gcc_target_platform}
+CC="$CC" CXX="$CXX" CFLAGS="%{optflags}" CXXFLAGS="%{optflags}" LDFLAGS="$RPM_LD_FLAGS" \
+../configure --prefix=%{_prefix}
+make %{?_smp_mflags}
+make install prefix=${IROOT}%{_prefix}
+cd ../..
+
+ln -sf nvptx-newlib-%{nvptx_newlib_gitrev}/newlib newlib
+rm -rf obj-offload-nvptx-none
+mkdir obj-offload-nvptx-none
+
+cd obj-offload-nvptx-none
+CC="$CC" CXX="$CXX" CFLAGS="$OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" \
+ CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+ | sed 's/ -Wformat-security / -Wformat -Wformat-security /'`" \
+ XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" \
+ ../configure --disable-bootstrap --disable-sjlj-exceptions \
+ --enable-newlib-io-long-long --with-build-time-tools=${IROOT}%{_prefix}/nvptx-none/bin \
+ --target nvptx-none --enable-as-accelerator-for=%{gcc_target_platform} \
+ --enable-languages=c,c++,fortran,lto \
+ --prefix=%{_prefix} --mandir=%{_mandir} --infodir=%{_infodir} \
+ --with-bugurl=http://bugzilla.redhat.com/bugzilla \
+ --enable-checking=release --with-system-zlib \
+ --with-gcc-major-version-only --without-isl
+make %{?_smp_mflags}
+cd ..
+rm -f newlib
+%endif
+
+rm -rf obj-%{gcc_target_platform}
+mkdir obj-%{gcc_target_platform}
+cd obj-%{gcc_target_platform}
+
+enablelgo=
+enablelada=
+enablelobjc=
+%if %{build_objc}
+enablelobjc=,objc,obj-c++
+%endif
+%if %{build_ada}
+enablelada=,ada
+%endif
+%if %{build_go}
+enablelgo=,go
+%endif
+CONFIGURE_OPTS="\
+ --prefix=%{_prefix} --mandir=%{_mandir} --infodir=%{_infodir} \
+ --with-bugurl=http://bugzilla.redhat.com/bugzilla \
+ --enable-shared --enable-threads=posix --enable-checking=release \
+%ifarch ppc64le
+ --enable-targets=powerpcle-linux \
+%endif
+%ifarch ppc64le %{mips} riscv64 s390x
+ --disable-multilib \
+%else
+ --enable-multilib \
+%endif
+ --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions \
+ --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only \
+%ifnarch %{mips}
+ --with-linker-hash-style=gnu \
+%endif
+ --enable-plugin --enable-initfini-array \
+%if %{build_isl}
+ --with-isl \
+%else
+ --without-isl \
+%endif
+%if %{build_libmpx}
+ --enable-libmpx \
+%else
+ --disable-libmpx \
+%endif
+%if %{build_offload_nvptx}
+ --enable-offload-targets=nvptx-none \
+ --without-cuda-driver \
+%endif
+%if 0%{?fedora} >= 21 || 0%{?rhel} >= 7
+%if %{attr_ifunc}
+ --enable-gnu-indirect-function \
+%endif
+%endif
+%ifarch %{arm}
+ --disable-sjlj-exceptions \
+%endif
+%ifarch ppc ppc64 ppc64le ppc64p7
+ --enable-secureplt \
+%endif
+%ifarch sparc sparcv9 sparc64 ppc ppc64 ppc64le ppc64p7 s390 s390x alpha
+ --with-long-double-128 \
+%endif
+%ifarch sparc
+ --disable-linux-futex \
+%endif
+%ifarch sparc64
+ --with-cpu=ultrasparc \
+%endif
+%ifarch sparc sparcv9
+ --host=%{gcc_target_platform} --build=%{gcc_target_platform} --target=%{gcc_target_platform} --with-cpu=v7
+%endif
+%ifarch ppc ppc64 ppc64p7
+%if 0%{?rhel} >= 7
+ --with-cpu-32=power7 --with-tune-32=power7 --with-cpu-64=power7 --with-tune-64=power7 \
+%endif
+%if 0%{?rhel} == 6
+ --with-cpu-32=power4 --with-tune-32=power6 --with-cpu-64=power4 --with-tune-64=power6 \
+%endif
+%endif
+%ifarch ppc64le
+ --with-cpu-32=power8 --with-tune-32=power8 --with-cpu-64=power8 --with-tune-64=power8 \
+%endif
+%ifarch ppc
+ --build=%{gcc_target_platform} --target=%{gcc_target_platform} --with-cpu=default32
+%endif
+%ifarch %{ix86} x86_64
+ --enable-cet \
+ --with-tune=generic \
+%endif
+%if 0%{?rhel} >= 7
+%ifarch %{ix86}
+ --with-arch=x86-64 \
+%endif
+%ifarch x86_64
+ --with-arch_32=x86-64 \
+%endif
+%else
+%ifarch %{ix86}
+ --with-arch=i686 \
+%endif
+%ifarch x86_64
+ --with-arch_32=i686 \
+%endif
+%endif
+%ifarch s390 s390x
+%if 0%{?rhel} >= 7
+%if 0%{?rhel} > 7
+ --with-arch=z13 --with-tune=z14 \
+%else
+ --with-arch=z196 --with-tune=zEC12 \
+%endif
+%else
+%if 0%{?fedora} >= 26
+ --with-arch=zEC12 --with-tune=z13 \
+%else
+ --with-arch=z9-109 --with-tune=z10 \
+%endif
+%endif
+ --enable-decimal-float \
+%endif
+%ifarch armv7hl
+ --with-tune=generic-armv7-a --with-arch=armv7-a \
+ --with-float=hard --with-fpu=vfpv3-d16 --with-abi=aapcs-linux \
+%endif
+%ifarch mips mipsel
+ --with-arch=mips32r2 --with-fp-32=xx \
+%endif
+%ifarch mips64 mips64el
+ --with-arch=mips64r2 --with-abi=64 \
+%endif
+%ifnarch sparc sparcv9 ppc
+ --build=%{gcc_target_platform} \
+%endif
+ "
+
+CC="$CC" CXX="$CXX" CFLAGS="$OPT_FLAGS" \
+ CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+ | sed 's/ -Wformat-security / -Wformat -Wformat-security /'`" \
+ XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" \
+ ../configure --enable-bootstrap \
+ --enable-languages=c,c++,fortran${enablelobjc}${enablelada}${enablelgo},lto \
+ $CONFIGURE_OPTS
+
+%ifarch sparc sparcv9 sparc64
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" BOOT_LDFLAGS="$RPM_LD_FLAGS" \
+ LDFLAGS_FOR_TARGET="$RPM_LD_FLAGS" bootstrap
+%else
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" BOOT_LDFLAGS="$RPM_LD_FLAGS" \
+ LDFLAGS_FOR_TARGET="$RPM_LD_FLAGS" profiledbootstrap
+%endif
+
+CC="`%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-cc`"
+CXX="`%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-cxx` `%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-includes`"
+
+%if %{build_libgccjit}
+# Build libgccjit separately, so that normal compiler binaries aren't -fpic
+# unnecessarily.
+mkdir objlibgccjit
+cd objlibgccjit
+CC="$CC" CXX="$CXX" CFLAGS="$OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" \
+ CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+ | sed 's/ -Wformat-security / -Wformat -Wformat-security /'`" \
+ XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" \
+ ../../configure --disable-bootstrap --enable-host-shared \
+ --enable-languages=jit $CONFIGURE_OPTS
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" all-gcc
+cp -a gcc/libgccjit.so* ../gcc/
+cd ../gcc/
+ln -sf xgcc %{gcc_target_platform}-gcc-%{gcc_major}
+cp -a Makefile{,.orig}
+sed -i -e '/^CHECK_TARGETS/s/$/ check-jit/' Makefile
+touch -r Makefile.orig Makefile
+rm Makefile.orig
+make jit.sphinx.html
+make jit.sphinx.install-html jit_htmldir=`pwd`/../../rpm.doc/libgccjit-devel/html
+cd ..
+%endif
+
+# Make generated man pages even if Pod::Man is not new enough
+perl -pi -e 's/head3/head2/' ../contrib/texi2pod.pl
+for i in ../gcc/doc/*.texi; do
+ cp -a $i $i.orig; sed 's/ftable/table/' $i.orig > $i
+done
+make -C gcc generated-manpages
+for i in ../gcc/doc/*.texi; do mv -f $i.orig $i; done
+
+# Make generated doxygen pages.
+%if %{build_libstdcxx_docs}
+cd %{gcc_target_platform}/libstdc++-v3
+make doc-html-doxygen
+make doc-man-doxygen
+cd ../..
+%endif
+
+# Copy various doc files here and there
+cd ..
+mkdir -p rpm.doc/gfortran rpm.doc/objc
+mkdir -p rpm.doc/go rpm.doc/libgo rpm.doc/libquadmath rpm.doc/libitm
+mkdir -p rpm.doc/changelogs/{gcc/cp,gcc/ada,gcc/jit,libstdc++-v3,libobjc,libgomp,libcc1,libatomic,libsanitizer,libmpx}
+
+for i in {gcc,gcc/cp,gcc/ada,gcc/jit,libstdc++-v3,libobjc,libgomp,libcc1,libatomic,libsanitizer,libmpx}/ChangeLog*; do
+ cp -p $i rpm.doc/changelogs/$i
+done
+
+(cd gcc/fortran; for i in ChangeLog*; do
+ cp -p $i ../../rpm.doc/gfortran/$i
+done)
+(cd libgfortran; for i in ChangeLog*; do
+ cp -p $i ../rpm.doc/gfortran/$i.libgfortran
+done)
+%if %{build_objc}
+(cd libobjc; for i in README*; do
+ cp -p $i ../rpm.doc/objc/$i.libobjc
+done)
+%endif
+%if %{build_libquadmath}
+(cd libquadmath; for i in ChangeLog* COPYING.LIB; do
+ cp -p $i ../rpm.doc/libquadmath/$i.libquadmath
+done)
+%endif
+%if %{build_libitm}
+(cd libitm; for i in ChangeLog*; do
+ cp -p $i ../rpm.doc/libitm/$i.libitm
+done)
+%endif
+%if %{build_go}
+(cd gcc/go; for i in README* ChangeLog*; do
+ cp -p $i ../../rpm.doc/go/$i
+done)
+(cd libgo; for i in LICENSE* PATENTS* README; do
+ cp -p $i ../rpm.doc/libgo/$i.libgo
+done)
+%endif
+
+rm -f rpm.doc/changelogs/gcc/ChangeLog.[1-9]
+find rpm.doc -name \*ChangeLog\* | xargs bzip2 -9
+
+%install
+rm -rf %{buildroot}
+
+%if %{build_offload_nvptx}
+cd nvptx-tools-%{nvptx_tools_gitrev}
+cd obj-%{gcc_target_platform}
+make install prefix=%{buildroot}%{_prefix}
+cd ../..
+
+ln -sf nvptx-newlib-%{nvptx_newlib_gitrev}/newlib newlib
+cd obj-offload-nvptx-none
+make prefix=%{buildroot}%{_prefix} mandir=%{buildroot}%{_mandir} \
+ infodir=%{buildroot}%{_infodir} install
+rm -rf %{buildroot}%{_prefix}/libexec/gcc/nvptx-none/%{gcc_major}/install-tools
+rm -rf %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/{install-tools,plugin,cc1,cc1plus,f951}
+rm -rf %{buildroot}%{_infodir} %{buildroot}%{_mandir}/man7 %{buildroot}%{_prefix}/share/locale
+rm -rf %{buildroot}%{_prefix}/lib/gcc/nvptx-none/%{gcc_major}/{install-tools,plugin}
+rm -rf %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/{install-tools,plugin,include-fixed}
+rm -rf %{buildroot}%{_prefix}/%{_lib}/libc[cp]1*
+mv -f %{buildroot}%{_prefix}/nvptx-none/lib/*.{a,spec} %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/
+mv -f %{buildroot}%{_prefix}/nvptx-none/lib/mgomp/*.{a,spec} %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/mgomp/
+mv -f %{buildroot}%{_prefix}/lib/gcc/nvptx-none/%{gcc_major}/*.a %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/
+mv -f %{buildroot}%{_prefix}/lib/gcc/nvptx-none/%{gcc_major}/mgomp/*.a %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none/mgomp/
+find %{buildroot}%{_prefix}/lib/gcc/nvptx-none %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none \
+ %{buildroot}%{_prefix}/nvptx-none/lib -name \*.la | xargs rm
+cd ..
+rm -f newlib
+%endif
+
+cd obj-%{gcc_target_platform}
+
+TARGET_PLATFORM=%{gcc_target_platform}
+
+# There are some MP bugs in libstdc++ Makefiles
+make -C %{gcc_target_platform}/libstdc++-v3
+
+make prefix=%{buildroot}%{_prefix} mandir=%{buildroot}%{_mandir} \
+ infodir=%{buildroot}%{_infodir} install
+%if %{build_ada}
+chmod 644 %{buildroot}%{_infodir}/gnat*
+%endif
+
+FULLPATH=%{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+FULLEPATH=%{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+
+# fix some things
+ln -sf gcc %{buildroot}%{_prefix}/bin/cc
+rm -f %{buildroot}%{_prefix}/lib/cpp
+ln -sf ../bin/cpp %{buildroot}/%{_prefix}/lib/cpp
+ln -sf gfortran %{buildroot}%{_prefix}/bin/f95
+rm -f %{buildroot}%{_infodir}/dir
+gzip -9 %{buildroot}%{_infodir}/*.info*
+ln -sf gcc %{buildroot}%{_prefix}/bin/gnatgcc
+mkdir -p %{buildroot}%{_fmoddir}
+
+%if %{build_go}
+mv %{buildroot}%{_prefix}/bin/go{,.gcc}
+mv %{buildroot}%{_prefix}/bin/gofmt{,.gcc}
+ln -sf /etc/alternatives/go %{buildroot}%{_prefix}/bin/go
+ln -sf /etc/alternatives/gofmt %{buildroot}%{_prefix}/bin/gofmt
+%endif
+
+cxxconfig="`find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h`"
+for i in `find %{gcc_target_platform}/[36]*/libstdc++-v3/include -name c++config.h 2>/dev/null`; do
+ if ! diff -up $cxxconfig $i; then
+ cat > %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/bits/c++config.h <
+#if __WORDSIZE == 32
+%ifarch %{multilib_64_archs}
+`cat $(find %{gcc_target_platform}/32/libstdc++-v3/include -name c++config.h)`
+%else
+`cat $(find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h)`
+%endif
+#else
+%ifarch %{multilib_64_archs}
+`cat $(find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h)`
+%else
+`cat $(find %{gcc_target_platform}/64/libstdc++-v3/include -name c++config.h)`
+%endif
+#endif
+#endif
+EOF
+ break
+ fi
+done
+
+for f in `find %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/ -name c++config.h`; do
+ for i in 1 2 4 8; do
+ sed -i -e 's/#define _GLIBCXX_ATOMIC_BUILTINS_'$i' 1/#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_'$i'\
+&\
+#endif/' $f
+ done
+done
+
+# Nuke bits/*.h.gch dirs
+# 1) there is no bits/*.h header installed, so when gch file can't be
+# used, compilation fails
+# 2) sometimes it is hard to match the exact options used for building
+# libstdc++-v3 or they aren't desirable
+# 3) there are multilib issues, conflicts etc. with this
+# 4) it is huge
+# People can always precompile on their own whatever they want, but
+# shipping this for everybody is unnecessary.
+rm -rf %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/bits/*.h.gch
+
+%if %{build_libstdcxx_docs}
+libstdcxx_doc_builddir=%{gcc_target_platform}/libstdc++-v3/doc/doxygen
+mkdir -p ../rpm.doc/libstdc++-v3
+cp -r -p ../libstdc++-v3/doc/html ../rpm.doc/libstdc++-v3/html
+cp -r -p $libstdcxx_doc_builddir/html ../rpm.doc/libstdc++-v3/html/api
+mkdir -p %{buildroot}%{_mandir}/man3
+cp -r -p $libstdcxx_doc_builddir/man/man3/* %{buildroot}%{_mandir}/man3/
+find ../rpm.doc/libstdc++-v3 -name \*~ | xargs rm
+%endif
+
+%ifarch sparcv9 sparc64
+ln -f %{buildroot}%{_prefix}/bin/%{gcc_target_platform}-gcc \
+ %{buildroot}%{_prefix}/bin/sparc-%{_vendor}-%{_target_os}-gcc
+%endif
+%ifarch ppc ppc64 ppc64p7
+ln -f %{buildroot}%{_prefix}/bin/%{gcc_target_platform}-gcc \
+ %{buildroot}%{_prefix}/bin/ppc-%{_vendor}-%{_target_os}-gcc
+%endif
+
+FULLLSUBDIR=
+%ifarch sparcv9 ppc
+FULLLSUBDIR=lib32
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+FULLLSUBDIR=lib64
+%endif
+if [ -n "$FULLLSUBDIR" ]; then
+ FULLLPATH=$FULLPATH/$FULLLSUBDIR
+ mkdir -p $FULLLPATH
+else
+ FULLLPATH=$FULLPATH
+fi
+
+find %{buildroot} -name \*.la | xargs rm -f
+
+mv %{buildroot}%{_prefix}/%{_lib}/libgfortran.spec $FULLPATH/
+%if %{build_libitm}
+mv %{buildroot}%{_prefix}/%{_lib}/libitm.spec $FULLPATH/
+%endif
+%if %{build_libasan}
+mv %{buildroot}%{_prefix}/%{_lib}/libsanitizer.spec $FULLPATH/
+%endif
+%if %{build_libmpx}
+mv %{buildroot}%{_prefix}/%{_lib}/libmpx.spec $FULLPATH/
+%endif
+
+mkdir -p %{buildroot}/%{_lib}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgcc_s.so.1 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1
+chmod 755 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1
+ln -sf libgcc_s-%{gcc_major}-%{DATE}.so.1 %{buildroot}/%{_lib}/libgcc_s.so.1
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64p7 ppc64le %{arm}
+rm -f $FULLPATH/libgcc_s.so
+echo '/* GNU ld script
+ Use the shared library, but some functions are only in
+ the static library, so try that secondarily. */
+OUTPUT_FORMAT('`gcc -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /%{_lib}/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so
+%else
+ln -sf /%{_lib}/libgcc_s.so.1 $FULLPATH/libgcc_s.so
+%endif
+%ifarch sparcv9 ppc
+%ifarch ppc
+rm -f $FULLPATH/64/libgcc_s.so
+echo '/* GNU ld script
+ Use the shared library, but some functions are only in
+ the static library, so try that secondarily. */
+OUTPUT_FORMAT('`gcc -m64 -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /lib64/libgcc_s.so.1 libgcc.a )' > $FULLPATH/64/libgcc_s.so
+%else
+ln -sf /lib64/libgcc_s.so.1 $FULLPATH/64/libgcc_s.so
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+%ifarch x86_64 ppc64 ppc64p7
+rm -f $FULLPATH/64/libgcc_s.so
+echo '/* GNU ld script
+ Use the shared library, but some functions are only in
+ the static library, so try that secondarily. */
+OUTPUT_FORMAT('`gcc -m32 -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/32/libgcc_s.so
+%else
+ln -sf /lib/libgcc_s.so.1 $FULLPATH/32/libgcc_s.so
+%endif
+%endif
+
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.spec $FULLPATH/
+
+%if %{build_ada}
+mv -f $FULLPATH/adalib/libgnarl-*.so %{buildroot}%{_prefix}/%{_lib}/
+mv -f $FULLPATH/adalib/libgnat-*.so %{buildroot}%{_prefix}/%{_lib}/
+rm -f $FULLPATH/adalib/libgnarl.so* $FULLPATH/adalib/libgnat.so*
+%endif
+
+mkdir -p %{buildroot}%{_prefix}/libexec/getconf
+if gcc/xgcc -B gcc/ -E -P -dD -xc /dev/null | grep '__LONG_MAX__.*\(2147483647\|0x7fffffff\($\|[LU]\)\)'; then
+ ln -sf POSIX_V6_ILP32_OFF32 %{buildroot}%{_prefix}/libexec/getconf/default
+else
+ ln -sf POSIX_V6_LP64_OFF64 %{buildroot}%{_prefix}/libexec/getconf/default
+fi
+
+mkdir -p %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++*gdb.py* \
+ %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/
+pushd ../libstdc++-v3/python
+for i in `find . -name \*.py`; do
+ touch -r $i %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/$i
+done
+touch -r hook.in %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc++*gdb.py
+popd
+for f in `find %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/ \
+ %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/ -name \*.py`; do
+ r=${f/$RPM_BUILD_ROOT/}
+ %{__python3} -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")'
+ %{__python3} -O -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")'
+done
+
+%if %{build_libgccjit}
+rm -f $FULLEPATH/libgccjit.so
+cp -a objlibgccjit/gcc/libgccjit.so* %{buildroot}%{_prefix}/%{_lib}/
+cp -a ../gcc/jit/libgccjit*.h %{buildroot}%{_prefix}/include/
+/usr/bin/install -c -m 644 objlibgccjit/gcc/doc/libgccjit.info %{buildroot}/%{_infodir}/
+gzip -9 %{buildroot}/%{_infodir}/libgccjit.info
+%endif
+
+pushd $FULLPATH
+if [ "%{_lib}" = "lib" ]; then
+%if %{build_objc}
+ln -sf ../../../libobjc.so.4 libobjc.so
+%endif
+ln -sf ../../../libstdc++.so.6.*[0-9] libstdc++.so
+ln -sf ../../../libgfortran.so.5.* libgfortran.so
+ln -sf ../../../libgomp.so.1.* libgomp.so
+%if %{build_go}
+ln -sf ../../../libgo.so.13.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_libitm}
+ln -sf ../../../libitm.so.1.* libitm.so
+%endif
+%if %{build_libatomic}
+ln -sf ../../../libatomic.so.1.* libatomic.so
+%endif
+%if %{build_libasan}
+ln -sf ../../../libasan.so.5.* libasan.so
+mv ../../../libasan_preinit.o libasan_preinit.o
+%endif
+%if %{build_libubsan}
+ln -sf ../../../libubsan.so.1.* libubsan.so
+%endif
+%if %{build_libmpx}
+ln -sf ../../../libmpx.so.2.* libmpx.so
+ln -sf ../../../libmpxwrappers.so.2.* libmpxwrappers.so
+%endif
+else
+%if %{build_objc}
+ln -sf ../../../../%{_lib}/libobjc.so.4 libobjc.so
+%endif
+ln -sf ../../../../%{_lib}/libstdc++.so.6.*[0-9] libstdc++.so
+ln -sf ../../../../%{_lib}/libgfortran.so.5.* libgfortran.so
+ln -sf ../../../../%{_lib}/libgomp.so.1.* libgomp.so
+%if %{build_go}
+ln -sf ../../../../%{_lib}/libgo.so.13.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../../%{_lib}/libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_libitm}
+ln -sf ../../../../%{_lib}/libitm.so.1.* libitm.so
+%endif
+%if %{build_libatomic}
+ln -sf ../../../../%{_lib}/libatomic.so.1.* libatomic.so
+%endif
+%if %{build_libasan}
+ln -sf ../../../../%{_lib}/libasan.so.5.* libasan.so
+mv ../../../../%{_lib}/libasan_preinit.o libasan_preinit.o
+%endif
+%if %{build_libubsan}
+ln -sf ../../../../%{_lib}/libubsan.so.1.* libubsan.so
+%endif
+%if %{build_libmpx}
+ln -sf ../../../../%{_lib}/libmpx.so.2.* libmpx.so
+ln -sf ../../../../%{_lib}/libmpxwrappers.so.2.* libmpxwrappers.so
+%endif
+%if %{build_libtsan}
+rm -f libtsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/libtsan.so.0.* | sed 's,^.*libt,libt,'`' )' > libtsan.so
+mv ../../../../%{_lib}/libtsan_preinit.o libtsan_preinit.o
+%endif
+%if %{build_liblsan}
+rm -f liblsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/liblsan.so.0.* | sed 's,^.*libl,libl,'`' )' > liblsan.so
+mv ../../../../%{_lib}/liblsan_preinit.o liblsan_preinit.o
+%endif
+fi
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++fs.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libsupc++.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgfortran.*a $FULLLPATH/
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libobjc.*a .
+%endif
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.*a .
+%if %{build_libquadmath}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libquadmath.*a $FULLLPATH/
+%endif
+%if %{build_libitm}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libitm.*a $FULLLPATH/
+%endif
+%if %{build_libatomic}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libatomic.*a $FULLLPATH/
+%endif
+%if %{build_libasan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libasan.*a $FULLLPATH/
+%endif
+%if %{build_libubsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libubsan.*a $FULLLPATH/
+%endif
+%if %{build_libmpx}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libmpx.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libmpxwrappers.*a $FULLLPATH/
+%endif
+%if %{build_libtsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libtsan.*a $FULLPATH/
+%endif
+%if %{build_liblsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/liblsan.*a $FULLPATH/
+%endif
+%if %{build_go}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgo.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgobegin.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgolibbegin.*a $FULLLPATH/
+%endif
+
+%if %{build_ada}
+%ifarch sparcv9 ppc
+rm -rf $FULLPATH/64/ada{include,lib}
+%endif
+%ifarch %{multilib_64_archs}
+rm -rf $FULLPATH/32/ada{include,lib}
+%endif
+if [ "$FULLPATH" != "$FULLLPATH" ]; then
+mv -f $FULLPATH/ada{include,lib} $FULLLPATH/
+pushd $FULLLPATH/adalib
+if [ "%{_lib}" = "lib" ]; then
+ln -sf ../../../../../libgnarl-*.so libgnarl.so
+ln -sf ../../../../../libgnarl-*.so libgnarl-8.so
+ln -sf ../../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../../libgnat-*.so libgnat-8.so
+else
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl-8.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat-8.so
+fi
+popd
+else
+pushd $FULLPATH/adalib
+if [ "%{_lib}" = "lib" ]; then
+ln -sf ../../../../libgnarl-*.so libgnarl.so
+ln -sf ../../../../libgnarl-*.so libgnarl-8.so
+ln -sf ../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../libgnat-*.so libgnat-8.so
+else
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl-8.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat-8.so
+fi
+popd
+fi
+%endif
+
+%ifarch sparcv9 ppc
+%if %{build_objc}
+ln -sf ../../../../../lib64/libobjc.so.4 64/libobjc.so
+%endif
+ln -sf ../`echo ../../../../lib/libstdc++.so.6.*[0-9] | sed s~/lib/~/lib64/~` 64/libstdc++.so
+ln -sf ../`echo ../../../../lib/libgfortran.so.5.* | sed s~/lib/~/lib64/~` 64/libgfortran.so
+ln -sf ../`echo ../../../../lib/libgomp.so.1.* | sed s~/lib/~/lib64/~` 64/libgomp.so
+%if %{build_go}
+rm -f libgo.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libgo.so.13.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgo.so.13.* | sed 's,^.*libg,libg,'`' )' > 64/libgo.so
+%endif
+%if %{build_libquadmath}
+rm -f libquadmath.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > libquadmath.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > 64/libquadmath.so
+%endif
+%if %{build_libitm}
+rm -f libitm.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > libitm.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > 64/libitm.so
+%endif
+%if %{build_libatomic}
+rm -f libatomic.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > libatomic.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > 64/libatomic.so
+%endif
+%if %{build_libasan}
+rm -f libasan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libasan.so.5.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libasan.so.5.* | sed 's,^.*liba,liba,'`' )' > 64/libasan.so
+mv ../../../../lib64/libasan_preinit.o 64/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+rm -f libubsan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > libubsan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > 64/libubsan.so
+%endif
+%if %{build_libmpx}
+rm -f libmpx.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libmpx.so.2.* | sed 's,^.*libm,libm,'`' )' > libmpx.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libmpx.so.2.* | sed 's,^.*libm,libm,'`' )' > 64/libmpx.so
+rm -f libmpxwrappers.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libmpxwrappers.so.2.* | sed 's,^.*libm,libm,'`' )' > libmpxwrappers.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libmpxwrappers.so.2.* | sed 's,^.*libm,libm,'`' )' > 64/libmpxwrappers.so
+%endif
+ln -sf lib32/libgfortran.a libgfortran.a
+ln -sf ../lib64/libgfortran.a 64/libgfortran.a
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/lib64/libobjc.*a 64/
+%endif
+mv -f %{buildroot}%{_prefix}/lib64/libgomp.*a 64/
+ln -sf lib32/libstdc++.a libstdc++.a
+ln -sf ../lib64/libstdc++.a 64/libstdc++.a
+ln -sf lib32/libstdc++fs.a libstdc++fs.a
+ln -sf ../lib64/libstdc++fs.a 64/libstdc++fs.a
+ln -sf lib32/libsupc++.a libsupc++.a
+ln -sf ../lib64/libsupc++.a 64/libsupc++.a
+%if %{build_libquadmath}
+ln -sf lib32/libquadmath.a libquadmath.a
+ln -sf ../lib64/libquadmath.a 64/libquadmath.a
+%endif
+%if %{build_libitm}
+ln -sf lib32/libitm.a libitm.a
+ln -sf ../lib64/libitm.a 64/libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf lib32/libatomic.a libatomic.a
+ln -sf ../lib64/libatomic.a 64/libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf lib32/libasan.a libasan.a
+ln -sf ../lib64/libasan.a 64/libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf lib32/libubsan.a libubsan.a
+ln -sf ../lib64/libubsan.a 64/libubsan.a
+%endif
+%if %{build_libmpx}
+ln -sf lib32/libmpx.a libmpx.a
+ln -sf ../lib64/libmpx.a 64/libmpx.a
+ln -sf lib32/libmpxwrappers.a libmpxwrappers.a
+ln -sf ../lib64/libmpxwrappers.a 64/libmpxwrappers.a
+%endif
+%if %{build_go}
+ln -sf lib32/libgo.a libgo.a
+ln -sf ../lib64/libgo.a 64/libgo.a
+ln -sf lib32/libgobegin.a libgobegin.a
+ln -sf ../lib64/libgobegin.a 64/libgobegin.a
+ln -sf lib32/libgolibbegin.a libgolibbegin.a
+ln -sf ../lib64/libgolibbegin.a 64/libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf lib32/adainclude adainclude
+ln -sf ../lib64/adainclude 64/adainclude
+ln -sf lib32/adalib adalib
+ln -sf ../lib64/adalib 64/adalib
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+mkdir -p 32
+%if %{build_objc}
+ln -sf ../../../../libobjc.so.4 32/libobjc.so
+%endif
+ln -sf ../`echo ../../../../lib64/libstdc++.so.6.*[0-9] | sed s~/../lib64/~/~` 32/libstdc++.so
+ln -sf ../`echo ../../../../lib64/libgfortran.so.5.* | sed s~/../lib64/~/~` 32/libgfortran.so
+ln -sf ../`echo ../../../../lib64/libgomp.so.1.* | sed s~/../lib64/~/~` 32/libgomp.so
+%if %{build_go}
+rm -f libgo.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libgo.so.13.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgo.so.13.* | sed 's,^.*libg,libg,'`' )' > 32/libgo.so
+%endif
+%if %{build_libquadmath}
+rm -f libquadmath.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > libquadmath.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > 32/libquadmath.so
+%endif
+%if %{build_libitm}
+rm -f libitm.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > libitm.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > 32/libitm.so
+%endif
+%if %{build_libatomic}
+rm -f libatomic.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > libatomic.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > 32/libatomic.so
+%endif
+%if %{build_libasan}
+rm -f libasan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libasan.so.5.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libasan.so.5.* | sed 's,^.*liba,liba,'`' )' > 32/libasan.so
+mv ../../../../lib/libasan_preinit.o 32/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+rm -f libubsan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > libubsan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > 32/libubsan.so
+%endif
+%if %{build_libmpx}
+rm -f libmpx.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libmpx.so.2.* | sed 's,^.*libm,libm,'`' )' > libmpx.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libmpx.so.2.* | sed 's,^.*libm,libm,'`' )' > 32/libmpx.so
+rm -f libmpxwrappers.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libmpxwrappers.so.2.* | sed 's,^.*libm,libm,'`' )' > libmpxwrappers.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libmpxwrappers.so.2.* | sed 's,^.*libm,libm,'`' )' > 32/libmpxwrappers.so
+%endif
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/lib/libobjc.*a 32/
+%endif
+mv -f %{buildroot}%{_prefix}/lib/libgomp.*a 32/
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+ln -sf ../lib32/libgfortran.a 32/libgfortran.a
+ln -sf lib64/libgfortran.a libgfortran.a
+ln -sf ../lib32/libstdc++.a 32/libstdc++.a
+ln -sf lib64/libstdc++.a libstdc++.a
+ln -sf ../lib32/libstdc++fs.a 32/libstdc++fs.a
+ln -sf lib64/libstdc++fs.a libstdc++fs.a
+ln -sf ../lib32/libsupc++.a 32/libsupc++.a
+ln -sf lib64/libsupc++.a libsupc++.a
+%if %{build_libquadmath}
+ln -sf ../lib32/libquadmath.a 32/libquadmath.a
+ln -sf lib64/libquadmath.a libquadmath.a
+%endif
+%if %{build_libitm}
+ln -sf ../lib32/libitm.a 32/libitm.a
+ln -sf lib64/libitm.a libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf ../lib32/libatomic.a 32/libatomic.a
+ln -sf lib64/libatomic.a libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf ../lib32/libasan.a 32/libasan.a
+ln -sf lib64/libasan.a libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf ../lib32/libubsan.a 32/libubsan.a
+ln -sf lib64/libubsan.a libubsan.a
+%endif
+%if %{build_libmpx}
+ln -sf ../lib32/libmpx.a 32/libmpx.a
+ln -sf lib64/libmpx.a libmpx.a
+ln -sf ../lib32/libmpxwrappers.a 32/libmpxwrappers.a
+ln -sf lib64/libmpxwrappers.a libmpxwrappers.a
+%endif
+%if %{build_go}
+ln -sf ../lib32/libgo.a 32/libgo.a
+ln -sf lib64/libgo.a libgo.a
+ln -sf ../lib32/libgobegin.a 32/libgobegin.a
+ln -sf lib64/libgobegin.a libgobegin.a
+ln -sf ../lib32/libgolibbegin.a 32/libgolibbegin.a
+ln -sf lib64/libgolibbegin.a libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf ../lib32/adainclude 32/adainclude
+ln -sf lib64/adainclude adainclude
+ln -sf ../lib32/adalib 32/adalib
+ln -sf lib64/adalib adalib
+%endif
+%else
+%ifarch %{multilib_64_archs}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgfortran.a 32/libgfortran.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libstdc++.a 32/libstdc++.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libstdc++fs.a 32/libstdc++fs.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libsupc++.a 32/libsupc++.a
+%if %{build_libquadmath}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libquadmath.a 32/libquadmath.a
+%endif
+%if %{build_libitm}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libitm.a 32/libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libatomic.a 32/libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libasan.a 32/libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libubsan.a 32/libubsan.a
+%endif
+%if %{build_libmpx}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libmpx.a 32/libmpx.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libmpxwrappers.a 32/libmpxwrappers.a
+%endif
+%if %{build_go}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgo.a 32/libgo.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgobegin.a 32/libgobegin.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgolibbegin.a 32/libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/adainclude 32/adainclude
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/adalib 32/adalib
+%endif
+%endif
+%endif
+
+# If we are building a debug package then copy all of the static archives
+# into the debug directory to keep them as unstripped copies.
+%if 0%{?_enable_debug_packages}
+for d in . $FULLLSUBDIR; do
+ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/$d
+ for f in `find $d -maxdepth 1 -a \
+ \( -name libasan.a -o -name libatomic.a \
+ -o -name libcaf_single.a \
+ -o -name libgcc.a -o -name libgcc_eh.a \
+ -o -name libgcov.a -o -name libgfortran.a \
+ -o -name libgo.a -o -name libgobegin.a \
+ -o -name libgolibbegin.a -o -name libgomp.a \
+ -o -name libitm.a -o -name liblsan.a \
+ -o -name libmpx.a -o -name libmpxwrappers.a \
+ -o -name libobjc.a \
+ -o -name libquadmath.a -o -name libstdc++.a \
+ -o -name libstdc++fs.a -o -name libsupc++.a \
+ -o -name libtsan.a -o -name libubsan.a \) -a -type f`; do
+ cp -a $f $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/$d/
+ done
+done
+%endif
+
+# Strip debug info from Fortran/ObjC/Java static libraries
+strip -g `find . \( -name libgfortran.a -o -name libobjc.a -o -name libgomp.a \
+ -o -name libgcc.a -o -name libgcov.a -o -name libquadmath.a \
+ -o -name libitm.a -o -name libgo.a -o -name libcaf\*.a \
+ -o -name libatomic.a -o -name libasan.a -o -name libtsan.a \
+ -o -name libubsan.a -o -name liblsan.a \
+ -o -name libmpx.a -o -name libmpxwrappers.a -o -name libcc1.a \) \
+ -a -type f`
+popd
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgfortran.so.5.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgomp.so.1.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libcc1.so.0.*
+%if %{build_libquadmath}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libquadmath.so.0.*
+%endif
+%if %{build_libitm}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libitm.so.1.*
+%endif
+%if %{build_libatomic}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libatomic.so.1.*
+%endif
+%if %{build_libasan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libasan.so.5.*
+%endif
+%if %{build_libubsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libubsan.so.1.*
+%endif
+%if %{build_libmpx}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libmpx.so.2.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libmpxwrappers.so.2.*
+%endif
+%if %{build_libtsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libtsan.so.0.*
+%endif
+%if %{build_liblsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/liblsan.so.0.*
+%endif
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.13.*
+chmod 644 %{buildroot}%{_prefix}/bin/go.gcc
+chmod 644 %{buildroot}%{_prefix}/bin/gofmt.gcc
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet
+%endif
+%if %{build_objc}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libobjc.so.4.*
+%endif
+
+%if %{build_ada}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnarl*so*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnat*so*
+%endif
+
+mv $FULLPATH/include-fixed/syslimits.h $FULLPATH/include/syslimits.h
+mv $FULLPATH/include-fixed/limits.h $FULLPATH/include/limits.h
+for h in `find $FULLPATH/include -name \*.h`; do
+ if grep -q 'It has been auto-edited by fixincludes from' $h; then
+ rh=`grep -A2 'It has been auto-edited by fixincludes from' $h | tail -1 | sed 's|^.*"\(.*\)".*$|\1|'`
+ diff -up $rh $h || :
+ rm -f $h
+ fi
+done
+
+cat > %{buildroot}%{_prefix}/bin/c89 <<"EOF"
+#!/bin/sh
+fl="-std=c89"
+for opt; do
+ case "$opt" in
+ -ansi|-std=c89|-std=iso9899:1990) fl="";;
+ -std=*) echo "`basename $0` called with non ANSI/ISO C option $opt" >&2
+ exit 1;;
+ esac
+done
+exec gcc $fl ${1+"$@"}
+EOF
+cat > %{buildroot}%{_prefix}/bin/c99 <<"EOF"
+#!/bin/sh
+fl="-std=c99"
+for opt; do
+ case "$opt" in
+ -std=c99|-std=iso9899:1999) fl="";;
+ -std=*) echo "`basename $0` called with non ISO C99 option $opt" >&2
+ exit 1;;
+ esac
+done
+exec gcc $fl ${1+"$@"}
+EOF
+chmod 755 %{buildroot}%{_prefix}/bin/c?9
+
+cd ..
+%find_lang %{name}
+%find_lang cpplib
+
+# Remove binaries we will not be including, so that they don't end up in
+# gcc-debuginfo
+rm -f %{buildroot}%{_prefix}/%{_lib}/{libffi*,libiberty.a} || :
+rm -f $FULLEPATH/install-tools/{mkheaders,fixincl}
+rm -f %{buildroot}%{_prefix}/lib/{32,64}/libiberty.a
+rm -f %{buildroot}%{_prefix}/%{_lib}/libssp*
+rm -f %{buildroot}%{_prefix}/%{_lib}/libvtv* || :
+rm -f %{buildroot}%{_prefix}/bin/gappletviewer || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gfortran || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gccgo || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcj || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ar || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-nm || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ranlib || :
+
+%ifarch %{multilib_64_archs}
+# Remove libraries for the other arch on multilib arches
+rm -f %{buildroot}%{_prefix}/lib/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib/lib*.a
+rm -f %{buildroot}/lib/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%ifnarch sparc64 ppc64 ppc64p7
+ln -sf %{multilib_32_arch}-%{_vendor}-%{_target_os} %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%else
+%ifarch sparcv9 ppc
+rm -f %{buildroot}%{_prefix}/lib64/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib64/lib*.a
+rm -f %{buildroot}/lib64/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib64/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%endif
+
+rm -f %{buildroot}%{mandir}/man3/ffi*
+
+# Help plugins find out nvra.
+echo gcc-%{version}-%{release}.%{_arch} > $FULLPATH/rpmver
+
+%check
+cd obj-%{gcc_target_platform}
+
+# run the tests.
+make %{?_smp_mflags} -k check ALT_CC_UNDER_TEST=gcc ALT_CXX_UNDER_TEST=g++ \
+%if 0%{?fedora} >= 20 || 0%{?rhel} > 7
+ RUNTESTFLAGS="--target_board=unix/'{,-fstack-protector-strong}'" || :
+%else
+ RUNTESTFLAGS="--target_board=unix/'{,-fstack-protector}'" || :
+%endif
+echo ====================TESTING=========================
+( LC_ALL=C ../contrib/test_summary || : ) 2>&1 | sed -n '/^cat.*EOF/,/^EOF/{/^cat.*EOF/d;/^EOF/d;/^LAST_UPDATED:/d;p;}'
+echo ====================TESTING END=====================
+mkdir testlogs-%{_target_platform}-%{version}-%{release}
+for i in `find . -name \*.log | grep -F testsuite/ | grep -v 'config.log\|acats.*/tests/'`; do
+ ln $i testlogs-%{_target_platform}-%{version}-%{release}/ || :
+done
+tar cf - testlogs-%{_target_platform}-%{version}-%{release} | xz -9e \
+ | uuencode testlogs-%{_target_platform}.tar.xz || :
+rm -rf testlogs-%{_target_platform}-%{version}-%{release}
+
+%post
+if [ -f %{_infodir}/gcc.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/gcc.info.gz || :
+fi
+
+%preun
+if [ $1 = 0 -a -f %{_infodir}/gcc.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/gcc.info.gz || :
+fi
+
+%post -n cpp
+if [ -f %{_infodir}/cpp.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/cpp.info.gz || :
+fi
+
+%preun -n cpp
+if [ $1 = 0 -a -f %{_infodir}/cpp.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/cpp.info.gz || :
+fi
+
+%post gfortran
+if [ -f %{_infodir}/gfortran.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/gfortran.info.gz || :
+fi
+
+%preun gfortran
+if [ $1 = 0 -a -f %{_infodir}/gfortran.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/gfortran.info.gz || :
+fi
+
+%post gnat
+if [ -f %{_infodir}/gnat_rm.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/gnat_rm.info.gz || :
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/gnat_ugn.info.gz || :
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/gnat-style.info.gz || :
+fi
+
+%preun gnat
+if [ $1 = 0 -a -f %{_infodir}/gnat_rm.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/gnat_rm.info.gz || :
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/gnat_ugn.info.gz || :
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/gnat-style.info.gz || :
+fi
+
+%post go
+%{_sbindir}/update-alternatives --install \
+ %{_prefix}/bin/go go %{_prefix}/bin/go.gcc 92 \
+ --slave %{_prefix}/bin/gofmt gofmt %{_prefix}/bin/gofmt.gcc
+
+%preun go
+if [ $1 = 0 ]; then
+ %{_sbindir}/update-alternatives --remove go %{_prefix}/bin/go.gcc
+fi
+
+# Because glibc Prereq's libgcc and /sbin/ldconfig
+# comes from glibc, it might not exist yet when
+# libgcc is installed
+%post -n libgcc -p
+if posix.access ("/sbin/ldconfig", "x") then
+ local pid = posix.fork ()
+ if pid == 0 then
+ posix.exec ("/sbin/ldconfig")
+ elseif pid ~= -1 then
+ posix.wait (pid)
+ end
+end
+
+%postun -n libgcc -p
+if posix.access ("/sbin/ldconfig", "x") then
+ local pid = posix.fork ()
+ if pid == 0 then
+ posix.exec ("/sbin/ldconfig")
+ elseif pid ~= -1 then
+ posix.wait (pid)
+ end
+end
+
+%post -n libstdc++ -p /sbin/ldconfig
+
+%postun -n libstdc++ -p /sbin/ldconfig
+
+%post -n libobjc -p /sbin/ldconfig
+
+%postun -n libobjc -p /sbin/ldconfig
+
+%post -n libgfortran -p /sbin/ldconfig
+
+%postun -n libgfortran -p /sbin/ldconfig
+
+%post -n libgnat -p /sbin/ldconfig
+
+%postun -n libgnat -p /sbin/ldconfig
+
+%post -n libgomp
+/sbin/ldconfig
+if [ -f %{_infodir}/libgomp.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/libgomp.info.gz || :
+fi
+
+%preun -n libgomp
+if [ $1 = 0 -a -f %{_infodir}/libgomp.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/libgomp.info.gz || :
+fi
+
+%postun -n libgomp -p /sbin/ldconfig
+
+%post gdb-plugin -p /sbin/ldconfig
+
+%postun gdb-plugin -p /sbin/ldconfig
+
+%post -n libgccjit -p /sbin/ldconfig
+
+%postun -n libgccjit -p /sbin/ldconfig
+
+%post -n libgccjit-devel
+if [ -f %{_infodir}/libgccjit.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/libgccjit.info.gz || :
+fi
+
+%preun -n libgccjit-devel
+if [ $1 = 0 -a -f %{_infodir}/libgccjit.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/libgccjit.info.gz || :
+fi
+
+%post -n libquadmath
+/sbin/ldconfig
+if [ -f %{_infodir}/libquadmath.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/libquadmath.info.gz || :
+fi
+
+%preun -n libquadmath
+if [ $1 = 0 -a -f %{_infodir}/libquadmath.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/libquadmath.info.gz || :
+fi
+
+%postun -n libquadmath -p /sbin/ldconfig
+
+%post -n libitm
+/sbin/ldconfig
+if [ -f %{_infodir}/libitm.info.gz ]; then
+ /sbin/install-info \
+ --info-dir=%{_infodir} %{_infodir}/libitm.info.gz || :
+fi
+
+%preun -n libitm
+if [ $1 = 0 -a -f %{_infodir}/libitm.info.gz ]; then
+ /sbin/install-info --delete \
+ --info-dir=%{_infodir} %{_infodir}/libitm.info.gz || :
+fi
+
+%postun -n libitm -p /sbin/ldconfig
+
+%post -n libatomic -p /sbin/ldconfig
+
+%postun -n libatomic -p /sbin/ldconfig
+
+%post -n libasan -p /sbin/ldconfig
+
+%postun -n libasan -p /sbin/ldconfig
+
+%post -n libubsan -p /sbin/ldconfig
+
+%postun -n libubsan -p /sbin/ldconfig
+
+%post -n libtsan -p /sbin/ldconfig
+
+%postun -n libtsan -p /sbin/ldconfig
+
+%post -n liblsan -p /sbin/ldconfig
+
+%postun -n liblsan -p /sbin/ldconfig
+
+%post -n libmpx -p /sbin/ldconfig
+
+%postun -n libmpx -p /sbin/ldconfig
+
+%post -n libgo -p /sbin/ldconfig
+
+%postun -n libgo -p /sbin/ldconfig
+
+%files -f %{name}.lang
+%{_prefix}/bin/cc
+%{_prefix}/bin/c89
+%{_prefix}/bin/c99
+%{_prefix}/bin/gcc
+%{_prefix}/bin/gcov
+%{_prefix}/bin/gcov-tool
+%{_prefix}/bin/gcov-dump
+%{_prefix}/bin/gcc-ar
+%{_prefix}/bin/gcc-nm
+%{_prefix}/bin/gcc-ranlib
+%ifarch ppc
+%{_prefix}/bin/%{_target_platform}-gcc
+%endif
+%ifarch sparc64 sparcv9
+%{_prefix}/bin/sparc-%{_vendor}-%{_target_os}-gcc
+%endif
+%ifarch ppc64 ppc64p7
+%{_prefix}/bin/ppc-%{_vendor}-%{_target_os}-gcc
+%endif
+%{_prefix}/bin/%{gcc_target_platform}-gcc
+%{_prefix}/bin/%{gcc_target_platform}-gcc-%{gcc_major}
+%{_mandir}/man1/gcc.1*
+%{_mandir}/man1/gcov.1*
+%{_mandir}/man1/gcov-tool.1*
+%{_mandir}/man1/gcov-dump.1*
+%{_infodir}/gcc*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/lto1
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/lto-wrapper
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/liblto_plugin.so*
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/rpmver
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stddef.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdarg.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdfix.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/varargs.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/float.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/limits.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdbool.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/iso646.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/syslimits.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/unwind.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/omp.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/openacc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdint.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdint-gcc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdalign.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdnoreturn.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdatomic.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/gcov.h
+%ifarch %{ix86} x86_64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/emmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ammintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/smmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/nmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/wmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/immintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fma4intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xopintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lwpintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/popcntintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tbmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ia32intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/f16cintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fmaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lzcntintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/rtmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xtestintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/adxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/prfchwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/rdseedintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fxsrintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsaveintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsaveoptintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512cdintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512erintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512fintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512pfintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/shaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm_malloc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm3dnow.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cpuid.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cross-stdarg.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512dqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512ifmaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512ifmavlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmivlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vlbwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vldqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clflushoptintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clwbintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mwaitxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsavecintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsavesintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clzerointrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pkuintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx5124fmapsintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx5124vnniwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vpopcntdqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/sgxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/gfniintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cetintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cet.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmi2vlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vnniintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vnnivlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vaesintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vpclmulqdqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vpopcntdqvlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bitalgintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pconfigintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/wbnoinvdintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/movdirintrin.h
+%endif
+%ifarch ia64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ia64intrin.h
+%endif
+%ifarch ppc ppc64 ppc64le ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ppc-asm.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/altivec.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/paired.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ppu_intrinsics.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/si2vmx.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/spu2vmx.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vec_types.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmxlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm_malloc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/emmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amo.h
+%endif
+%ifarch %{arm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/unwind-arm-common.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_neon.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_acle.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_cmse.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_fp16.h
+%endif
+%ifarch aarch64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_neon.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_acle.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_fp16.h
+%endif
+%ifarch sparc sparcv9 sparc64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/visintrin.h
+%endif
+%ifarch s390 s390x
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/s390intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmxlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vecintrin.h
+%endif
+%if %{build_libmpx}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpx.spec
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/sanitizer
+%endif
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/collect2
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.spec
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.so
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.spec
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsanitizer.spec
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgomp.so
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libubsan.so
+%endif
+%if %{build_libmpx}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libmpx.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libmpxwrappers.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libmpxwrappers.so
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgomp.so
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libubsan.so
+%endif
+%if %{build_libmpx}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libmpx.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libmpxwrappers.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libmpxwrappers.so
+%endif
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.so
+%endif
+%if %{build_libmpx}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpx.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpxwrappers.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpxwrappers.so
+%endif
+%else
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.so
+%endif
+%if %{build_libmpx}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpx.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpxwrappers.so
+%endif
+%endif
+%if %{build_libtsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan_preinit.o
+%endif
+%if %{build_liblsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan_preinit.o
+%endif
+%{_prefix}/libexec/getconf/default
+%doc gcc/README* rpm.doc/changelogs/gcc/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license gcc/COPYING* COPYING.RUNTIME
+
+%files -n cpp -f cpplib.lang
+%{_prefix}/lib/cpp
+%{_prefix}/bin/cpp
+%{_mandir}/man1/cpp.1*
+%{_infodir}/cpp*
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1
+
+%files -n libgcc
+/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1
+/%{_lib}/libgcc_s.so.1
+%{!?_licensedir:%global license %%doc}
+%license gcc/COPYING* COPYING.RUNTIME
+
+%files c++
+%{_prefix}/bin/%{gcc_target_platform}-*++
+%{_prefix}/bin/g++
+%{_prefix}/bin/c++
+%{_mandir}/man1/g++.1*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1plus
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libsupc++.a
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libsupc++.a
+%endif
+%ifarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.so
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsupc++.a
+%endif
+%doc rpm.doc/changelogs/gcc/cp/ChangeLog*
+
+%files -n libstdc++
+%{_prefix}/%{_lib}/libstdc++.so.6*
+%dir %{_datadir}/gdb
+%dir %{_datadir}/gdb/auto-load
+%dir %{_datadir}/gdb/auto-load/%{_prefix}
+%dir %{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc*gdb.py*
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/__pycache__
+%dir %{_prefix}/share/gcc-%{gcc_major}
+%dir %{_prefix}/share/gcc-%{gcc_major}/python
+%{_prefix}/share/gcc-%{gcc_major}/python/libstdcxx
+
+%files -n libstdc++-devel
+%dir %{_prefix}/include/c++
+%{_prefix}/include/c++/%{gcc_major}
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifnarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.so
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libstdc++fs.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libstdc++fs.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++fs.a
+%endif
+%doc rpm.doc/changelogs/libstdc++-v3/ChangeLog* libstdc++-v3/README*
+
+%files -n libstdc++-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libsupc++.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libsupc++.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsupc++.a
+%endif
+
+%if %{build_libstdcxx_docs}
+%files -n libstdc++-docs
+%{_mandir}/man3/*
+%doc rpm.doc/libstdc++-v3/html
+%endif
+
+%if %{build_objc}
+%files objc
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/objc
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1obj
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libobjc.so
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libobjc.so
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libobjc.so
+%endif
+%doc rpm.doc/objc/*
+%doc libobjc/THREADS* rpm.doc/changelogs/libobjc/ChangeLog*
+
+%files objc++
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1objplus
+
+%files -n libobjc
+%{_prefix}/%{_lib}/libobjc.so.4*
+%endif
+
+%files gfortran
+%{_prefix}/bin/gfortran
+%{_prefix}/bin/f95
+%{_mandir}/man1/gfortran.1*
+%{_infodir}/gfortran*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.f90
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib_kinds.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc.f90
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc_kinds.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc_lib.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_arithmetic.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_exceptions.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_features.mod
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/f951
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.spec
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libcaf_single.a
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.a
+%endif
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.so
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libcaf_single.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgfortran.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgfortran.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/finclude
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libcaf_single.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgfortran.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgfortran.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/finclude
+%endif
+%dir %{_fmoddir}
+%doc rpm.doc/gfortran/*
+
+%files -n libgfortran
+%{_prefix}/%{_lib}/libgfortran.so.5*
+
+%files -n libgfortran-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgfortran.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgfortran.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.a
+%endif
+
+%if %{build_ada}
+%files gnat
+%{_prefix}/bin/gnat
+%{_prefix}/bin/gnat[^i]*
+%{_infodir}/gnat*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/adalib
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/adalib
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%endif
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/gnat1
+%doc rpm.doc/changelogs/gcc/ada/ChangeLog*
+
+%files -n libgnat
+%{_prefix}/%{_lib}/libgnat-*.so
+%{_prefix}/%{_lib}/libgnarl-*.so
+
+%files -n libgnat-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnarl.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnarl.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnarl.a
+%endif
+
+%files -n libgnat-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnarl.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnarl.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnarl.a
+%endif
+%endif
+
+%files -n libgomp
+%{_prefix}/%{_lib}/libgomp.so.1*
+%{_infodir}/libgomp.info*
+%doc rpm.doc/changelogs/libgomp/ChangeLog*
+
+%if %{build_libquadmath}
+%files -n libquadmath
+%{_prefix}/%{_lib}/libquadmath.so.0*
+%{_infodir}/libquadmath.info*
+%{!?_licensedir:%global license %%doc}
+%license rpm.doc/libquadmath/COPYING*
+
+%files -n libquadmath-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/quadmath.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/quadmath_weak.h
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.so
+%endif
+%doc rpm.doc/libquadmath/ChangeLog*
+
+%files -n libquadmath-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libquadmath.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libquadmath.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.a
+%endif
+%endif
+
+%if %{build_libitm}
+%files -n libitm
+%{_prefix}/%{_lib}/libitm.so.1*
+%{_infodir}/libitm.info*
+
+%files -n libitm-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+#%%{_prefix}/lib/gcc/%%{gcc_target_platform}/%%{gcc_major}/include/itm.h
+#%%{_prefix}/lib/gcc/%%{gcc_target_platform}/%%{gcc_major}/include/itm_weak.h
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.so
+%endif
+%doc rpm.doc/libitm/ChangeLog*
+
+%files -n libitm-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libitm.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libitm.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.a
+%endif
+%endif
+
+%if %{build_libatomic}
+%files -n libatomic
+%{_prefix}/%{_lib}/libatomic.so.1*
+
+%files -n libatomic-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libatomic.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libatomic.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.a
+%endif
+%doc rpm.doc/changelogs/libatomic/ChangeLog*
+%endif
+
+%if %{build_libasan}
+%files -n libasan
+%{_prefix}/%{_lib}/libasan.so.5*
+
+%files -n libasan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libasan.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libasan.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.a
+%endif
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_libubsan}
+%files -n libubsan
+%{_prefix}/%{_lib}/libubsan.so.1*
+
+%files -n libubsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libubsan.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libubsan.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.a
+%endif
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_libtsan}
+%files -n libtsan
+%{_prefix}/%{_lib}/libtsan.so.0*
+
+%files -n libtsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan.a
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_liblsan}
+%files -n liblsan
+%{_prefix}/%{_lib}/liblsan.so.0*
+
+%files -n liblsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan.a
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_libmpx}
+%files -n libmpx
+%{_prefix}/%{_lib}/libmpx.so.2*
+%{_prefix}/%{_lib}/libmpxwrappers.so.2*
+
+%files -n libmpx-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libmpxwrappers.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libmpxwrappers.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpx.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libmpxwrappers.a
+%endif
+%doc rpm.doc/changelogs/libmpx/ChangeLog*
+%endif
+
+%if %{build_go}
+%files go
+%ghost %{_prefix}/bin/go
+%attr(755,root,root) %{_prefix}/bin/go.gcc
+%{_prefix}/bin/gccgo
+%ghost %{_prefix}/bin/gofmt
+%attr(755,root,root) %{_prefix}/bin/gofmt.gcc
+%{_mandir}/man1/gccgo.1*
+%{_mandir}/man1/go.1*
+%{_mandir}/man1/gofmt.1*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/go1
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgo.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgolibbegin.a
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgo.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgolibbegin.a
+%endif
+%ifarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.so
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgolibbegin.a
+%endif
+%doc rpm.doc/go/*
+
+%files -n libgo
+%attr(755,root,root) %{_prefix}/%{_lib}/libgo.so.13*
+%doc rpm.doc/libgo/*
+
+%files -n libgo-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/%{_lib}/go
+%dir %{_prefix}/%{_lib}/go/%{gcc_major}
+%{_prefix}/%{_lib}/go/%{gcc_major}/%{gcc_target_platform}
+%ifarch %{multilib_64_archs}
+%ifnarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/go
+%dir %{_prefix}/lib/go/%{gcc_major}
+%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgolibbegin.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgolibbegin.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgolibbegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.so
+%endif
+
+%files -n libgo-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgo.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgo.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.a
+%endif
+%endif
+
+%if %{build_libgccjit}
+%files -n libgccjit
+%{_prefix}/%{_lib}/libgccjit.so.*
+%doc rpm.doc/changelogs/gcc/jit/ChangeLog*
+
+%files -n libgccjit-devel
+%{_prefix}/%{_lib}/libgccjit.so
+%{_prefix}/include/libgccjit*.h
+%{_infodir}/libgccjit.info*
+%doc rpm.doc/libgccjit-devel/*
+%doc gcc/jit/docs/examples
+%endif
+
+%files plugin-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/gtype.state
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+
+%files gdb-plugin
+%{_prefix}/%{_lib}/libcc1.so*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/libcc1plugin.so*
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/libcp1plugin.so*
+%doc rpm.doc/changelogs/libcc1/ChangeLog*
+
+%if %{build_offload_nvptx}
+%files offload-nvptx
+%{_prefix}/bin/nvptx-none-*
+%{_prefix}/bin/%{gcc_target_platform}-accel-nvptx-none-gcc
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/accel
+%{_prefix}/lib/gcc/nvptx-none
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/accel/nvptx-none
+%dir %{_prefix}/nvptx-none
+%{_prefix}/nvptx-none/bin
+%{_prefix}/nvptx-none/include
+
+%files -n libgomp-offload-nvptx
+%{_prefix}/%{_lib}/libgomp-plugin-nvptx.so.*
+%endif
+
+%changelog
+* Mon Jun 3 2019 Marek Polacek 8.3.1-4.4
+- backport workaround for broken C/C++ wrappers to LAPACK (#1711346)
+
+* Fri May 24 2019 Marek Polacek 8.3.1-4.3
+- additional fix for the libgomp testsuite (#1707568)
+
+* Tue May 21 2019 Marek Polacek 8.3.1-4.2
+- backport the -fuse-ld=lld option (#1670535)
+- TLS model fix (#1678555, PR c++/85400)
+- two small autoFDO fixes (#1686082)
+- libgomp update (#1707568)
+- member template redeclaration fix (#1652704, PR c++/86747)
+- turn libgcc_s.so into a linker script on i?86, x86_64, ppc64le and also on
+ ppc and ppc64 for 64-bit multilib (#1708309)
+- avoid using unaligned vsx or lxvd2x/stxvd2x for memcpy/memmove inline
+ expansion (#1666977)
+
+* Wed May 8 2019 Marek Polacek 8.3.1-4.1
+- tweak gcc8-rh1668903-1.patch and gcc8-rh1668903-2.patch patches
+
+* Tue May 7 2019 Marek Polacek 8.3.1-4
+- update from Fedora 8.3.1-4 (#1680182)
+- drop gcc8-pr60790.patch, gcc8-pr89629.patch, gcc8-rh1668903-4.patch
+
+* Tue May 7 2019 Marek Polacek 8.3.1-3
+- update from Fedora 8.3.1-3 (#1680182)
+- remove load and test FP splitter (#1673116)
+- fix *movsi_from_df (#1677652)
+- add missing headers
+- add support for live patching (#1668903)
+- retire gcc8-rh1612514.patch, gcc8-rh1652016.patch, gcc8-rh1652929-?.patch
+
+* Mon Dec 10 2018 Marek Polacek 8.2.1-3.5
+- remove python2 dependecy (#1595385)
+
+* Tue Nov 27 2018 Jeff Law 8.2.1-3.4
+- Backport PPC string inlines from trunk which allow for valgrind's
+ memcheck to work properly (#1652929)
+- Backport bugfix for clz pattern on s390 affecting jemalloc (#1652016)
+
+* Mon Oct 15 2018 Marek Polacek 8.2.1-3.3
+- avoid IFUNC resolver access to uninitialized data (#1559350, PR libgcc/60790)
+
+* Thu Oct 11 2018 Marek Polacek 8.2.1-3.2
+- fix typos in manual (#1612514)
+
+* Mon Oct 8 2018 Marek Polacek 8.2.1-3.1
+- enable hardening of binaries (#1624114)
+- disable libgccjit on RHEL
+
+* Tue Sep 18 2018 Marek Polacek 8.2.1-3
+- update from Fedora 8.2.1-3
+
+* Thu Aug 9 2018 Marek Polacek 8.2.1-1.3
+- change the default -march on s390x to z13 with tuning for z14 (#1571124)
+- use --disable-multilib on s390x
+
+* Mon Jul 30 2018 Marek Polacek 8.2.1-1.2
+- rebuild
+
+* Sat Jul 28 2018 Marek Polacek 8.2.1-1.1
+- rebuild
+
+* Fri Jul 27 2018 Marek Polacek 8.2.1-1
+- enable annobin annotations (#1574936)
+- update from Fedora 8.2.1-1
+
+* Thu Jul 12 2018 Marek Polacek 8.1.1-5
+- update from Fedora 8.1.1-5
+
+* Wed Jun 6 2018 Marek Polacek 8.1.1-1.1
+- fix BuildRequires of python-sphinx
+
+* Thu May 3 2018 Marek Polacek 8.1.1-1
+- update from Fedora 8.1.1-1
+
+* Mon Apr 30 2018 Marek Polacek 8.0.1-0.23
+- new package