From e4bb7dc686c768f2ce26007eb3dc9b6127716b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 15:04:10 -0600 Subject: [PATCH 01/19] fix: regenerate CUDA sources per translation unit --- integration_tests/CMakeLists.txt | 1 + integration_tests/gpu_cuda_cpu_01.f90 | 16 ++++++++++++++++ integration_tests/gpu_cuda_cpu_01_mod.f90 | 22 ++++++++++++++++++++++ src/libasr/codegen/asr_to_llvm.cpp | 7 +++++-- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 integration_tests/gpu_cuda_cpu_01.f90 create mode 100644 integration_tests/gpu_cuda_cpu_01_mod.f90 diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index a4904c9bb39..6145b5ee98d 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6044,6 +6044,7 @@ RUN(NAME gpu_metal_147 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_ RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_cuda_cpu_01 LABELS gfortran llvm cuda_cpu EXTRAFILES gpu_cuda_cpu_01_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) diff --git a/integration_tests/gpu_cuda_cpu_01.f90 b/integration_tests/gpu_cuda_cpu_01.f90 new file mode 100644 index 00000000000..9becec9c72e --- /dev/null +++ b/integration_tests/gpu_cuda_cpu_01.f90 @@ -0,0 +1,16 @@ +program gpu_cuda_cpu_01 + use gpu_cuda_cpu_01_m, only: transform_t + implicit none + type(transform_t) :: t + real :: x(4), y(4) + integer :: i + x = [1.0, 2.0, 3.0, 4.0] + do concurrent (i = 1:4) + y(i) = t%apply(x(i)) + end do + if (abs(y(1) - 2.0) > 1e-6) error stop 1 + if (abs(y(2) - 4.0) > 1e-6) error stop 2 + if (abs(y(3) - 6.0) > 1e-6) error stop 3 + if (abs(y(4) - 8.0) > 1e-6) error stop 4 + print *, "ok" +end program diff --git a/integration_tests/gpu_cuda_cpu_01_mod.f90 b/integration_tests/gpu_cuda_cpu_01_mod.f90 new file mode 100644 index 00000000000..81ddf002c50 --- /dev/null +++ b/integration_tests/gpu_cuda_cpu_01_mod.f90 @@ -0,0 +1,22 @@ +module gpu_cuda_cpu_01_m + implicit none + type :: transform_t + contains + procedure :: apply => my_apply + end type + interface + elemental module function my_apply(self, x) result(y) + class(transform_t), intent(in) :: self + real, intent(in) :: x + real :: y + end function + end interface +end module + +submodule (gpu_cuda_cpu_01_m) gpu_cuda_cpu_01_s + implicit none +contains + module procedure my_apply + y = x * 2.0 + end procedure +end submodule diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 827aba04215..44ff0c1abe9 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -30123,8 +30123,11 @@ Result> asr_to_llvm(ASR::TranslationUnit_t &asr, co.gpu_metal_source = metal_res.result; } - // GPU CUDA: generate CUDA kernel source after passes have created the kernel functions - if (co.gpu_backend == "cuda" && co.gpu_cuda_source.empty()) { + // GPU CUDA: generate CUDA kernel source after passes have created the kernel functions. + // Every translation unit needs its own device source; separate compilation reuses + // CompilerOptions across files, so leaving an earlier TU's source in place would + // suppress later kernels and leave their registry empty. + if (co.gpu_backend == "cuda") { diag::Diagnostics cuda_diag; Result cuda_res = asr_to_cuda(al, asr, cuda_diag, co); if (!cuda_res.ok) { From 91ae734998d80a93c2659d14da8e7f33ccedba7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 16:37:16 -0600 Subject: [PATCH 02/19] fix: frame CUDA archive metadata --- integration_tests/CMakeLists.txt | 25 +- integration_tests/gpu_cuda_cpu_archive_01.f90 | 10 + .../gpu_cuda_cpu_archive_01_mod.f90 | 12 + src/bin/lfortran.cpp | 301 +++++++++++++++--- src/libasr/codegen/asr_to_llvm.cpp | 26 ++ 5 files changed, 324 insertions(+), 50 deletions(-) create mode 100644 integration_tests/gpu_cuda_cpu_archive_01.f90 create mode 100644 integration_tests/gpu_cuda_cpu_archive_01_mod.f90 diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 6145b5ee98d..74dc9836f72 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -59,7 +59,7 @@ elseif (NOT LFORTRAN_BACKEND AND APPLE) endif() endif() -macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES) +macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES RUN_STATIC_LIBRARY_FILES) set(fail ${${RUN_FAIL}}) set(name ${${RUN_NAME}}) set(file_name ${${RUN_FILE_NAME}}) @@ -69,6 +69,7 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXT set(copy_to_bin ${${RUN_COPY_TO_BIN}}) set(gfortran_args ${${RUN_GFORTRAN_ARGS}}) set(shared_library_files ${${RUN_SHARED_LIBRARY_FILES}}) + set(static_library_files ${${RUN_STATIC_LIBRARY_FILES}}) if (NOT name) message(FATAL_ERROR "Must specify the NAME argument") @@ -211,6 +212,11 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXT target_compile_options(${name}_lib PRIVATE $<$:${extra_args}>) target_link_libraries(${name} PRIVATE ${name}_lib) endif() + if (static_library_files) + add_library(${name}_staticlib STATIC ${static_library_files}) + target_compile_options(${name}_staticlib PRIVATE $<$:${extra_args}>) + target_link_libraries(${name} PRIVATE ${name}_staticlib) + endif() add_test(${name} ${CURRENT_BINARY_DIR}/${name}) elseif (LFORTRAN_BACKEND STREQUAL "llvm_omp") add_executable(${name} ${file_name}.f90 ${extra_files}) @@ -259,6 +265,11 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXT add_executable(${name} ${file_name}.f90 ${extra_files}) target_compile_options(${name} PUBLIC $<$:--gpu=cuda_cpu ${extra_args}>) target_link_options(${name} PUBLIC --gpu=cuda_cpu) + if (static_library_files) + add_library(${name}_staticlib STATIC ${static_library_files}) + target_compile_options(${name}_staticlib PRIVATE $<$:--gpu=cuda_cpu ${extra_args}>) + target_link_libraries(${name} PRIVATE ${name}_staticlib) + endif() add_test(${name} ${CURRENT_BINARY_DIR}/${name}) elseif (LFORTRAN_BACKEND STREQUAL "flang") add_executable(${name} ${file_name}.f90 ${extra_files}) @@ -278,6 +289,11 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXT target_compile_options(${name}_lib PRIVATE $<$:${gfortran_args}>) target_link_libraries(${name} PRIVATE ${name}_lib) endif() + if (static_library_files) + add_library(${name}_staticlib STATIC ${static_library_files}) + target_compile_options(${name}_staticlib PRIVATE $<$:${gfortran_args}>) + target_link_libraries(${name} PRIVATE ${name}_staticlib) + endif() add_test(${name} ${CURRENT_BINARY_DIR}/${name}) endif() @@ -298,7 +314,7 @@ endmacro(RUN_UTIL) macro(RUN) set(options FAIL NO_FAST NO_FAST_MATH NO_DETECT_LEAKS NO_STD_F23 NO_LLVM_GOC) set(oneValueArgs NAME FILE INCLUDE_PATH COPY_TO_BIN NUM_IMAGES) - set(multiValueArgs LABELS EXTRAFILES EXTRA_ARGS GFORTRAN_ARGS SHARED_LIBRARY_FILES) + set(multiValueArgs LABELS EXTRAFILES EXTRA_ARGS GFORTRAN_ARGS SHARED_LIBRARY_FILES STATIC_LIBRARY_FILES) cmake_parse_arguments(RUN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) set(RUN_SMOKE_NAME "${RUN_NAME}") @@ -345,9 +361,9 @@ macro(RUN) endif() set(RUN_NAME "${RUN_NAME}_FAST") list(REMOVE_ITEM RUN_LABELS gfortran) # remove gfortran from --fast test - RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES) + RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES RUN_STATIC_LIBRARY_FILES) else () - RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES) + RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_EXTRA_ARGS RUN_COPY_TO_BIN RUN_GFORTRAN_ARGS RUN_SHARED_LIBRARY_FILES RUN_STATIC_LIBRARY_FILES) endif() endmacro(RUN) @@ -6045,6 +6061,7 @@ RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_cuda_cpu_01 LABELS gfortran llvm cuda_cpu EXTRAFILES gpu_cuda_cpu_01_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) diff --git a/integration_tests/gpu_cuda_cpu_archive_01.f90 b/integration_tests/gpu_cuda_cpu_archive_01.f90 new file mode 100644 index 00000000000..4d928e92f8a --- /dev/null +++ b/integration_tests/gpu_cuda_cpu_archive_01.f90 @@ -0,0 +1,10 @@ +program gpu_cuda_cpu_archive_01 + use gpu_cuda_cpu_archive_01_m, only: twice + implicit none + real :: x(4), y(4) + x = [1.0, 2.0, 3.0, 4.0] + y = -1.0 + call twice(x, y) + if (any(y /= [2.0, 4.0, 6.0, 8.0])) error stop 1 + print *, "ok" +end program diff --git a/integration_tests/gpu_cuda_cpu_archive_01_mod.f90 b/integration_tests/gpu_cuda_cpu_archive_01_mod.f90 new file mode 100644 index 00000000000..37e5ca52eb7 --- /dev/null +++ b/integration_tests/gpu_cuda_cpu_archive_01_mod.f90 @@ -0,0 +1,12 @@ +module gpu_cuda_cpu_archive_01_m + implicit none +contains + subroutine twice(x, y) + real, intent(in) :: x(4) + real, intent(out) :: y(4) + integer :: i + do concurrent (i = 1:4) + y(i) = 2.0*x(i) + end do + end subroutine +end module diff --git a/src/bin/lfortran.cpp b/src/bin/lfortran.cpp index d53f38aede2..c28b789e280 100644 --- a/src/bin/lfortran.cpp +++ b/src/bin/lfortran.cpp @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #ifndef CLI11_HAS_FILESYSTEM #define CLI11_HAS_FILESYSTEM 0 #endif // CLI11_HAS_FILESYSTEM @@ -53,6 +55,13 @@ #include #include #include +#ifdef HAVE_LFORTRAN_LLVM +#include +#include +#include +#include +#include +#endif #include #include #include @@ -91,6 +100,7 @@ namespace { using LCompilers::endswith; using LCompilers::CompilerOptions; +using LCompilers::read_file; using LCompilers::read_file_ok; namespace lcli = LCompilers::CommandLineInterface; @@ -118,7 +128,192 @@ std::string get_system_temp_dir() std::string LFORTRAN_TEMP_DIR = get_system_temp_dir(); +bool append_cuda_sidecar( + const std::filesystem::path &sidecar_path, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + const std::string sidecar = sidecar_path.string(); + if (!seen_sidecars.insert(sidecar).second) return true; + + std::error_code ec; + if (!std::filesystem::exists(sidecar_path, ec)) { + if (ec) { + std::cerr << "Failed to inspect CUDA sidecar '" << sidecar + << "': " << ec.message() << std::endl; + return false; + } + return true; + } + if (!std::filesystem::is_regular_file(sidecar_path, ec)) { + if (ec) { + std::cerr << "Failed to inspect CUDA sidecar '" << sidecar + << "': " << ec.message() << std::endl; + } else { + std::cerr << "CUDA sidecar '" << sidecar + << "' is not a regular file" << std::endl; + } + return false; + } + + std::string sidecar_source; + if (!read_file(sidecar, sidecar_source)) { + std::cerr << "Failed to read CUDA sidecar '" << sidecar << "'" + << std::endl; + return false; + } + cuda_sources.push_back(std::move(sidecar_source)); + return true; +} + +#ifdef HAVE_LFORTRAN_LLVM +const char *cuda_source_section_name() +{ +#ifdef HAVE_LFORTRAN_MACHO + return "__lcgpu"; +#else + return ".lcompilers.gpu.cuda.source"; +#endif +} +bool append_cuda_payload( + const char *data, + size_t size, + std::vector &cuda_sources) +{ + size_t pos = 0; + while (pos < size) { + size_t end = pos; + while (end < size && data[end] != '\0') { + end++; + } + if (end == size) { + std::cerr << "Malformed CUDA metadata: missing NUL terminator" + << std::endl; + return false; + } + if (end > pos) { + cuda_sources.emplace_back(data + pos, end - pos); + } + pos = end + 1; + while (pos < size && data[pos] == '\0') { + pos++; + } + } + return true; +} + +bool append_cuda_section_from_object( + llvm::object::ObjectFile &object, + std::vector &cuda_sources, + bool &found_cuda_section) +{ + for (const auto §ion : object.sections()) { + auto section_name_or_err = section.getName(); + if (!section_name_or_err) { + std::cerr << "Failed to read CUDA section name: " + << llvm::toString(section_name_or_err.takeError()) + << std::endl; + return false; + } + if (*section_name_or_err != cuda_source_section_name()) { + continue; + } + found_cuda_section = true; + auto contents_or_err = section.getContents(); + if (!contents_or_err) { + std::cerr << "Failed to read CUDA section contents: " + << llvm::toString(contents_or_err.takeError()) + << std::endl; + return false; + } + if (!append_cuda_payload(contents_or_err->data(), + contents_or_err->size(), cuda_sources)) { + return false; + } + } + return true; +} + +bool append_cuda_source_from_input( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + auto binary_or_err = llvm::object::createBinary(input); + if (!binary_or_err) { + std::cerr << "Failed to open linker input '" << input << "': " + << llvm::toString(binary_or_err.takeError()) << std::endl; + return false; + } + bool found_cuda_section = false; + llvm::object::Binary *binary = binary_or_err->getBinary(); + if (auto *object = llvm::dyn_cast(binary)) { + if (!append_cuda_section_from_object(*object, cuda_sources, + found_cuda_section)) { + return false; + } + } else if (auto *archive = llvm::dyn_cast(binary)) { + llvm::Error err = llvm::Error::success(); + for (auto child : archive->children(err)) { + auto child_binary_or_err = child.getAsBinary(); + if (!child_binary_or_err) { + std::cerr << "Failed to open archive member binary: " + << llvm::toString(child_binary_or_err.takeError()) + << std::endl; + return false; + } + if (auto *child_object = llvm::dyn_cast( + child_binary_or_err->get())) { + bool child_found_cuda_section = false; + if (!append_cuda_section_from_object(*child_object, + cuda_sources, child_found_cuda_section)) { + return false; + } + if (!child_found_cuda_section) { + auto child_name_or_err = child.getFullName(); + if (!child_name_or_err) { + std::cerr << "Failed to read archive member name in '" + << input << "': " + << llvm::toString( + child_name_or_err.takeError()) + << std::endl; + return false; + } + if (!append_cuda_sidecar( + std::filesystem::path(input).parent_path() + / (*child_name_or_err + ".cuda.cu"), + seen_sidecars, cuda_sources)) { + return false; + } + } + found_cuda_section = found_cuda_section || child_found_cuda_section; + } + } + if (err) { + std::cerr << "Failed to read archive member list: " + << llvm::toString(std::move(err)) << std::endl; + return false; + } + } + if (!found_cuda_section) { + return append_cuda_sidecar( + std::filesystem::path(input + ".cuda.cu"), + seen_sidecars, cuda_sources); + } + return true; +} +#else +bool append_cuda_source_from_input( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + return append_cuda_sidecar( + std::filesystem::path(input + ".cuda.cu"), + seen_sidecars, cuda_sources); +} +#endif // The unique compilation ID for this invocation of the compiler. // Used in naming unique intermediate object files during both compilation modes. @@ -2239,57 +2434,66 @@ int link_executable(const std::vector &infiles, + " -framework Metal -framework Foundation"; } if (compiler_options.gpu_backend == "cuda") { - // Collect CUDA kernel source. Every object file carries the - // device source of its own translation unit in a sidecar, so - // reading all of them is what picks up a kernel that lives in - // a module compiled separately. Only a link that finds no - // sidecar at all falls back to the source this invocation - // generated. - std::string cuda_source; + // Collect CUDA kernel source from embedded object metadata. + // Each object contributes its own translation unit, and + // legacy sidecars remain as a fallback for older builds. + std::vector cuda_sources; + std::set seen_cuda_sidecars; for (auto &s : infiles) { - std::string sidecar = s + ".cuda.cu"; - std::ifstream f(sidecar); - if (f.good()) { - std::string content( - (std::istreambuf_iterator(f)), - std::istreambuf_iterator()); - cuda_source += content; + if (!append_cuda_source_from_input( + s, seen_cuda_sidecars, cuda_sources)) { + return 10; } } - if (cuda_source.empty()) { - cuda_source = compiler_options.gpu_cuda_source; + if (cuda_sources.empty()) { + cuda_sources.push_back(compiler_options.gpu_cuda_source); } - // Write CUDA kernel source to a temp .cu file - std::string cuda_kernel_src = LFORTRAN_TEMP_DIR - + "/lfortran_gpu_kernel_" + LCOMPILERS_UNIQUE_ID + ".cu"; - std::string cuda_kernel_obj = LFORTRAN_TEMP_DIR - + "/lfortran_gpu_kernel_" + LCOMPILERS_UNIQUE_ID + ".o"; - { - std::ofstream cu_out(cuda_kernel_src); - cu_out << cuda_source; - cu_out.close(); - } - // Compile the kernel .cu with the device compiler. When - // emulating, the device code is ordinary host C++, and the - // language has to be named explicitly because no host - // compiler knows the .cu suffix. The emulation is built - // without OpenMP, so the threads of a block run one after - // another and a __syncthreads() reports that it cannot be - // honoured; the device code and the runtime below have to - // agree on that, so neither is given -fopenmp. + // Write every unique CUDA fragment to a temp .cu file. Each + // translation unit compiles separately so its local + // declarations stay local and identical definitions do not + // collide when archive members are aggregated at link time. bool emulate_cpu = compiler_options.gpu_cpu_emulation; std::string runtime_include = " -I" + runtime_library_dir + "/../libasr/runtime"; std::string device_cc = compiler_options.device_compiler; - std::string cuda_kernel_cmd = device_cc + " -c -O2" - + (emulate_cpu ? runtime_include + " -x c++" : "") - + " -o " + cuda_kernel_obj + " " + cuda_kernel_src; - int cuda_err = system(cuda_kernel_cmd.c_str()); - if (cuda_err) { - std::cerr << "Failed to compile CUDA kernel: " - << cuda_kernel_cmd << std::endl; - return 10; + std::vector cuda_kernel_objs; + std::set seen_cuda_fragments; + size_t cuda_kernel_index = 0; + for (const auto &cuda_source : cuda_sources) { + if (!seen_cuda_fragments.insert(cuda_source).second) { + continue; + } + std::string cuda_kernel_src = LFORTRAN_TEMP_DIR + + "/lfortran_gpu_kernel_" + LCOMPILERS_UNIQUE_ID + + "_" + std::to_string(cuda_kernel_index) + ".cu"; + std::string cuda_kernel_obj = LFORTRAN_TEMP_DIR + + "/lfortran_gpu_kernel_" + LCOMPILERS_UNIQUE_ID + + "_" + std::to_string(cuda_kernel_index) + ".o"; + { + std::ofstream cu_out(cuda_kernel_src); + cu_out << cuda_source; + cu_out.close(); + } + // Compile the kernel .cu with the device compiler. When + // emulating, the device code is ordinary host C++, and + // the language has to be named explicitly because no host + // compiler knows the .cu suffix. The emulation is built + // without OpenMP, so the threads of a block run one after + // another and a __syncthreads() reports that it cannot be + // honoured; the device code and the runtime below have to + // agree on that, so neither is given -fopenmp. + std::string cuda_kernel_cmd = device_cc + " -c -O2" + + (emulate_cpu ? runtime_include + " -x c++" : "") + + " -o " + cuda_kernel_obj + " " + cuda_kernel_src; + int cuda_err = system(cuda_kernel_cmd.c_str()); + if (cuda_err) { + std::cerr << "Failed to compile CUDA kernel: " + << cuda_kernel_cmd << std::endl; + return 10; + } + cuda_kernel_objs.push_back(std::move(cuda_kernel_obj)); + cuda_kernel_index++; } // Compile the GPU runtime. The CPU emulation uses its own @@ -2307,7 +2511,7 @@ int link_executable(const std::vector &infiles, + (emulate_cpu ? " -x c" : "") + " -o " + cuda_runtime_obj + " " + cuda_runtime_src; - cuda_err = system(cuda_rt_cmd.c_str()); + int cuda_err = system(cuda_rt_cmd.c_str()); if (cuda_err) { std::cerr << "Failed to compile CUDA runtime: " << cuda_rt_cmd << std::endl; @@ -2328,8 +2532,10 @@ int link_executable(const std::vector &infiles, == LCompilers::Platform::macOS_ARM || compiler_options.platform == LCompilers::Platform::macOS_PowerPC; - compile_cmd += " " + cuda_kernel_obj - + " " + cuda_runtime_obj + for (auto &cuda_kernel_obj : cuda_kernel_objs) { + compile_cmd += " " + cuda_kernel_obj; + } + compile_cmd += " " + cuda_runtime_obj + (is_macos ? " -lc++" : " -lstdc++") + " -lm"; } else { // The device compiler also drives the link, since it knows @@ -2338,7 +2544,10 @@ int link_executable(const std::vector &infiles, for (auto &s : infiles) { compile_cmd += s + " "; } - compile_cmd += cuda_kernel_obj + " " + cuda_runtime_obj; + for (auto &cuda_kernel_obj : cuda_kernel_objs) { + compile_cmd += cuda_kernel_obj + " "; + } + compile_cmd += cuda_runtime_obj; compile_cmd += " -L" + base_path + " -Xlinker -rpath -Xlinker " + base_path + " -l" + runtime_lib + " -lm"; diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 44ff0c1abe9..c381e96a252 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -2534,6 +2534,29 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::appendToGlobalCtors(*module, ctor_fn, 65535); } + void emit_gpu_cuda_source_section() { + if (compiler_options.gpu_cuda_source.empty()) return; + const char *cuda_source_section_name = +#ifdef HAVE_LFORTRAN_MACHO + "__DATA,__lcgpu"; +#else + ".lcompilers.gpu.cuda.source"; +#endif + std::string framed_source = compiler_options.gpu_cuda_source; + framed_source.push_back('\0'); + llvm::ArrayType *source_type = llvm::ArrayType::get( + llvm::Type::getInt8Ty(context), + framed_source.size()); + auto *source = new llvm::GlobalVariable( + *module, source_type, true, llvm::GlobalValue::PrivateLinkage, + llvm::ConstantDataArray::getString(context, framed_source, false), + "__lcompilers_gpu_cuda_source"); + source->setSection(cuda_source_section_name); + source->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + source->setAlignment(llvm::Align(1)); + llvm::appendToCompilerUsed(*module, {source}); + } + template void visit_AllocateUtil(const T& x, ASR::expr_t* m_stat, bool realloc, ASR::expr_t* m_source = nullptr) { llvm::Value* stat_target = nullptr; @@ -30152,6 +30175,9 @@ Result> asr_to_llvm(ASR::TranslationUnit_t &asr, Error error; return error; } + if (co.gpu_backend == "cuda") { + v.emit_gpu_cuda_source_section(); + } target_config.apply_target_attributes(*v.module); std::string msg; llvm::raw_string_ostream err(msg); From 161e7a2a01655369fbf2d64e48feed5d117dc589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 17:53:11 -0600 Subject: [PATCH 03/19] fix: keep native CUDA registrar local --- integration_tests/gpu_cuda_cpu_01.f90 | 11 ++++++----- integration_tests/gpu_cuda_cpu_01_mod.f90 | 8 ++++++++ src/libasr/codegen/asr_to_cuda.cpp | 3 +++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/integration_tests/gpu_cuda_cpu_01.f90 b/integration_tests/gpu_cuda_cpu_01.f90 index 9becec9c72e..e5fd89ee8d1 100644 --- a/integration_tests/gpu_cuda_cpu_01.f90 +++ b/integration_tests/gpu_cuda_cpu_01.f90 @@ -1,16 +1,17 @@ program gpu_cuda_cpu_01 - use gpu_cuda_cpu_01_m, only: transform_t + use gpu_cuda_cpu_01_m, only: transform_t, shift_up implicit none type(transform_t) :: t real :: x(4), y(4) integer :: i x = [1.0, 2.0, 3.0, 4.0] + call shift_up(x) do concurrent (i = 1:4) y(i) = t%apply(x(i)) end do - if (abs(y(1) - 2.0) > 1e-6) error stop 1 - if (abs(y(2) - 4.0) > 1e-6) error stop 2 - if (abs(y(3) - 6.0) > 1e-6) error stop 3 - if (abs(y(4) - 8.0) > 1e-6) error stop 4 + if (abs(y(1) - 4.0) > 1e-6) error stop 1 + if (abs(y(2) - 6.0) > 1e-6) error stop 2 + if (abs(y(3) - 8.0) > 1e-6) error stop 3 + if (abs(y(4) - 10.0) > 1e-6) error stop 4 print *, "ok" end program diff --git a/integration_tests/gpu_cuda_cpu_01_mod.f90 b/integration_tests/gpu_cuda_cpu_01_mod.f90 index 81ddf002c50..d8919e49910 100644 --- a/integration_tests/gpu_cuda_cpu_01_mod.f90 +++ b/integration_tests/gpu_cuda_cpu_01_mod.f90 @@ -11,6 +11,14 @@ elemental module function my_apply(self, x) result(y) real :: y end function end interface +contains + subroutine shift_up(x) + real, intent(inout) :: x(4) + integer :: i + do concurrent (i = 1:4) + x(i) = x(i) + 1.0 + end do + end subroutine end module submodule (gpu_cuda_cpu_01_m) gpu_cuda_cpu_01_s diff --git a/src/libasr/codegen/asr_to_cuda.cpp b/src/libasr/codegen/asr_to_cuda.cpp index 57c46cc8146..718ba9bc2a4 100644 --- a/src/libasr/codegen/asr_to_cuda.cpp +++ b/src/libasr/codegen/asr_to_cuda.cpp @@ -182,9 +182,11 @@ struct CudaDialect { src << "}\n"; return; } + if (kernel_names.empty()) return; src << "typedef void (*kernel_func_t)(void);\n"; src << "extern \"C\" void lfortran_gpu_register_kernel(" "const char *name, kernel_func_t func);\n\n"; + src << "namespace {\n"; src << "struct _lfortran_cuda_registrar {\n"; src << " _lfortran_cuda_registrar() {\n"; for (auto &kname : kernel_names) { @@ -193,6 +195,7 @@ struct CudaDialect { } src << " }\n"; src << "} _lfortran_cuda_reg;\n"; + src << "}\n"; } }; From ac9c757af8fdbf617d0b75b8c8b176d43c9a8d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 17:53:16 -0600 Subject: [PATCH 04/19] fix: resolve CUDA archive libraries before source collection --- integration_tests/CMakeLists.txt | 2 +- .../gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu | 1 + src/bin/lfortran.cpp | 97 +++++++++++++++---- 3 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 74dc9836f72..d71f23a5b46 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6061,7 +6061,7 @@ RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_cuda_cpu_01 LABELS gfortran llvm cuda_cpu EXTRAFILES gpu_cuda_cpu_01_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 COPY_TO_BIN gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) diff --git a/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu b/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu new file mode 100644 index 00000000000..1c8f3a3ba6a --- /dev/null +++ b/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu @@ -0,0 +1 @@ +#error unexpected archive-member sidecar was selected instead of archive metadata diff --git a/src/bin/lfortran.cpp b/src/bin/lfortran.cpp index c28b789e280..7fbc3e94792 100644 --- a/src/bin/lfortran.cpp +++ b/src/bin/lfortran.cpp @@ -166,6 +166,79 @@ bool append_cuda_sidecar( return true; } +bool append_cuda_source_from_input( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources); + +bool resolve_linker_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + std::filesystem::path &resolved_path, + bool &is_static_archive) +{ + std::vector shared_suffixes; + if (platform == LCompilers::Platform::macOS_Intel || + platform == LCompilers::Platform::macOS_ARM || + platform == LCompilers::Platform::macOS_PowerPC) { + shared_suffixes = {".dylib", ".so", ".tbd"}; + } else if (platform == LCompilers::Platform::Windows) { + shared_suffixes = {".dll"}; + } else { + shared_suffixes = {".so"}; + } + const std::vector static_suffixes = + (platform == LCompilers::Platform::Windows) ? + std::vector{".lib"} : + std::vector{".a"}; + const std::string library_prefix = + (platform == LCompilers::Platform::Windows) ? "" : "lib"; + + for (const auto &dir : lib_dirs) { + const std::filesystem::path base_dir(dir); + for (const auto &suffix : shared_suffixes) { + const std::filesystem::path candidate = + base_dir / (library_prefix + library_name + suffix); + std::error_code ec; + if (std::filesystem::is_regular_file(candidate, ec) && !ec) { + resolved_path = candidate; + is_static_archive = false; + return true; + } + } + for (const auto &suffix : static_suffixes) { + const std::filesystem::path candidate = + base_dir / (library_prefix + library_name + suffix); + std::error_code ec; + if (std::filesystem::is_regular_file(candidate, ec) && !ec) { + resolved_path = candidate; + is_static_archive = true; + return true; + } + } + } + return false; +} + +bool append_cuda_source_from_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + std::filesystem::path resolved_library; + bool is_static_archive = false; + if (!resolve_linker_library(library_name, lib_dirs, platform, + resolved_library, is_static_archive)) { + return true; + } + if (!is_static_archive) return true; + return append_cuda_source_from_input(resolved_library.string(), + seen_sidecars, cuda_sources); +} + #ifdef HAVE_LFORTRAN_LLVM const char *cuda_source_section_name() { @@ -270,23 +343,6 @@ bool append_cuda_source_from_input( cuda_sources, child_found_cuda_section)) { return false; } - if (!child_found_cuda_section) { - auto child_name_or_err = child.getFullName(); - if (!child_name_or_err) { - std::cerr << "Failed to read archive member name in '" - << input << "': " - << llvm::toString( - child_name_or_err.takeError()) - << std::endl; - return false; - } - if (!append_cuda_sidecar( - std::filesystem::path(input).parent_path() - / (*child_name_or_err + ".cuda.cu"), - seen_sidecars, cuda_sources)) { - return false; - } - } found_cuda_section = found_cuda_section || child_found_cuda_section; } } @@ -2445,6 +2501,13 @@ int link_executable(const std::vector &infiles, return 10; } } + for (auto &library_name : libraries) { + if (!append_cuda_source_from_library(library_name, lib_dirs, + compiler_options.platform, seen_cuda_sidecars, + cuda_sources)) { + return 10; + } + } if (cuda_sources.empty()) { cuda_sources.push_back(compiler_options.gpu_cuda_source); } From fe16b8a096294d9c49704fabb7b28bc8d24111bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 19:11:19 -0600 Subject: [PATCH 05/19] fix: cover CUDA library selection helpers --- src/bin/CMakeLists.txt | 1 + src/bin/cuda_link_helpers.cpp | 272 +++++++++++++++++++++++++++ src/bin/cuda_link_helpers.h | 29 +++ src/bin/lfortran.cpp | 259 ++----------------------- src/lfortran/tests/CMakeLists.txt | 2 + src/tests/test_cuda_link_helpers.cpp | 80 ++++++++ 6 files changed, 396 insertions(+), 247 deletions(-) create mode 100644 src/bin/cuda_link_helpers.cpp create mode 100644 src/bin/cuda_link_helpers.h create mode 100644 src/tests/test_cuda_link_helpers.cpp diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index 9833a3998c6..2f800b69a33 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -26,6 +26,7 @@ endif() set(LFORTRAN_SRC lfortran_accessor.cpp lsp_cli.cpp + cuda_link_helpers.cpp ${LFORTRAN_SRC} ) diff --git a/src/bin/cuda_link_helpers.cpp b/src/bin/cuda_link_helpers.cpp new file mode 100644 index 00000000000..c5726a32acd --- /dev/null +++ b/src/bin/cuda_link_helpers.cpp @@ -0,0 +1,272 @@ +#include "cuda_link_helpers.h" + +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_LFORTRAN_LLVM +#include +#include +#include +#include +#include +#endif + +namespace { + +bool append_cuda_sidecar( + const std::filesystem::path &sidecar, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + if (!seen_sidecars.insert(sidecar.string()).second) { + return true; + } + std::error_code ec; + if (!std::filesystem::exists(sidecar, ec)) { + if (ec) { + std::cerr << "Failed to inspect CUDA sidecar '" << sidecar + << "': " << ec.message() << std::endl; + return false; + } + return true; + } + if (!std::filesystem::is_regular_file(sidecar, ec)) { + if (ec) { + std::cerr << "Failed to inspect CUDA sidecar '" << sidecar + << "': " << ec.message() << std::endl; + } else { + std::cerr << "CUDA sidecar '" << sidecar + << "' is not a regular file" << std::endl; + } + return false; + } + + std::string sidecar_source; + if (!LCompilers::read_file(sidecar, sidecar_source)) { + std::cerr << "Failed to read CUDA sidecar '" << sidecar << "'" + << std::endl; + return false; + } + cuda_sources.push_back(std::move(sidecar_source)); + return true; +} + +#ifdef HAVE_LFORTRAN_LLVM +const char *cuda_source_section_name() +{ +#ifdef HAVE_LFORTRAN_MACHO + return "__lcgpu"; +#else + return ".lcompilers.gpu.cuda.source"; +#endif +} + +bool append_cuda_payload( + const char *data, + size_t size, + std::vector &cuda_sources) +{ + size_t pos = 0; + while (pos < size) { + size_t end = pos; + while (end < size && data[end] != '\0') { + end++; + } + if (end == size) { + std::cerr << "Malformed CUDA metadata: missing NUL terminator" + << std::endl; + return false; + } + if (end > pos) { + cuda_sources.emplace_back(data + pos, end - pos); + } + pos = end + 1; + while (pos < size && data[pos] == '\0') { + pos++; + } + } + return true; +} + +bool append_cuda_section_from_object( + llvm::object::ObjectFile &object, + std::vector &cuda_sources, + bool &found_cuda_section) +{ + for (const auto §ion : object.sections()) { + auto section_name_or_err = section.getName(); + if (!section_name_or_err) { + std::cerr << "Failed to read CUDA section name: " + << llvm::toString(section_name_or_err.takeError()) + << std::endl; + return false; + } + if (*section_name_or_err != cuda_source_section_name()) { + continue; + } + found_cuda_section = true; + auto contents_or_err = section.getContents(); + if (!contents_or_err) { + std::cerr << "Failed to read CUDA section contents: " + << llvm::toString(contents_or_err.takeError()) + << std::endl; + return false; + } + if (!append_cuda_payload(contents_or_err->data(), + contents_or_err->size(), cuda_sources)) { + return false; + } + } + return true; +} + +bool append_cuda_source_from_input_impl( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + auto binary_or_err = llvm::object::createBinary(input); + if (!binary_or_err) { + std::cerr << "Failed to open linker input '" << input << "': " + << llvm::toString(binary_or_err.takeError()) << std::endl; + return false; + } + bool found_cuda_section = false; + llvm::object::Binary *binary = binary_or_err->getBinary(); + if (auto *object = llvm::dyn_cast(binary)) { + if (!append_cuda_section_from_object(*object, cuda_sources, + found_cuda_section)) { + return false; + } + } else if (auto *archive = llvm::dyn_cast(binary)) { + llvm::Error err = llvm::Error::success(); + for (auto child : archive->children(err)) { + auto child_binary_or_err = child.getAsBinary(); + if (!child_binary_or_err) { + std::cerr << "Failed to open archive member binary: " + << llvm::toString(child_binary_or_err.takeError()) + << std::endl; + return false; + } + if (auto *child_object = llvm::dyn_cast( + child_binary_or_err->get())) { + bool child_found_cuda_section = false; + if (!append_cuda_section_from_object(*child_object, + cuda_sources, child_found_cuda_section)) { + return false; + } + found_cuda_section = found_cuda_section || child_found_cuda_section; + } + } + if (err) { + std::cerr << "Failed to read archive member list: " + << llvm::toString(std::move(err)) << std::endl; + return false; + } + } + if (!found_cuda_section) { + return append_cuda_sidecar( + std::filesystem::path(input + ".cuda.cu"), + seen_sidecars, cuda_sources); + } + return true; +} +#else +bool append_cuda_source_from_input_impl( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + return append_cuda_sidecar( + std::filesystem::path(input + ".cuda.cu"), + seen_sidecars, cuda_sources); +} +#endif + +} // namespace + +bool append_cuda_source_from_input( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + return append_cuda_source_from_input_impl( + input, seen_sidecars, cuda_sources); +} + +bool resolve_linker_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + bool static_only, + std::filesystem::path &resolved_path, + bool &is_static_archive) +{ + std::vector shared_suffixes; + if (platform == LCompilers::Platform::macOS_Intel || + platform == LCompilers::Platform::macOS_ARM || + platform == LCompilers::Platform::macOS_PowerPC) { + shared_suffixes = {".dylib", ".so", ".tbd"}; + } else if (platform == LCompilers::Platform::Windows) { + shared_suffixes = {".dll"}; + } else { + shared_suffixes = {".so"}; + } + const std::vector static_suffixes = + (platform == LCompilers::Platform::Windows) ? + std::vector{".lib"} : + std::vector{".a"}; + const std::string library_prefix = + (platform == LCompilers::Platform::Windows) ? "" : "lib"; + + for (const auto &dir : lib_dirs) { + const std::filesystem::path base_dir(dir); + if (!static_only) { + for (const auto &suffix : shared_suffixes) { + const std::filesystem::path candidate = + base_dir / (library_prefix + library_name + suffix); + std::error_code ec; + if (std::filesystem::is_regular_file(candidate, ec) && !ec) { + resolved_path = candidate; + is_static_archive = false; + return true; + } + } + } + for (const auto &suffix : static_suffixes) { + const std::filesystem::path candidate = + base_dir / (library_prefix + library_name + suffix); + std::error_code ec; + if (std::filesystem::is_regular_file(candidate, ec) && !ec) { + resolved_path = candidate; + is_static_archive = true; + return true; + } + } + } + return false; +} + +bool append_cuda_source_from_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + bool static_only, + std::set &seen_sidecars, + std::vector &cuda_sources) +{ + std::filesystem::path resolved_library; + bool is_static_archive = false; + if (!resolve_linker_library(library_name, lib_dirs, platform, static_only, + resolved_library, is_static_archive)) { + return true; + } + if (!is_static_archive) return true; + return append_cuda_source_from_input(resolved_library.string(), + seen_sidecars, cuda_sources); +} diff --git a/src/bin/cuda_link_helpers.h b/src/bin/cuda_link_helpers.h new file mode 100644 index 00000000000..f660c54bd06 --- /dev/null +++ b/src/bin/cuda_link_helpers.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include + +#include "libasr/utils.h" + +bool resolve_linker_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + bool static_only, + std::filesystem::path &resolved_path, + bool &is_static_archive); + +bool append_cuda_source_from_library( + const std::string &library_name, + const std::vector &lib_dirs, + LCompilers::Platform platform, + bool static_only, + std::set &seen_sidecars, + std::vector &cuda_sources); + +bool append_cuda_source_from_input( + const std::string &input, + std::set &seen_sidecars, + std::vector &cuda_sources); diff --git a/src/bin/lfortran.cpp b/src/bin/lfortran.cpp index 7fbc3e94792..d03d899ca4c 100644 --- a/src/bin/lfortran.cpp +++ b/src/bin/lfortran.cpp @@ -11,6 +11,7 @@ #define CLI11_HAS_FILESYSTEM 0 #endif // CLI11_HAS_FILESYSTEM #include +#include "cuda_link_helpers.h" #include #include @@ -128,249 +129,6 @@ std::string get_system_temp_dir() std::string LFORTRAN_TEMP_DIR = get_system_temp_dir(); -bool append_cuda_sidecar( - const std::filesystem::path &sidecar_path, - std::set &seen_sidecars, - std::vector &cuda_sources) -{ - const std::string sidecar = sidecar_path.string(); - if (!seen_sidecars.insert(sidecar).second) return true; - - std::error_code ec; - if (!std::filesystem::exists(sidecar_path, ec)) { - if (ec) { - std::cerr << "Failed to inspect CUDA sidecar '" << sidecar - << "': " << ec.message() << std::endl; - return false; - } - return true; - } - if (!std::filesystem::is_regular_file(sidecar_path, ec)) { - if (ec) { - std::cerr << "Failed to inspect CUDA sidecar '" << sidecar - << "': " << ec.message() << std::endl; - } else { - std::cerr << "CUDA sidecar '" << sidecar - << "' is not a regular file" << std::endl; - } - return false; - } - - std::string sidecar_source; - if (!read_file(sidecar, sidecar_source)) { - std::cerr << "Failed to read CUDA sidecar '" << sidecar << "'" - << std::endl; - return false; - } - cuda_sources.push_back(std::move(sidecar_source)); - return true; -} - -bool append_cuda_source_from_input( - const std::string &input, - std::set &seen_sidecars, - std::vector &cuda_sources); - -bool resolve_linker_library( - const std::string &library_name, - const std::vector &lib_dirs, - LCompilers::Platform platform, - std::filesystem::path &resolved_path, - bool &is_static_archive) -{ - std::vector shared_suffixes; - if (platform == LCompilers::Platform::macOS_Intel || - platform == LCompilers::Platform::macOS_ARM || - platform == LCompilers::Platform::macOS_PowerPC) { - shared_suffixes = {".dylib", ".so", ".tbd"}; - } else if (platform == LCompilers::Platform::Windows) { - shared_suffixes = {".dll"}; - } else { - shared_suffixes = {".so"}; - } - const std::vector static_suffixes = - (platform == LCompilers::Platform::Windows) ? - std::vector{".lib"} : - std::vector{".a"}; - const std::string library_prefix = - (platform == LCompilers::Platform::Windows) ? "" : "lib"; - - for (const auto &dir : lib_dirs) { - const std::filesystem::path base_dir(dir); - for (const auto &suffix : shared_suffixes) { - const std::filesystem::path candidate = - base_dir / (library_prefix + library_name + suffix); - std::error_code ec; - if (std::filesystem::is_regular_file(candidate, ec) && !ec) { - resolved_path = candidate; - is_static_archive = false; - return true; - } - } - for (const auto &suffix : static_suffixes) { - const std::filesystem::path candidate = - base_dir / (library_prefix + library_name + suffix); - std::error_code ec; - if (std::filesystem::is_regular_file(candidate, ec) && !ec) { - resolved_path = candidate; - is_static_archive = true; - return true; - } - } - } - return false; -} - -bool append_cuda_source_from_library( - const std::string &library_name, - const std::vector &lib_dirs, - LCompilers::Platform platform, - std::set &seen_sidecars, - std::vector &cuda_sources) -{ - std::filesystem::path resolved_library; - bool is_static_archive = false; - if (!resolve_linker_library(library_name, lib_dirs, platform, - resolved_library, is_static_archive)) { - return true; - } - if (!is_static_archive) return true; - return append_cuda_source_from_input(resolved_library.string(), - seen_sidecars, cuda_sources); -} - -#ifdef HAVE_LFORTRAN_LLVM -const char *cuda_source_section_name() -{ -#ifdef HAVE_LFORTRAN_MACHO - return "__lcgpu"; -#else - return ".lcompilers.gpu.cuda.source"; -#endif -} - -bool append_cuda_payload( - const char *data, - size_t size, - std::vector &cuda_sources) -{ - size_t pos = 0; - while (pos < size) { - size_t end = pos; - while (end < size && data[end] != '\0') { - end++; - } - if (end == size) { - std::cerr << "Malformed CUDA metadata: missing NUL terminator" - << std::endl; - return false; - } - if (end > pos) { - cuda_sources.emplace_back(data + pos, end - pos); - } - pos = end + 1; - while (pos < size && data[pos] == '\0') { - pos++; - } - } - return true; -} - -bool append_cuda_section_from_object( - llvm::object::ObjectFile &object, - std::vector &cuda_sources, - bool &found_cuda_section) -{ - for (const auto §ion : object.sections()) { - auto section_name_or_err = section.getName(); - if (!section_name_or_err) { - std::cerr << "Failed to read CUDA section name: " - << llvm::toString(section_name_or_err.takeError()) - << std::endl; - return false; - } - if (*section_name_or_err != cuda_source_section_name()) { - continue; - } - found_cuda_section = true; - auto contents_or_err = section.getContents(); - if (!contents_or_err) { - std::cerr << "Failed to read CUDA section contents: " - << llvm::toString(contents_or_err.takeError()) - << std::endl; - return false; - } - if (!append_cuda_payload(contents_or_err->data(), - contents_or_err->size(), cuda_sources)) { - return false; - } - } - return true; -} - -bool append_cuda_source_from_input( - const std::string &input, - std::set &seen_sidecars, - std::vector &cuda_sources) -{ - auto binary_or_err = llvm::object::createBinary(input); - if (!binary_or_err) { - std::cerr << "Failed to open linker input '" << input << "': " - << llvm::toString(binary_or_err.takeError()) << std::endl; - return false; - } - bool found_cuda_section = false; - llvm::object::Binary *binary = binary_or_err->getBinary(); - if (auto *object = llvm::dyn_cast(binary)) { - if (!append_cuda_section_from_object(*object, cuda_sources, - found_cuda_section)) { - return false; - } - } else if (auto *archive = llvm::dyn_cast(binary)) { - llvm::Error err = llvm::Error::success(); - for (auto child : archive->children(err)) { - auto child_binary_or_err = child.getAsBinary(); - if (!child_binary_or_err) { - std::cerr << "Failed to open archive member binary: " - << llvm::toString(child_binary_or_err.takeError()) - << std::endl; - return false; - } - if (auto *child_object = llvm::dyn_cast( - child_binary_or_err->get())) { - bool child_found_cuda_section = false; - if (!append_cuda_section_from_object(*child_object, - cuda_sources, child_found_cuda_section)) { - return false; - } - found_cuda_section = found_cuda_section || child_found_cuda_section; - } - } - if (err) { - std::cerr << "Failed to read archive member list: " - << llvm::toString(std::move(err)) << std::endl; - return false; - } - } - if (!found_cuda_section) { - return append_cuda_sidecar( - std::filesystem::path(input + ".cuda.cu"), - seen_sidecars, cuda_sources); - } - return true; -} -#else -bool append_cuda_source_from_input( - const std::string &input, - std::set &seen_sidecars, - std::vector &cuda_sources) -{ - return append_cuda_sidecar( - std::filesystem::path(input + ".cuda.cu"), - seen_sidecars, cuda_sources); -} -#endif - // The unique compilation ID for this invocation of the compiler. // Used in naming unique intermediate object files during both compilation modes. const std::string LCOMPILERS_UNIQUE_ID = LCompilers::get_unique_ID(); @@ -2363,6 +2121,10 @@ int link_executable(const std::vector &infiles, std::cout << "Cannot use static_executable and shared_executable together" << std::endl; return 10; } + const bool static_library_search = static_executable + && compiler_options.platform != LCompilers::Platform::macOS_Intel + && compiler_options.platform != LCompilers::Platform::macOS_ARM + && compiler_options.platform != LCompilers::Platform::macOS_PowerPC; if (backend == Backend::llvm || backend == Backend::mlir) { std::string run_cmd = "", compile_cmd = ""; if (t == "x86_64-pc-windows-msvc") { @@ -2458,7 +2220,7 @@ int link_executable(const std::vector &infiles, if(!extra_library_flags.empty()) { compile_cmd += extra_library_flags + " "; } - compile_cmd += + " -L" + compile_cmd += " -L" + base_path + " -Wl,-rpath," + base_path; if (!extra_linker_flags.empty()) { compile_cmd += extra_linker_flags; @@ -2503,8 +2265,8 @@ int link_executable(const std::vector &infiles, } for (auto &library_name : libraries) { if (!append_cuda_source_from_library(library_name, lib_dirs, - compiler_options.platform, seen_cuda_sidecars, - cuda_sources)) { + compiler_options.platform, static_library_search, + seen_cuda_sidecars, cuda_sources)) { return 10; } } @@ -2603,7 +2365,9 @@ int link_executable(const std::vector &infiles, } else { // The device compiler also drives the link, since it knows // where its own device runtime lives. - compile_cmd = device_cc + " -o " + outfile + " "; + compile_cmd = device_cc + + (static_library_search ? " -static" : "") + + " -o " + outfile + " "; for (auto &s : infiles) { compile_cmd += s + " "; } @@ -2611,6 +2375,7 @@ int link_executable(const std::vector &infiles, compile_cmd += cuda_kernel_obj + " "; } compile_cmd += cuda_runtime_obj; + compile_cmd += extra_library_flags; compile_cmd += " -L" + base_path + " -Xlinker -rpath -Xlinker " + base_path + " -l" + runtime_lib + " -lm"; diff --git a/src/lfortran/tests/CMakeLists.txt b/src/lfortran/tests/CMakeLists.txt index cecd18e6cf8..b2d9f23ced4 100644 --- a/src/lfortran/tests/CMakeLists.txt +++ b/src/lfortran/tests/CMakeLists.txt @@ -38,6 +38,8 @@ set(SRC test_asr_text.cpp test_asr_text_parser.cpp test_gpu.cpp + ../../bin/cuda_link_helpers.cpp + ../../tests/test_cuda_link_helpers.cpp ) if (WITH_JSON) diff --git a/src/tests/test_cuda_link_helpers.cpp b/src/tests/test_cuda_link_helpers.cpp new file mode 100644 index 00000000000..8e6757c802e --- /dev/null +++ b/src/tests/test_cuda_link_helpers.cpp @@ -0,0 +1,80 @@ +#include + +#include "../bin/cuda_link_helpers.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace fs = std::filesystem; + +static void write_file(const fs::path &path, const std::string &text) +{ + std::ofstream out(path); + if (!out.is_open()) { + throw std::runtime_error("failed to open " + path.string()); + } + out << text; +} + +static void run_command(const std::string &cmd) +{ + int status = std::system(cmd.c_str()); + if (status != 0) { + throw std::runtime_error("command failed: " + cmd); + } +} + +TEST_CASE("CUDA library resolution prefers shared libraries unless static is effective") { + const fs::path workdir = "cuda_link_helper_resolve"; + fs::remove_all(workdir); + fs::create_directories(workdir); + + const fs::path so = workdir / "libformal.so"; + const fs::path archive = workdir / "libformal.a"; + write_file(so, "shared"); + write_file(archive, "archive"); + + std::filesystem::path resolved; + bool is_static_archive = false; + + REQUIRE(resolve_linker_library("formal", {workdir.string()}, + LCompilers::Platform::Linux, false, resolved, is_static_archive)); + CHECK(resolved == so); + CHECK_FALSE(is_static_archive); + + REQUIRE(resolve_linker_library("formal", {workdir.string()}, + LCompilers::Platform::Linux, true, resolved, is_static_archive)); + CHECK(resolved == archive); + CHECK(is_static_archive); + + fs::remove_all(workdir); +} + +TEST_CASE("Metadata-free archives ignore unrelated member sidecars") { + const fs::path workdir = "cuda_link_helper_archive"; + fs::remove_all(workdir); + fs::create_directories(workdir); + + const fs::path source = workdir / "plain.c"; + const fs::path object = workdir / "plain.o"; + const fs::path archive = workdir / "libplain.a"; + const fs::path ignored_sidecar = workdir / "plain.o.cuda.cu"; + write_file(source, "int plain(void) { return 7; }\n"); + run_command("cc -c " + source.string() + " -o " + object.string()); + run_command("ar rcs " + archive.string() + " " + object.string()); + write_file(ignored_sidecar, "#error unrelated member sidecar must be ignored\n"); + + std::set seen_sidecars; + std::vector cuda_sources; + REQUIRE(append_cuda_source_from_library("plain", {workdir.string()}, + LCompilers::Platform::Linux, false, seen_sidecars, cuda_sources)); + CHECK(cuda_sources.empty()); + + fs::remove_all(workdir); +} From b2f389b854b98dfd6671d0f849e06cd92e2e8368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 01:45:42 +0000 Subject: [PATCH 06/19] fix: compile CUDA device code for the target GPU architecture nvcc was run without -arch, so it built only for its default sm_75 and newer GPUs ran the kernels through driver PTX JIT. Pass -arch=native by default (nvcc falls back to its default with a warning when no GPU is present) and add --gpu-arch to select one explicitly. The flag goes on the device compiler, so the kernel, runtime and link commands agree. --- src/bin/lfortran.cpp | 11 +++++++++++ src/bin/lfortran_command_line_parser.cpp | 1 + src/libasr/utils.h | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/bin/lfortran.cpp b/src/bin/lfortran.cpp index d53f38aede2..f8450762198 100644 --- a/src/bin/lfortran.cpp +++ b/src/bin/lfortran.cpp @@ -2282,6 +2282,17 @@ int link_executable(const std::vector &infiles, std::string runtime_include = " -I" + runtime_library_dir + "/../libasr/runtime"; std::string device_cc = compiler_options.device_compiler; + if (!emulate_cpu) { + // Without an architecture nvcc builds for its oldest + // default one, which a newer GPU can run only by JIT + // compiling the embedded PTX at startup. `native` builds + // for the GPUs present, and falls back to the default + // with a warning on a machine that has none. Kernel, + // runtime and link all go through device_cc, so they + // agree on it. + device_cc += " -arch=" + (compiler_options.gpu_arch.empty() + ? std::string("native") : compiler_options.gpu_arch); + } std::string cuda_kernel_cmd = device_cc + " -c -O2" + (emulate_cpu ? runtime_include + " -x c++" : "") + " -o " + cuda_kernel_obj + " " + cuda_kernel_src; diff --git a/src/bin/lfortran_command_line_parser.cpp b/src/bin/lfortran_command_line_parser.cpp index 6d1958ed210..4278c65c165 100644 --- a/src/bin/lfortran_command_line_parser.cpp +++ b/src/bin/lfortran_command_line_parser.cpp @@ -350,6 +350,7 @@ namespace LCompilers::CommandLineInterface { app.add_option("--emcc-embed", compiler_options.emcc_embed, "Embed a given file/directory using emscripten for LLVM->WASM")->group(group_backend_codegen_options); app.add_option("--gpu", compiler_options.gpu_backend, "Enable GPU offloading for do concurrent (metal, cuda, cuda_cpu)")->capture_default_str()->group(group_backend_codegen_options); app.add_option("--device-compiler", compiler_options.device_compiler, "Toolchain driver used to compile and link GPU device code")->capture_default_str()->group(group_backend_codegen_options); + app.add_option("--gpu-arch", compiler_options.gpu_arch, "GPU architecture to compile device code for with --gpu=cuda (e.g. sm_120); defaults to the GPUs of the compiling machine")->group(group_backend_codegen_options); app.add_flag("--gpu-offload-omp-loops", compiler_options.po.gpu_offload_omp_loops, "Offload an `!$omp parallel do` loop onto the GPU as well")->group(group_backend_codegen_options); app.add_flag("--gpu-allow-cpu-fallback", compiler_options.po.gpu_allow_cpu_fallback, "Run a parallel loop that uses a construct the selected GPU does not support (real(8) on Metal, real(10) or real(16), or input/output) on the CPU with a warning instead of failing compilation")->group(group_backend_codegen_options); diff --git a/src/libasr/utils.h b/src/libasr/utils.h index ce38ccfc693..37b933588b3 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -135,6 +135,9 @@ struct CompilerOptions { bool gpu_cpu_emulation = false; // Toolchain driver used to compile and link GPU device code. std::string device_compiler = "nvcc"; + // GPU architecture the device code is compiled for, such as sm_120. + // Empty means the GPUs of the machine that compiles. + std::string gpu_arch = ""; std::string openmp_lib_dir = ""; bool lookup_name = false; bool rename_symbol = false; From 33ce46ec2302c4eeeaf48db26f8eba81cb8422ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Sun, 18 Oct 2026 19:46:27 -0600 Subject: [PATCH 07/19] fix: make formal CUDA fixtures portable --- integration_tests/CMakeLists.txt | 2 +- .../gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu | 1 - src/bin/cuda_link_helpers.cpp | 35 +++++++- src/bin/lfortran.cpp | 2 +- src/lfortran/tests/CMakeLists.txt | 14 +++ src/lfortran/tests/plain.c | 4 + src/tests/test_cuda_link_helpers.cpp | 86 ++++++++++++------- 7 files changed, 106 insertions(+), 38 deletions(-) delete mode 100644 integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu create mode 100644 src/lfortran/tests/plain.c diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index d71f23a5b46..74dc9836f72 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6061,7 +6061,7 @@ RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_cuda_cpu_01 LABELS gfortran llvm cuda_cpu EXTRAFILES gpu_cuda_cpu_01_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 COPY_TO_BIN gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) diff --git a/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu b/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu deleted file mode 100644 index 1c8f3a3ba6a..00000000000 --- a/integration_tests/gpu_cuda_cpu_archive_01_mod.f90.o.cuda.cu +++ /dev/null @@ -1 +0,0 @@ -#error unexpected archive-member sidecar was selected instead of archive metadata diff --git a/src/bin/cuda_link_helpers.cpp b/src/bin/cuda_link_helpers.cpp index c5726a32acd..d41a1895dc5 100644 --- a/src/bin/cuda_link_helpers.cpp +++ b/src/bin/cuda_link_helpers.cpp @@ -9,6 +9,7 @@ #include #ifdef HAVE_LFORTRAN_LLVM +#include #include #include #include @@ -47,7 +48,7 @@ bool append_cuda_sidecar( } std::string sidecar_source; - if (!LCompilers::read_file(sidecar, sidecar_source)) { + if (!LCompilers::read_file(sidecar.string(), sidecar_source)) { std::cerr << "Failed to read CUDA sidecar '" << sidecar << "'" << std::endl; return false; @@ -57,6 +58,34 @@ bool append_cuda_sidecar( } #ifdef HAVE_LFORTRAN_LLVM +llvm::Expected cuda_section_name( + const llvm::object::SectionRef §ion) +{ +#if LLVM_VERSION_MAJOR >= 10 + return section.getName(); +#else + llvm::StringRef name; + if (auto error = section.getName(name)) { + return llvm::errorCodeToError(error); + } + return name; +#endif +} + +llvm::Expected cuda_section_contents( + const llvm::object::SectionRef §ion) +{ +#if LLVM_VERSION_MAJOR >= 9 + return section.getContents(); +#else + llvm::StringRef contents; + if (auto error = section.getContents(contents)) { + return llvm::errorCodeToError(error); + } + return contents; +#endif +} + const char *cuda_source_section_name() { #ifdef HAVE_LFORTRAN_MACHO @@ -99,7 +128,7 @@ bool append_cuda_section_from_object( bool &found_cuda_section) { for (const auto §ion : object.sections()) { - auto section_name_or_err = section.getName(); + auto section_name_or_err = cuda_section_name(section); if (!section_name_or_err) { std::cerr << "Failed to read CUDA section name: " << llvm::toString(section_name_or_err.takeError()) @@ -110,7 +139,7 @@ bool append_cuda_section_from_object( continue; } found_cuda_section = true; - auto contents_or_err = section.getContents(); + auto contents_or_err = cuda_section_contents(section); if (!contents_or_err) { std::cerr << "Failed to read CUDA section contents: " << llvm::toString(contents_or_err.takeError()) diff --git a/src/bin/lfortran.cpp b/src/bin/lfortran.cpp index d03d899ca4c..459b5bf5058 100644 --- a/src/bin/lfortran.cpp +++ b/src/bin/lfortran.cpp @@ -2366,7 +2366,7 @@ int link_executable(const std::vector &infiles, // The device compiler also drives the link, since it knows // where its own device runtime lives. compile_cmd = device_cc - + (static_library_search ? " -static" : "") + + (static_library_search ? " -Xcompiler=-static" : "") + " -o " + outfile + " "; for (auto &s : infiles) { compile_cmd += s + " "; diff --git a/src/lfortran/tests/CMakeLists.txt b/src/lfortran/tests/CMakeLists.txt index b2d9f23ced4..069e3e42e11 100644 --- a/src/lfortran/tests/CMakeLists.txt +++ b/src/lfortran/tests/CMakeLists.txt @@ -27,6 +27,18 @@ if (NOT XEUS_LFORTRAN_WASM_BUILD) ADDTEST(test_stacktrace) endif() +add_library(cuda_link_helper_plain_fixture STATIC plain.c) +set_target_properties(cuda_link_helper_plain_fixture PROPERTIES OUTPUT_NAME plain) +set(cuda_link_helpers_fixture_header_content [=[ +#pragma once +namespace cuda_link_helpers_fixture { +inline constexpr const char plain_archive[] = R"PATH($)PATH"; +inline constexpr const char plain_member[] = "plain.c@CMAKE_C_OUTPUT_EXTENSION@"; +} +]=]) +string(CONFIGURE "${cuda_link_helpers_fixture_header_content}" cuda_link_helpers_fixture_header_content @ONLY) +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$/test_cuda_link_helpers_fixture.hpp" CONTENT "${cuda_link_helpers_fixture_header_content}") + set(SRC test_parse.cpp test_ast.cpp @@ -70,6 +82,8 @@ endif() add_executable(test_lfortran ${SRC}) target_link_libraries(test_lfortran lfortran_lib p::doctest) target_compile_definitions(test_lfortran PRIVATE LFORTRAN_PROJECT_SOURCE_DIR="${CMAKE_SOURCE_DIR}") +target_include_directories(test_lfortran PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/$") +add_dependencies(test_lfortran cuda_link_helper_plain_fixture) # The test binary never calls set_exec_path_and_mode(), so it cannot work out # where the runtime modfiles are; a test that uses an intrinsic module would # fail with "modfile was not found". Under Emscripten they are preloaded into diff --git a/src/lfortran/tests/plain.c b/src/lfortran/tests/plain.c new file mode 100644 index 00000000000..ec6c6c906c3 --- /dev/null +++ b/src/lfortran/tests/plain.c @@ -0,0 +1,4 @@ +int plain(void) +{ + return 7; +} diff --git a/src/tests/test_cuda_link_helpers.cpp b/src/tests/test_cuda_link_helpers.cpp index 8e6757c802e..8026cebede9 100644 --- a/src/tests/test_cuda_link_helpers.cpp +++ b/src/tests/test_cuda_link_helpers.cpp @@ -1,6 +1,7 @@ #include #include "../bin/cuda_link_helpers.h" +#include "test_cuda_link_helpers_fixture.hpp" #include #include @@ -8,11 +9,12 @@ #include #include #include - -#include +#include namespace fs = std::filesystem; +namespace { + static void write_file(const fs::path &path, const std::string &text) { std::ofstream out(path); @@ -22,59 +24,79 @@ static void write_file(const fs::path &path, const std::string &text) out << text; } -static void run_command(const std::string &cmd) -{ - int status = std::system(cmd.c_str()); - if (status != 0) { - throw std::runtime_error("command failed: " + cmd); +struct OwnedDirectory { + fs::path path; + + explicit OwnedDirectory(const fs::path &root, const std::string &prefix) + { + fs::create_directories(root); + for (int i = 0; i < 32; ++i) { + fs::path candidate = root / (prefix + "_" + LCompilers::get_unique_ID()); + std::error_code ec; + if (fs::create_directory(candidate, ec)) { + path = candidate; + return; + } + } + throw std::runtime_error("failed to create unique directory under " + root.string()); } -} -TEST_CASE("CUDA library resolution prefers shared libraries unless static is effective") { - const fs::path workdir = "cuda_link_helper_resolve"; - fs::remove_all(workdir); - fs::create_directories(workdir); + ~OwnedDirectory() + { + std::error_code ec; + fs::remove_all(path, ec); + } +}; + +} // namespace - const fs::path so = workdir / "libformal.so"; - const fs::path archive = workdir / "libformal.a"; +TEST_CASE("CUDA library resolution prefers shared libraries unless static is effective") +{ + OwnedDirectory workdir(fs::path(cuda_link_helpers_fixture::plain_archive).parent_path(), + "cuda_link_helper_resolve"); + + const fs::path so = workdir.path / "libformal.so"; + const fs::path archive = workdir.path / "libformal.a"; write_file(so, "shared"); write_file(archive, "archive"); std::filesystem::path resolved; bool is_static_archive = false; - REQUIRE(resolve_linker_library("formal", {workdir.string()}, + REQUIRE(resolve_linker_library("formal", {workdir.path.string()}, LCompilers::Platform::Linux, false, resolved, is_static_archive)); CHECK(resolved == so); CHECK_FALSE(is_static_archive); - REQUIRE(resolve_linker_library("formal", {workdir.string()}, + REQUIRE(resolve_linker_library("formal", {workdir.path.string()}, LCompilers::Platform::Linux, true, resolved, is_static_archive)); CHECK(resolved == archive); CHECK(is_static_archive); - - fs::remove_all(workdir); } +#ifdef HAVE_LFORTRAN_LLVM TEST_CASE("Metadata-free archives ignore unrelated member sidecars") { - const fs::path workdir = "cuda_link_helper_archive"; - fs::remove_all(workdir); - fs::create_directories(workdir); - - const fs::path source = workdir / "plain.c"; - const fs::path object = workdir / "plain.o"; - const fs::path archive = workdir / "libplain.a"; - const fs::path ignored_sidecar = workdir / "plain.o.cuda.cu"; - write_file(source, "int plain(void) { return 7; }\n"); - run_command("cc -c " + source.string() + " -o " + object.string()); - run_command("ar rcs " + archive.string() + " " + object.string()); + OwnedDirectory workdir(fs::path(cuda_link_helpers_fixture::plain_archive).parent_path(), + "cuda_link_helper_archive"); + + const fs::path archive = workdir.path / "libplain.a"; + { + std::error_code ec; + fs::copy_file(cuda_link_helpers_fixture::plain_archive, archive, ec); + if (ec) { + throw std::runtime_error("failed to copy fixture archive to " + archive.string() + + ": " + ec.message()); + } + } + + const fs::path ignored_sidecar = + workdir.path / (std::string(cuda_link_helpers_fixture::plain_member) + ".cuda.cu"); write_file(ignored_sidecar, "#error unrelated member sidecar must be ignored\n"); std::set seen_sidecars; std::vector cuda_sources; - REQUIRE(append_cuda_source_from_library("plain", {workdir.string()}, + REQUIRE(append_cuda_source_from_library("plain", {workdir.path.string()}, LCompilers::Platform::Linux, false, seen_sidecars, cuda_sources)); CHECK(cuda_sources.empty()); - - fs::remove_all(workdir); } +#endif From 54305736c17d2488f89604f1410cffa1a7be0961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:00:45 +0000 Subject: [PATCH 08/19] fix: give each CUDA translation unit a uniquely named kernel registrar Under separate compilation the per-object CUDA device sources are concatenated into one .cu file, and every one of them defined the same _lfortran_cuda_registrar struct and _lfortran_cuda_reg variable, so nvcc rejected the link. Name the registrar after the first kernel, as the cuda_cpu emulation already does, and emit none for a translation unit without kernels. Enable the cuda label on the separately compiled GPU tests that now build. --- integration_tests/CMakeLists.txt | 36 +++++++++++++++--------------- src/libasr/codegen/asr_to_cuda.cpp | 13 ++++++----- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0bc1f0a8de6..44a198626b8 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6036,24 +6036,24 @@ RUN(NAME gpu_metal_130 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_131 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_132 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_133 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_134 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_134_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_135 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_135_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_136 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_136_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_134 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_134_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_135 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_135_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_136 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_136_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_137 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_138 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_139 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_140 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_140_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_140 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_140_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_141 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_142 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_142_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_142 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_142_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_143 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_144 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_144_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_144 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_144_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_145 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_146 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_147 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_147_activation.f90 gpu_metal_147_neural_network.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_147 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_147_activation.f90 gpu_metal_147_neural_network.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_154 LABELS gfortran llvm metal cuda_cpu) @@ -6063,7 +6063,7 @@ RUN(NAME gpu_metal_157 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_158 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_159 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_160 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_161 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_161_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_161 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_161_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_162 LABELS gfortran llvm) RUN(NAME gpu_metal_163 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_164 LABELS gfortran llvm metal cuda_cpu) @@ -6172,7 +6172,7 @@ RUN(NAME gpu_metal_259 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_260 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_261 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_262 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_263 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_263_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) +RUN(NAME gpu_metal_263 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_263_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_264 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_265 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_266 LABELS gfortran llvm metal cuda_cpu) @@ -6190,10 +6190,10 @@ RUN(NAME gpu_metal_277 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc- RUN(NAME gpu_metal_278 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_279 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_280 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_281 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_281_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) +RUN(NAME gpu_metal_281 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_281_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_282 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_282_mod.f90 EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_283 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_283_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_284 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_284_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) +RUN(NAME gpu_metal_283 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_283_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) +RUN(NAME gpu_metal_284 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_284_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_285 LABELS gfortran llvm EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_286 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_287 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) @@ -6387,9 +6387,9 @@ RUN(NAME gpu_metal_375 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking rep RUN(NAME gpu_metal_359 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component that is not allocated without --realloc-lhs-arrays RUN(NAME gpu_metal_363 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component an `if` lets the loop write that is not allocated without --realloc-lhs-arrays RUN(NAME gpu_metal_364 FAIL NO_FAST NO_STD_F23 LABELS llvm metal cuda_cpu) # bounds checking reports a component the loop assigns an array to that is not allocated without --realloc-lhs-arrays; --std=f23 allocates it on assignment -RUN(NAME gpu_metal_377 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_377_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_385 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_385_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_395 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_395_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_377 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_377_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_385 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_385_mod.f90 EXTRA_ARGS --separate-compilation) +RUN(NAME gpu_metal_395 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_395_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_396 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --fast) RUN(NAME gpu_metal_397 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_398 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) @@ -6400,8 +6400,8 @@ RUN(NAME gpu_metal_402 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc- RUN(NAME gpu_metal_403 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_404 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_405 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_413 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_413_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_435 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_435_mod.f90 EXTRA_ARGS --separate-compilation $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_413 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_413_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) +RUN(NAME gpu_metal_435 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_435_mod.f90 EXTRA_ARGS --separate-compilation $<$:--gpu-allow-cpu-fallback>) RUN(NAME inline_scoped_01 LABELS gfortran llvm EXTRA_ARGS --fast) RUN(NAME inline_function_calls_01 LABELS gfortran llvm EXTRA_ARGS --fast) diff --git a/src/libasr/codegen/asr_to_cuda.cpp b/src/libasr/codegen/asr_to_cuda.cpp index 57c46cc8146..c0d7218f265 100644 --- a/src/libasr/codegen/asr_to_cuda.cpp +++ b/src/libasr/codegen/asr_to_cuda.cpp @@ -160,10 +160,9 @@ struct CudaDialect { void emit_translation_unit_epilogue(std::stringstream &src, const std::vector &kernel_names) const { - if (!emit_registrar) return; + if (!emit_registrar || kernel_names.empty()) return; src << "\n// Auto-generated kernel registration\n"; if (emulate_cpu) { - if (kernel_names.empty()) return; // The thunks are registered instead of the kernels, and a plain // constructor attribute keeps the file free of any C++ runtime // dependency. Under separate compilation the per-object device @@ -185,14 +184,18 @@ struct CudaDialect { src << "typedef void (*kernel_func_t)(void);\n"; src << "extern \"C\" void lfortran_gpu_register_kernel(" "const char *name, kernel_func_t func);\n\n"; - src << "struct _lfortran_cuda_registrar {\n"; - src << " _lfortran_cuda_registrar() {\n"; + // As above, the registrar is named after the first kernel so that + // the concatenated per-object device sources do not collide. + const std::string registrar = "_lfortran_cuda_registrar_" + + kernel_names[0]; + src << "struct " << registrar << " {\n"; + src << " " << registrar << "() {\n"; for (auto &kname : kernel_names) { src << " lfortran_gpu_register_kernel(\"" << kname << "\", (kernel_func_t)" << kname << ");\n"; } src << " }\n"; - src << "} _lfortran_cuda_reg;\n"; + src << "} " << registrar << "_instance;\n"; } }; From 6a5d5a1f8704c829c2adbb6a594ba7452e940e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:12:48 +0000 Subject: [PATCH 09/19] fix: skip a GPU launch with no threads in the CUDA runtime An empty do concurrent iteration space gives a grid with a zero extent, which cudaLaunchKernel rejects with 'invalid argument'. A launch of no threads runs nothing, so lfortran_gpu_launch now returns before copying anything in or launching when a grid or block extent is not positive. The CPU emulation runtime does the same, so a negative extent is never turned into a huge unsigned block count there either. --- integration_tests/CMakeLists.txt | 5 +-- integration_tests/gpu_metal_482.f90 | 41 +++++++++++++++++++++++ src/libasr/runtime/lfortran_gpu_cpu.c | 2 ++ src/libasr/runtime/lfortran_gpu_cuda.cu | 4 +++ src/libasr/runtime/lfortran_gpu_runtime.h | 11 ++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 integration_tests/gpu_metal_482.f90 diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0bc1f0a8de6..81b39064bc8 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6345,7 +6345,7 @@ RUN(NAME gpu_metal_442 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc- RUN(NAME gpu_metal_443 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_444 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_450 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_449 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_449 LABELS gfortran llvm metal cuda_cpu cuda) RUN(NAME gpu_metal_454 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_445 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_460 LABELS gfortran llvm metal cuda_cpu) @@ -6373,6 +6373,7 @@ RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_482 LABELS gfortran llvm metal cuda_cpu cuda) # gfortran evaluates a `do concurrent` limit twice, so gpu_metal_369 has no # gfortran label. The llvm backend and gfortran evaluate the limits of an # inner index again for every value of the outer one, so gpu_metal_370 is for @@ -6447,7 +6448,7 @@ RUN(NAME gpu_kernel_source_08 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_09 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu cuda) RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) diff --git a/integration_tests/gpu_metal_482.f90 b/integration_tests/gpu_metal_482.f90 new file mode 100644 index 00000000000..5e554606265 --- /dev/null +++ b/integration_tests/gpu_metal_482.f90 @@ -0,0 +1,41 @@ +program gpu_metal_482 + ! A `do concurrent` loop with an empty index range launches no thread: + ! the arrays it would write keep their values, also when an earlier loop + ! left them on the device, and a reduction over it keeps its initial value. + implicit none + integer :: i, n, lo + integer :: a(5) + real :: x(100), s + n = 3 + lo = 7 + + a = -1 + do concurrent (i = lo:n) + a(i) = 0 + end do + if (any(a /= -1)) error stop 1 + + do concurrent (i = 1:5) + a(i) = i + end do + do concurrent (i = lo:n) + a(i) = 0 + end do + do i = 1, 5 + if (a(i) /= i) error stop 2 + end do + + x = 1 + s = 5 + do concurrent (i = lo:n) reduce(+:s) + s = s + x(i) + end do + if (abs(s - 5) > 1e-6) error stop 3 + + s = 0 + do concurrent (i = 1:100) reduce(+:s) + s = s + x(i) + end do + if (abs(s - 100) > 1e-6) error stop 4 + print *, a, s +end program diff --git a/src/libasr/runtime/lfortran_gpu_cpu.c b/src/libasr/runtime/lfortran_gpu_cpu.c index be4f807c878..65897420fc9 100644 --- a/src/libasr/runtime/lfortran_gpu_cpu.c +++ b/src/libasr/runtime/lfortran_gpu_cpu.c @@ -206,6 +206,8 @@ void lfortran_gpu_launch(lfortran_gpu_ctx* ctx, lfortran_gpu_kernel* k, int grid[3], int block[3]) { if (!ctx || !k) return; + // As in the CUDA runtime, a launch of no threads runs nothing. + if (lfortran_gpu_launch_is_empty(grid, block)) return; // Same argument array the CUDA runtime hands to cudaLaunchKernel: every // entry points at the argument value. diff --git a/src/libasr/runtime/lfortran_gpu_cuda.cu b/src/libasr/runtime/lfortran_gpu_cuda.cu index 62125199ed5..35510ff74be 100644 --- a/src/libasr/runtime/lfortran_gpu_cuda.cu +++ b/src/libasr/runtime/lfortran_gpu_cuda.cu @@ -342,6 +342,10 @@ void lfortran_gpu_launch(lfortran_gpu_ctx* ctx, lfortran_gpu_kernel* k, int grid[3], int block[3]) { if (!ctx || !k) return; + // A launch of no threads (an empty iteration space) runs nothing, and + // CUDA rejects a grid or a block with a zero extent: there is nothing + // to copy in or launch, and the host and device copies stay as they are. + if (lfortran_gpu_launch_is_empty(grid, block)) return; for (int i = 0; i < k->n_args; i++) { if (k->kind[i] == ARG_BUFFER diff --git a/src/libasr/runtime/lfortran_gpu_runtime.h b/src/libasr/runtime/lfortran_gpu_runtime.h index b91e8c60a3f..296675276fb 100644 --- a/src/libasr/runtime/lfortran_gpu_runtime.h +++ b/src/libasr/runtime/lfortran_gpu_runtime.h @@ -26,6 +26,17 @@ static inline void lfortran_gpu_copy_kernel_name(char *dest, const char *name, dest[name_len] = '\0'; } +// Whether a launch has no threads: a grid or block extent that is not +// positive, as an empty iteration space gives. Such a launch runs nothing. +static inline int lfortran_gpu_launch_is_empty(const int grid[3], + const int block[3]) +{ + for (int i = 0; i < 3; i++) { + if (grid[i] <= 0 || block[i] <= 0) return 1; + } + return 0; +} + // The size in bytes of the device heap of a launch that allocates on the // device: the value of the environment variable LFORTRAN_GPU_HEAP_SIZE, a // number with an optional K, M or G suffix (powers of 1024), or 256 MiB when From 24efacad877cb95f4b68bf09b9aa84f9466c4718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:16:38 +0000 Subject: [PATCH 10/19] test: run the GPU tests that pass on an NVIDIA GPU with the cuda backend Only four integration tests carried the cuda label, so `integration_tests -b cuda` checked almost nothing on a machine with an NVIDIA GPU. Label the 454 cuda_cpu tests that pass with --gpu=cuda on a real GPU (RTX PRO 6000 Blackwell, sm_120). The cuda_cpu tests that still fail there are fixed and labeled separately. --- integration_tests/CMakeLists.txt | 908 +++++++++++++++---------------- 1 file changed, 454 insertions(+), 454 deletions(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0bc1f0a8de6..50e1ca9151d 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -3193,7 +3193,7 @@ RUN(NAME realloc_lhs_30 LABELS gfortran llvm RUN(NAME automatic_allocation_01 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) RUN(NAME automatic_allocation_02 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) RUN(NAME automatic_allocation_03 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) -RUN(NAME automatic_array_01 LABELS gfortran llvm cuda_cpu) +RUN(NAME automatic_array_01 LABELS gfortran llvm cuda cuda_cpu) RUN(NAME automatic_array_02 LABELS gfortran llvm) RUN(NAME block_01 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc fortran) @@ -5387,16 +5387,16 @@ RUN(NAME openmp_66 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_67 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_68 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_69 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) -RUN(NAME openmp_70 LABELS metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_71 LABELS metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_72 LABELS metal cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_70 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_71 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_72 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) RUN(NAME openmp_73 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_74 LABELS gfortran llvm) -RUN(NAME openmp_75 LABELS gfortran metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_76 LABELS gfortran metal cuda_cpu EXTRA_ARGS --openmp --gpu-offload-omp-loops GFORTRAN_ARGS -fopenmp) +RUN(NAME openmp_75 LABELS gfortran metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_76 LABELS gfortran metal cuda cuda_cpu EXTRA_ARGS --openmp --gpu-offload-omp-loops GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_77 LABELS llvm llvm_omp) RUN(NAME openmp_78 LABELS gfortran llvm llvm_omp GFORTRAN_ARGS -fopenmp) -RUN(NAME openmp_79 LABELS gfortran metal cuda_cpu llvm_omp EXTRA_ARGS --openmp) +RUN(NAME openmp_79 LABELS gfortran metal cuda cuda_cpu llvm_omp EXTRA_ARGS --openmp) RUN(NAME openmp_80 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_82 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_83 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) @@ -5903,215 +5903,215 @@ RUN(NAME coarrays_53 EXTRA_ARGS --coarray=true EXTRAFILES coarrays_53_sub.f90) # is registered below without the gpu labels until the gap is closed, and the # diagnostic is tracked by a `gpu_offload_cuda` or `gpu_offload_metal` # reference test in tests/tests.toml. -RUN(NAME gpu_metal_01 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_02 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_03 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_04 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_01 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_02 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_03 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_04 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_05 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_06 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_07 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_08 LABELS gfortran llvm metal cuda cuda_cpu) -RUN(NAME gpu_metal_09 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_10 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_11 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_12 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_13 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_14 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_15 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_16 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_17 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_18 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_19 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_20 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_21 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_22 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_23 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_24 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_25 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_26 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_27 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_28 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_29 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_30 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_31 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_32 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_33 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_34 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_35 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_36 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_37 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_38 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_39 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_40 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_41 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_42 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_43 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_44 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_45 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_46 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_47 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_48 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_49 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_50 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_51 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_52 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_53 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_54 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_55 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_56 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_57 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_58 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_59 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_09 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_10 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_11 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_12 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_13 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_14 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_15 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_16 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_17 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_18 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_19 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_20 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_21 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_22 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_23 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_24 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_25 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_26 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_27 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_28 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_29 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_30 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_31 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_32 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_33 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_34 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_35 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_36 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_37 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_38 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_39 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_40 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_41 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_42 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_43 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_44 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_45 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_46 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_47 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_48 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_49 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_50 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_51 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_52 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_53 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_54 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_55 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_56 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_57 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_58 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_59 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_60 LABELS gfortran llvm) -RUN(NAME gpu_metal_61 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_62 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_63 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_64 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_65 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_66 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_67 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_68 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_69 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_70 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_71 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_72 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_73 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_74 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_75 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_76 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_77 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_78 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_79 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_80 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_81 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_82 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_83 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_84 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_85 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_86 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_87 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_88 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_89 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_90 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_91 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_92 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_93 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_94 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_95 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_96 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_97 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_98 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_99 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_100 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_101 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_102 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_103 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_104 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_105 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_106 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_107 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_108 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_109 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_110 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_111 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_112 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_113 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_114 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_115 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_116 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_117 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_118 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_119 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_120 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_121 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_122 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_123 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_124 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_125 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_126 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_127 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_128 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_129 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_130 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_131 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_132 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_133 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_61 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_62 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_63 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_64 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_65 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_66 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_67 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_68 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_69 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_70 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_71 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_72 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_73 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_74 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_75 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_76 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_77 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_78 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_79 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_80 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_81 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_82 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_83 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_84 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_85 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_86 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_87 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_88 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_89 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_90 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_91 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_92 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_93 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_94 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_95 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_96 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_97 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_98 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_99 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_100 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_101 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_102 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_103 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_104 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_105 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_106 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_107 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_108 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_109 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_110 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_111 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_112 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_113 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_114 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_115 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_116 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_117 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_118 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_119 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_120 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_121 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_122 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_123 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_124 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_125 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_126 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_127 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_128 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_129 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_130 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_131 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_132 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_133 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_134 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_134_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_135 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_135_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_136 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_136_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_137 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_138 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_139 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_137 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_138 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_139 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_140 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_140_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_141 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_141 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_142 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_142_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_143 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_143 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_144 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_144_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_145 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_146 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_145 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_146 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_147 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_147_activation.f90 gpu_metal_147_neural_network.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_154 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_155 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_156 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_157 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_158 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_159 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_160 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_154 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_155 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_156 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_157 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_158 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_159 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_160 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_161 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_161_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_162 LABELS gfortran llvm) -RUN(NAME gpu_metal_163 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_164 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_165 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_166 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_167 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_168 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_169 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_170 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_171 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_172 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_173 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_174 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_175 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_176 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_177 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_178 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_179 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_180 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_181 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_182 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_183 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_184 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_185 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_186 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_187 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_188 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_189 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_190 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_191 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_192 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_193 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_194 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_195 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_196 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_197 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_198 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_199 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_200 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_201 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_202 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_203 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_204 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_metal_205 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_206 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_163 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_164 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_165 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_166 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_167 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_168 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_169 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_170 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_171 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_172 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_173 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_174 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_175 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_176 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_177 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_178 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_179 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_180 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_181 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_182 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_183 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_184 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_185 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_186 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_187 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_188 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_189 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_190 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_191 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_192 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_193 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_194 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_195 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_196 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_197 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_198 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_199 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_200 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_201 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_202 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_203 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_204 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_metal_205 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_206 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_207 LABELS gfortran llvm) -RUN(NAME gpu_metal_208 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_208 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda cuda_cpu) # gpu_metal_210 onward were written against the Metal path. Twelve of # them are not labelled cuda_cpu: the CUDA lowering does not yet compile # them, and labelling a test for a backend that cannot run it says nothing @@ -6119,294 +6119,294 @@ RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda_cpu) # CUDA path used to lower its logical(8) loop to a 4-byte int kernel rather # than decline it, so the label would have caught a wrong answer. It does # decline it now, and carries the label. -RUN(NAME gpu_metal_210 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_211 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_212 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_213 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_214 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_215 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_216 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_210 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_211 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_212 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_213 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_214 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_215 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_216 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_217 LABELS gfortran llvm) -RUN(NAME gpu_metal_218 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_219 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_218 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_219 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_220 LABELS gfortran llvm) -RUN(NAME gpu_metal_221 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_222 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_223 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_224 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_225 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_226 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_227 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_228 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_229 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_230 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_231 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_232 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_233 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_234 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_235 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_236 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_237 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_238 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_239 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_240 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_241 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_242 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_243 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_244 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_245 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_221 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_222 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_223 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_224 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_225 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_226 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_227 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_228 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_229 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_230 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_231 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_232 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_233 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_234 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_235 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_236 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_237 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_238 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_239 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_240 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_241 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_242 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_243 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_244 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_245 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_246 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_247 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_248 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_249 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_250 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_251 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_252 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_253 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_254 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_255 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_256 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_257 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_258 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_259 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_260 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_261 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_262 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_247 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_248 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_249 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_250 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_251 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_252 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_253 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_254 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_255 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_256 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_257 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_258 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_259 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_260 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_261 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_262 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_263 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_263_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_264 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_265 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_266 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_267 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_268 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_269 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_270 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_264 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_265 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_266 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_267 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_268 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_269 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_270 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_271 LABELS gfortran llvm) -RUN(NAME gpu_metal_272 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_272 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_273 LABELS gfortran llvm) -RUN(NAME gpu_metal_274 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_275 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_274 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_275 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_276 LABELS gfortran llvm) -RUN(NAME gpu_metal_277 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_278 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_279 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_280 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_277 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_278 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_279 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_280 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_281 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_281_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_282 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_282_mod.f90 EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_282 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_282_mod.f90 EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_283 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_283_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_284 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_284_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_285 LABELS gfortran llvm EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_286 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_287 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_288 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_289 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_290 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_291 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_metal_292 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_293 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_294 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_295 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_296 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_286 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_287 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_288 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_289 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_290 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_291 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_metal_292 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_293 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_294 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_295 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_296 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_297 LABELS gfortran llvm) -RUN(NAME gpu_metal_298 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_298 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_299 LABELS gfortran llvm) -RUN(NAME gpu_metal_300 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_300 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_301 LABELS gfortran llvm) -RUN(NAME gpu_metal_302 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_303 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_304 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_305 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_306 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_302 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_303 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_304 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_305 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_306 LABELS gfortran llvm metal cuda cuda_cpu) # Fortran 2023 `(cond ? a : b)`; no gfortran, same reason as conditional_expr_*. -RUN(NAME gpu_metal_307 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_308 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_309 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_310 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_311 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_312 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_313 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_314 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_315 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_316 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_317 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_318 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_319 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_320 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_321 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_322 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_323 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_324 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_325 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_326 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_307 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_308 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_309 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_310 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_311 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_312 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_313 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_314 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_315 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_316 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_317 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_318 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_319 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_320 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_321 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_322 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_323 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_324 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_325 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_326 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_327 LABELS gfortran llvm EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_328 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_329 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_330 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_331 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_332 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_333 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_334 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_335 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_336 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_337 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_338 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_328 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_329 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_330 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_331 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_332 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_333 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_334 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_335 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_336 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_337 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_338 LABELS gfortran llvm metal cuda cuda_cpu) # No gfortran label: `reduce` is F2023, and the gfortran the CI builds with # rejects it outright ("Syntax error in DO statement"). Same reason # gpu_metal_21 above carries none. Checked by hand against gfortran 16, # which does accept it. -RUN(NAME gpu_metal_339 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_340 LABELS llvm metal cuda_cpu EXTRA_ARGS --separate-compilation) # `shared` locality is not accepted by every supported gfortran -RUN(NAME gpu_metal_341 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_342 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_343 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_344 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_345 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_346 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_347 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_348 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_349 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_350 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_351 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_352 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_353 LABELS llvm metal cuda_cpu) # conditional expressions are not accepted by every supported gfortran -RUN(NAME gpu_metal_354 LABELS llvm metal cuda_cpu) # conditional expressions are not accepted by every supported gfortran -RUN(NAME gpu_metal_355 LABELS llvm metal cuda_cpu) # `local` locality is not accepted by every supported gfortran -RUN(NAME gpu_metal_356 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_372 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_357 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_360 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_361 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_362 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_365 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_366 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_371 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_367 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_373 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_374 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_378 LABELS llvm cuda_cpu) # integer(8) loop index is supported on cuda_cpu; metal declines integer(8); gfortran on CI lacks reduce clause -RUN(NAME gpu_metal_379 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_380 LABELS llvm metal cuda_cpu) # gfortran on CI lacks reduce clause -RUN(NAME gpu_metal_383 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_384 FAIL LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_339 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_340 LABELS llvm metal cuda cuda_cpu EXTRA_ARGS --separate-compilation) # `shared` locality is not accepted by every supported gfortran +RUN(NAME gpu_metal_341 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_342 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_343 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_344 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_345 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_346 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_347 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_348 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_349 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_350 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_351 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_352 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_353 LABELS llvm metal cuda cuda_cpu) # conditional expressions are not accepted by every supported gfortran +RUN(NAME gpu_metal_354 LABELS llvm metal cuda cuda_cpu) # conditional expressions are not accepted by every supported gfortran +RUN(NAME gpu_metal_355 LABELS llvm metal cuda cuda_cpu) # `local` locality is not accepted by every supported gfortran +RUN(NAME gpu_metal_356 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_372 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_357 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_360 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_361 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_362 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_365 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_366 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_371 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_367 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_373 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_374 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_378 LABELS llvm cuda cuda_cpu) # integer(8) loop index is supported on cuda_cpu; metal declines integer(8); gfortran on CI lacks reduce clause +RUN(NAME gpu_metal_379 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_380 LABELS llvm metal cuda cuda_cpu) # gfortran on CI lacks reduce clause +RUN(NAME gpu_metal_383 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_384 FAIL LABELS gfortran llvm metal cuda cuda_cpu) # gpu_metal_381 has a BLOCK array whose extent is known only at run time, # which a Metal shader cannot declare yet, so it has no metal label. -RUN(NAME gpu_metal_381 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_382 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_386 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_387 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_388 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_389 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_390 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_391 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_381 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_382 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_386 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_387 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_388 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_389 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_390 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_391 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_406 LABELS gfortran llvm) # the GPU backends report an error, see tests/tests.toml RUN(NAME gpu_metal_407 LABELS gfortran llvm) # the GPU backends report an error, see tests/tests.toml -RUN(NAME gpu_metal_408 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_392 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_393 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_394 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_409 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_410 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_411 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_412 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_408 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_392 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_393 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_394 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_409 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_410 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_411 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_412 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # A component whose size the host cannot work out before the loop: the # value is made on the device heap and copied out after the launch. -RUN(NAME gpu_metal_358 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_368 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_376 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_358 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_368 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_376 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # A launch that allocates more than the device heap holds stops; on the CPU # each iteration frees what it allocates, so the test is GPU-only. -RUN(NAME gpu_metal_414 FAIL LABELS metal cuda_cpu) -RUN(NAME gpu_metal_415 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_416 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays --no-array-bounds-checking) -RUN(NAME gpu_metal_419 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_420 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_417 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_418 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_421 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_422 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_423 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_424 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_425 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_426 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_427 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_428 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_429 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_430 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_431 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_432 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_433 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_434 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_436 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_437 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_438 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_439 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_440 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_441 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_442 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_443 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_444 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_450 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_414 FAIL LABELS metal cuda cuda_cpu) +RUN(NAME gpu_metal_415 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_416 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays --no-array-bounds-checking) +RUN(NAME gpu_metal_419 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_420 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_417 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_418 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_421 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_422 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_423 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_424 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_425 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_426 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_427 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_428 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_429 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_430 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_431 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_432 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_433 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_434 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_436 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_437 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_438 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_439 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_440 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_441 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_442 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_443 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_444 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_450 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_449 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_454 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_445 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_460 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_461 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_462 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_463 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_464 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_465 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_447 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_448 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_455 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_456 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_451 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_452 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_453 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_470 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_471 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_472 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_473 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_474 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_475 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_476 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_477 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_454 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_445 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_460 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_461 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_462 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_463 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_464 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_465 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_447 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_448 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_455 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_456 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_451 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_452 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_453 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_470 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_471 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_472 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_473 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_474 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_475 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_476 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_477 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda cuda_cpu) # gfortran evaluates a `do concurrent` limit twice, so gpu_metal_369 has no # gfortran label. The llvm backend and gfortran evaluate the limits of an # inner index again for every value of the outer one, so gpu_metal_370 is for # the GPU backends only. -RUN(NAME gpu_metal_369 LABELS llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_370 LABELS metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_369 LABELS llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_370 LABELS metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # Expected run-time errors on the GPU backends only. gpu_metal_359 and # gpu_metal_363 are GPU-only because the llvm backend still allocates array # components in `t(i) = f(...)` without --realloc-lhs-arrays (#9738). # gpu_metal_375 is GPU-only for the same reason as gpu_metal_363 (#9738). -RUN(NAME gpu_metal_375 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component written in both branches of an `if` that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_359 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_363 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component an `if` lets the loop write that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_364 FAIL NO_FAST NO_STD_F23 LABELS llvm metal cuda_cpu) # bounds checking reports a component the loop assigns an array to that is not allocated without --realloc-lhs-arrays; --std=f23 allocates it on assignment +RUN(NAME gpu_metal_375 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component written in both branches of an `if` that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_359 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_363 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component an `if` lets the loop write that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_364 FAIL NO_FAST NO_STD_F23 LABELS llvm metal cuda cuda_cpu) # bounds checking reports a component the loop assigns an array to that is not allocated without --realloc-lhs-arrays; --std=f23 allocates it on assignment RUN(NAME gpu_metal_377 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_377_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_385 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_385_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_395 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_395_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_396 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --fast) -RUN(NAME gpu_metal_397 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_398 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_399 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_400 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_401 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_402 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_403 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_404 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_405 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_396 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --fast) +RUN(NAME gpu_metal_397 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_398 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_399 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_400 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_401 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_402 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_403 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_404 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_405 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_413 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_413_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_435 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_435_mod.f90 EXTRA_ARGS --separate-compilation $<$:--gpu-allow-cpu-fallback>) RUN(NAME inline_scoped_01 LABELS gfortran llvm EXTRA_ARGS --fast) RUN(NAME inline_function_calls_01 LABELS gfortran llvm EXTRA_ARGS --fast) -RUN(NAME gpu_decline_01 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_decline_02 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_decline_01 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_decline_02 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_decline_03 LABELS gfortran llvm EXTRAFILES gpu_decline_03_ext.f90) RUN(NAME gpu_decline_04 LABELS gfortran llvm) RUN(NAME gpu_decline_05 LABELS gfortran llvm) @@ -6427,14 +6427,14 @@ RUN(NAME gpu_decline_16 LABELS gfortran llvm) # One program per entry of the GPU unsupported list. Each runs on the CPU with # --gpu-allow-cpu-fallback where its loop is on the list, and the error # without the flag is kept by a reference test in tests/tests.toml. -RUN(NAME gpu_unsupported_01 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_02 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_03 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_04 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_05 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_unsupported_06 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_unsupported_07 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_unsupported_08 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_unsupported_01 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_02 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_03 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_04 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_05 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_unsupported_06 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_unsupported_07 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_unsupported_08 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_01 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_02 LABELS gfortran llvm) @@ -6445,10 +6445,10 @@ RUN(NAME gpu_kernel_source_06 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_07 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_08 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_09 LABELS gfortran llvm) -RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) RUN(NAME real128_arith_02 LABELS gfortran llvm) From f1bbb3a910c0ebfc0519783e4339ff33bd58e5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:30:45 +0000 Subject: [PATCH 11/19] fix: give each GPU thread its own copy of per-iteration arrays A fixed-size array that every do concurrent iteration defines before it references it is private to the iteration (F2018 11.1.7.5), but the GPU offload pass passed it to the kernel as one buffer that every thread wrote and read. On a real GPU the last writer won (gpu_metal_246 failed with --gpu=cuda); cuda_cpu runs threads serially and hid the race. The privatizer in gpu_offload_privatize.cpp already makes such arrays locals of a BLOCK around the body, but its flow reader: - treated any ASSOCIATE construct as a read, so `t = [...]` inside an ASSOCIATE kept `t` shared; - only recognized whole-array and DO-nest definitions, so the temporary an array constructor is lowered to (`k = lbound(c, 1); c(k) = a; k = k + 1; ...`) and arrays defined element by element stayed shared. It now follows integer locals with known values and counts each element defined, allowing reads of elements already defined. Variables with LOCAL locality (`local(t)`, the region's OMPPrivate clause) were never privatized: the array stayed a shared buffer and a scalar referenced after the loop produced a kernel that did not compile. They now become BLOCK locals unconditionally, so the variable outside the loop is also unaffected, as the standard requires. A LOCAL array a thread cannot hold (e.g. of derived type) is reported as not offloadable instead of racing. gpu_metal_246 now carries the cuda label; gpu_metal_483 covers the privatized cases with n = 100000; gpu_kernel_source_14 checks through CUDA and Metal kernel references that no shared buffer is passed, which CI can observe without an NVIDIA GPU; gpu_decline_17 checks the new diagnostic. gpu_metal_474's CUDA kernel reference changes only by making an array-constant temporary thread-local. --- integration_tests/CMakeLists.txt | 5 +- integration_tests/gpu_decline_17.f90 | 27 ++ integration_tests/gpu_kernel_source_14.f90 | 44 +++ integration_tests/gpu_metal_483.f90 | 172 +++++++++ src/libasr/pass/gpu_decline.cpp | 3 + src/libasr/pass/gpu_decline.h | 3 + src/libasr/pass/gpu_offload.cpp | 6 +- src/libasr/pass/gpu_offload_privatize.cpp | 342 +++++++++++++++++- src/libasr/pass/gpu_offload_visitor.h | 17 +- ...a_kernel-gpu_kernel_source_14-ae38410.json | 13 + ...kernel-gpu_kernel_source_14-ae38410.stdout | 106 ++++++ ...gpu_cuda_kernel-gpu_metal_474-0583450.json | 2 +- ...u_cuda_kernel-gpu_metal_474-0583450.stdout | 46 +-- ...l_kernel-gpu_kernel_source_14-4e9d9d4.json | 13 + ...kernel-gpu_kernel_source_14-4e9d9d4.stdout | 201 ++++++++++ ...u_offload_cuda-gpu_decline_17-d2b52ed.json | 13 + ...offload_cuda-gpu_decline_17-d2b52ed.stderr | 9 + tests/tests.toml | 9 + 18 files changed, 987 insertions(+), 44 deletions(-) create mode 100644 integration_tests/gpu_decline_17.f90 create mode 100644 integration_tests/gpu_kernel_source_14.f90 create mode 100644 integration_tests/gpu_metal_483.f90 create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.json create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.stdout create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.json create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.stdout create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0bc1f0a8de6..a79980d4d1f 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6155,7 +6155,7 @@ RUN(NAME gpu_metal_242 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_243 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_244 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_245 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_246 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_246 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_247 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_248 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_249 LABELS gfortran llvm metal cuda_cpu) @@ -6373,6 +6373,7 @@ RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_483 LABELS gfortran llvm metal cuda cuda_cpu) # gfortran evaluates a `do concurrent` limit twice, so gpu_metal_369 has no # gfortran label. The llvm backend and gfortran evaluate the limits of an # inner index again for every value of the outer one, so gpu_metal_370 is for @@ -6423,6 +6424,7 @@ RUN(NAME gpu_decline_13 LABELS gfortran) RUN(NAME gpu_decline_14 LABELS gfortran llvm) RUN(NAME gpu_decline_15 LABELS gfortran llvm) RUN(NAME gpu_decline_16 LABELS gfortran llvm) +RUN(NAME gpu_decline_17 LABELS gfortran llvm) # One program per entry of the GPU unsupported list. Each runs on the CPU with # --gpu-allow-cpu-fallback where its loop is on the list, and the error @@ -6449,6 +6451,7 @@ RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_14 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) RUN(NAME real128_arith_02 LABELS gfortran llvm) diff --git a/integration_tests/gpu_decline_17.f90 b/integration_tests/gpu_decline_17.f90 new file mode 100644 index 00000000000..b8c959e1cb8 --- /dev/null +++ b/integration_tests/gpu_decline_17.f90 @@ -0,0 +1,27 @@ +! gpu decline reason: LocalityNotPrivate +! An array of LOCAL locality is a new array in each iteration. Each thread +! needs a copy of its own, and an array of derived type is not one a thread +! can hold as a local yet: one buffer shared by every thread would be a +! race, so the loop is not offloaded. +program gpu_decline_17 +implicit none +type :: pair + real :: a +end type +integer, parameter :: n = 1000 +real :: x(n), g(n) +type(pair) :: t(2) +integer :: j +do j = 1, n + x(j) = real(j) +end do +do concurrent (j = 1:n) local(t) + t(1)%a = x(j) + t(2)%a = 2.0 * x(j) + g(j) = t(1)%a + t(2)%a +end do +do j = 1, n + if (abs(g(j) - 3.0 * x(j)) > 1.0e-3) error stop +end do +print *, "ok" +end program diff --git a/integration_tests/gpu_kernel_source_14.f90 b/integration_tests/gpu_kernel_source_14.f90 new file mode 100644 index 00000000000..bced051822a --- /dev/null +++ b/integration_tests/gpu_kernel_source_14.f90 @@ -0,0 +1,44 @@ +program gpu_kernel_source_14 + ! Every iteration defines `t` whole before it references it, so `t` + ! is private to the iteration, and so is the temporary an array + ! constructor is lowered to. Each kernel must declare them as + ! locals of the thread, not take them as buffers every thread shares: + ! CI has no GPU that would expose the race, so the reference kernel + ! source is what checks this. The second loop names `u` in a LOCAL + ! locality specifier and defines it element by element. + implicit none + integer, parameter :: n = 8 + real :: x(n), g(4, n), t(4), u(4) + integer :: j + + do j = 1, n + x(j) = real(j) + end do + do concurrent (j = 1:n) + associate (e => 10.0 * x(j)) + t = [x(j), e, e + 1.0, e + 2.0] + g(:, j) = t + end associate + end do + do j = 1, n + if (abs(g(1, j) - x(j)) > 1.0e-5) error stop 1 + if (abs(g(2, j) - 10.0 * x(j)) > 1.0e-5) error stop 2 + if (abs(g(3, j) - (10.0 * x(j) + 1.0)) > 1.0e-5) error stop 3 + if (abs(g(4, j) - (10.0 * x(j) + 2.0)) > 1.0e-5) error stop 4 + end do + do concurrent (j = 1:n) local(u) + t = [x(j), 2.0 * x(j), 3.0 * x(j), 4.0 * x(j)] + u(1) = t(4) + u(2) = t(3) + u(3) = t(2) + u(4) = t(1) + g(:, j) = u + end do + do j = 1, n + if (abs(g(1, j) - 4.0 * x(j)) > 1.0e-5) error stop 5 + if (abs(g(2, j) - 3.0 * x(j)) > 1.0e-5) error stop 6 + if (abs(g(3, j) - 2.0 * x(j)) > 1.0e-5) error stop 7 + if (abs(g(4, j) - x(j)) > 1.0e-5) error stop 8 + end do + print *, "ok" +end program diff --git a/integration_tests/gpu_metal_483.f90 b/integration_tests/gpu_metal_483.f90 new file mode 100644 index 00000000000..ba26b1879d8 --- /dev/null +++ b/integration_tests/gpu_metal_483.f90 @@ -0,0 +1,172 @@ +module gpu_metal_483_m +! A fixed-size local array that every iteration of a DO CONCURRENT loop +! defines whole before it references it is private to the iteration +! (Fortran 2018, 11.1.7.5). On a GPU it must become a per-thread local: +! one buffer that every thread writes and reads is a race, and with many +! threads in flight the last writer wins. The loops are long enough for +! a real GPU to run them in parallel. +implicit none +contains + + ! The definition sits inside an ASSOCIATE construct. + subroutine assoc_whole(x, g, n) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + integer :: j + real :: t(4) + do concurrent (j = 1:n) + associate (e => 10.0 * x(j)) + t = [x(j), e, e + 1.0, e + 2.0] + g(:,j) = t + end associate + end do + end subroutine + + ! Nested ASSOCIATE constructs, the array defined by a DO loop. + subroutine assoc_nested(x, g, n) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + integer :: j, k + real :: t(4) + do concurrent (j = 1:n) + associate (a => x(j)) + associate (b => 2.0 * a) + do k = 1, 4 + t(k) = b + real(k) + end do + g(:,j) = t(4:1:-1) + end associate + end associate + end do + end subroutine + + ! An explicit LOCAL locality specifier. + subroutine local_spec(x, g, n) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + integer :: j + real :: t(4) + do concurrent (j = 1:n) local(t) + t = [x(j), 3.0 * x(j), 3.0 * x(j) + 1.0, 3.0 * x(j) + 2.0] + g(:,j) = t + end do + end subroutine + + ! A constructor outside any ASSOCIATE: its lowering fills a + ! temporary of the procedure element by element through a counter. + subroutine plain(x, g, n) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + integer :: j + real :: t(4) + do concurrent (j = 1:n) + t = [x(j), 4.0 * x(j), 4.0 * x(j) + 1.0, 4.0 * x(j) + 2.0] + g(:,j) = t + end do + end subroutine + + ! Every element defined one by one, later ones reading earlier ones. + subroutine elements(x, g, n) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + integer :: j + real :: t(2,2) + do concurrent (j = 1:n) + t(1,1) = x(j) + t(2,1) = 5.0 * x(j) + t(1,2) = t(2,1) + 1.0 + t(2,2) = t(1,2) + 1.0 + g(1:2,j) = t(:,1) + g(3:4,j) = t(:,2) + end do + end subroutine + + ! LOCAL locality of an array and of a scalar that are dummy + ! arguments. + subroutine local_dummies(x, g, n, t, s) + integer, intent(in) :: n + real, intent(in) :: x(n) + real, intent(out) :: g(4,n) + real, intent(inout) :: t(4), s + integer :: j + do concurrent (j = 1:n) local(t, s) + s = 6.0 * x(j) + t = [x(j), s, s + 1.0, s + 2.0] + g(:,j) = t + end do + end subroutine + +end module + +program gpu_metal_483 +use gpu_metal_483_m +implicit none +integer, parameter :: n = 100000 +real, allocatable :: x(:), g(:,:) +real :: tout(4), sout +integer :: j, k + +allocate(x(n), g(4,n)) +do j = 1, n + x(j) = real(mod(j, 997)) +end do + +g = 0.0 +call assoc_whole(x, g, n) +do j = 1, n + if (abs(g(1,j) - x(j)) > 1.0e-3) error stop "assoc_whole: element 1" + if (abs(g(2,j) - 10.0 * x(j)) > 1.0e-3) error stop "assoc_whole: element 2" + if (abs(g(3,j) - (10.0 * x(j) + 1.0)) > 1.0e-3) error stop "assoc_whole: element 3" + if (abs(g(4,j) - (10.0 * x(j) + 2.0)) > 1.0e-3) error stop "assoc_whole: element 4" +end do + +g = 0.0 +call assoc_nested(x, g, n) +do j = 1, n + do k = 1, 4 + if (abs(g(k,j) - (2.0 * x(j) + real(5 - k))) > 1.0e-3) error stop "assoc_nested" + end do +end do + +g = 0.0 +call local_spec(x, g, n) +do j = 1, n + if (abs(g(1,j) - x(j)) > 1.0e-3) error stop "local: element 1" + if (abs(g(2,j) - 3.0 * x(j)) > 1.0e-3) error stop "local: element 2" + if (abs(g(3,j) - (3.0 * x(j) + 1.0)) > 1.0e-3) error stop "local: element 3" + if (abs(g(4,j) - (3.0 * x(j) + 2.0)) > 1.0e-3) error stop "local: element 4" +end do + +g = 0.0 +call plain(x, g, n) +do j = 1, n + do k = 1, 4 + if (abs(g(k,j) - merge(x(j), 4.0 * x(j) + real(k - 2), k == 1)) > 1.0e-3) error stop "plain" + end do +end do + +g = 0.0 +call elements(x, g, n) +do j = 1, n + do k = 1, 4 + if (abs(g(k,j) - merge(x(j), 5.0 * x(j) + real(k - 2), k == 1)) > 1.0e-3) error stop "elements" + end do +end do + +g = 0.0 +tout = -1.0 +sout = -2.0 +call local_dummies(x, g, n, tout, sout) +do j = 1, n + do k = 1, 4 + if (abs(g(k,j) - merge(x(j), 6.0 * x(j) + real(k - 2), k == 1)) > 1.0e-3) error stop "local_dummies" + end do +end do + +print *, "ok" +end program diff --git a/src/libasr/pass/gpu_decline.cpp b/src/libasr/pass/gpu_decline.cpp index 14502d8d44c..b45996283e6 100644 --- a/src/libasr/pass/gpu_decline.cpp +++ b/src/libasr/pass/gpu_decline.cpp @@ -167,6 +167,9 @@ std::string gpu_decline_message(const GpuDecline &decline) { case GpuDeclineReason::UnsizedLocalArray: return "local array '" + decline.name + "' has no extent the gpu can use"; + case GpuDeclineReason::LocalityNotPrivate: + return "array '" + decline.name + "' of local locality " + "cannot be given a copy per gpu thread"; case GpuDeclineReason::AliasTemporaryRuntimeSized: return "an aliased assignment needs a run-time sized temporary"; case GpuDeclineReason::UngatherableStridedSection: diff --git a/src/libasr/pass/gpu_decline.h b/src/libasr/pass/gpu_decline.h index 298932ee847..26226fa0889 100644 --- a/src/libasr/pass/gpu_decline.h +++ b/src/libasr/pass/gpu_decline.h @@ -131,6 +131,9 @@ enum class GpuDeclineReason { // --- what the pass's own lowering cannot yet do to the body --- StructElementGather, UnsizedLocalArray, + // An array of LOCAL locality that a thread cannot hold a copy of its + // own of. + LocalityNotPrivate, AliasTemporaryRuntimeSized, UngatherableStridedSection, // A section passed to a procedure has to be copied into a contiguous diff --git a/src/libasr/pass/gpu_offload.cpp b/src/libasr/pass/gpu_offload.cpp index ea2a078f48d..facafe4d39d 100644 --- a/src/libasr/pass/gpu_offload.cpp +++ b/src/libasr/pass/gpu_offload.cpp @@ -212,8 +212,10 @@ void GpuOffloadVisitor::visit_OMPRegion(const ASR::OMPRegion_t ®ion) { resolve_enclosing_associates(work, n_dims, enclosing_assoc_map); Vec private_shapes; private_shapes.reserve(al, 4); - privatize_iteration_arrays(region, work, - enclosing_assoc_map, private_shapes); + if (!privatize_iteration_arrays(region, work, + enclosing_assoc_map, private_shapes)) { + return; + } // Detect if the do concurrent is inside a Block scope. If so, // block-local variables need to be collected as kernel parameters diff --git a/src/libasr/pass/gpu_offload_privatize.cpp b/src/libasr/pass/gpu_offload_privatize.cpp index e7c73ec77b5..2ee56e3dcbd 100644 --- a/src/libasr/pass/gpu_offload_privatize.cpp +++ b/src/libasr/pass/gpu_offload_privatize.cpp @@ -70,6 +70,13 @@ class GpuArrayAccess { return conflicts(acc, path, routine); } + // The same question asked about another variable of the procedure. + GpuArrayAccess of(ASR::symbol_t *other) { + return GpuArrayAccess(other, routine, pointers, outside); + } + + SymbolTable *procedure() const { return routine; } + private: SymbolTable *routine; const PointerTargets &pointers; @@ -202,26 +209,215 @@ class GpuArrayFlowReader { ASR::Array_t *arr; GpuArrayAccess &access; - GpuArrayFlowReader(ASR::symbol_t *sym_, GpuArrayAccess &access_) + GpuArrayFlowReader(ASR::symbol_t *sym_, GpuArrayAccess &access_, + const std::set &host_associated_) : sym(sym_), arr(ASR::down_cast( - ASRUtils::symbol_type(sym_))), access(access_) {} + ASRUtils::symbol_type(sym_))), access(access_), + host_associated(host_associated_) {} // `escaped` is set when a path may leave the run elsewhere than past // its end, by a jump out of one of its statements, wherever that // statement nests it. Such a path skips what the rest of the run // defines. GpuArrayFlow run(ASR::stmt_t **body, size_t n_body, bool &escaped) { + counters.clear(); + elements.clear(); for (size_t i = 0; i < n_body; i++) { Leaves leaves; leaves.visit_stmt(*body[i]); if (leaves.found) escaped = true; GpuArrayFlow f = stmt(body[i]); if (f != GpuArrayFlow::Untouched) return f; + count(body[i]); } return GpuArrayFlow::Untouched; } private: + const std::set &host_associated; + + // What the statements of the run read so far tell: the values of + // integer locals known at this point of it, and the elements of the + // array, by their offset in array element order, it has defined. + // A run that defines every element one by one -- the array + // constructor lowering `k = 1; t(k) = a; k = k + 1; t(k) = b; ...`, + // or `t(1) = a; t(2) = b` -- defines all of it. + std::map counters; + std::set elements; + + // An integer local that only a statement that names it can change. + bool trackable(ASR::symbol_t *s) { + if (s == sym || !ASR::is_a(*s)) return false; + ASR::Variable_t *v = ASR::down_cast(s); + return ASR::is_a(*v->m_type) + && v->m_intent == ASR::intentType::Local + && !v->m_is_volatile && v->m_common_block == nullptr + && !reachable_elsewhere(s, access.procedure()) + && host_associated.count(s) == 0; + } + + bool evaluate(ASR::expr_t *e, int64_t &v) { + if (e == nullptr) return false; + if (constant(e, v)) return true; + switch (e->type) { + case ASR::exprType::Var: { + auto it = counters.find(ASR::down_cast(e)->m_v); + if (it == counters.end()) return false; + v = it->second; + return true; + } + case ASR::exprType::ArrayBound: { + // `lbound(t, d)` of a dimension with constant bounds, as + // the array constructor lowering starts its counter. + ASR::ArrayBound_t *b = ASR::down_cast(e); + int64_t dim = 0, start = 0, length = 0; + if (!ASR::is_a(*b->m_v) || + ASR::down_cast(b->m_v)->m_v != sym || + !constant(b->m_dim, dim) || dim < 1 || + dim > (int64_t)arr->n_dims || + !constant(arr->m_dims[dim - 1].m_start, start) || + !constant(arr->m_dims[dim - 1].m_length, length)) { + return false; + } + v = b->m_bound == ASR::arrayboundType::LBound + ? start : start + length - 1; + return true; + } + case ASR::exprType::Cast: { + ASR::Cast_t *c = ASR::down_cast(e); + return c->m_kind == ASR::cast_kindType::IntegerToInteger + && evaluate(c->m_arg, v); + } + case ASR::exprType::IntegerBinOp: { + ASR::IntegerBinOp_t *b = ASR::down_cast( + e); + int64_t l = 0, r = 0; + if (!evaluate(b->m_left, l) || !evaluate(b->m_right, r)) { + return false; + } + if (b->m_op == ASR::binopType::Add) v = l + r; + else if (b->m_op == ASR::binopType::Sub) v = l - r; + else return false; + return true; + } + default: return false; + } + } + + // Follows the integer locals a statement the run went on past + // assigns. Any statement other than such an assignment, or the + // definition of an element, may change them in ways not followed + // here, and forgets them all. + void count(ASR::stmt_t *s) { + if (ASR::is_a(*s)) { + ASR::Assignment_t *a = ASR::down_cast(s); + if (a->m_overloaded == nullptr && ASR::is_a( + *a->m_target)) { + ASR::symbol_t *t = ASR::down_cast( + a->m_target)->m_v; + int64_t v = 0; + bool known = trackable(t) && evaluate(a->m_value, v); + counters.erase(t); + if (known) { + counters[t] = v; + } else if (access.of(t).expr(a->m_value)) { + counters.clear(); + } + return; + } + if (element(s, nullptr)) return; + } + counters.clear(); + } + + // Whether an element of the array, its subscripts values known here, + // is one the run has defined; `offset` is set to its position in + // array element order. + bool known_element(const ASR::ArrayItem_t &item, int64_t &offset, + bool defined) { + if (!ASR::is_a(*item.m_v) || + ASR::down_cast(item.m_v)->m_v != sym || + item.n_args != arr->n_dims) { + return false; + } + int64_t position = 0, stride = 1; + for (size_t d = 0; d < item.n_args; d++) { + const ASR::array_index_t &idx = item.m_args[d]; + int64_t start = 0, length = 0, v = 0; + if (idx.m_left || idx.m_step || + !constant(arr->m_dims[d].m_start, start) || + !constant(arr->m_dims[d].m_length, length) || + !evaluate(idx.m_right, v) || + v < start || v >= start + length) { + return false; + } + position += (v - start) * stride; + stride *= length; + } + offset = position; + return !defined || elements.count(position) > 0; + } + + // Whether `e` reads the array only through elements the run has + // defined, `t(2) + 1.0` after `t(2) = a`. + bool reads_defined(ASR::expr_t *e) { + if (!access.expr(e)) return true; + struct Reads : public ASR::BaseWalkVisitor { + GpuArrayFlowReader &r; + bool ok = true; + explicit Reads(GpuArrayFlowReader &r_) : r(r_) {} + void visit_ArrayItem(const ASR::ArrayItem_t &x) { + int64_t offset = 0; + if (ASR::is_a(*x.m_v) && + ASR::down_cast(x.m_v)->m_v == r.sym) { + ok = ok && r.known_element(x, offset, true); + return; + } + ASR::BaseWalkVisitor::visit_ArrayItem(x); + } + void visit_Var(const ASR::Var_t &x) { + if (x.m_v == r.sym) ok = false; + } + } reads(*this); + reads.visit_expr(*e); + return reads.ok; + } + + // `t(i1, ..., ir) = v`, each subscript a value known here within the + // declared bounds of its dimension, where `v` reads `t` only through + // elements defined before and names no integer local followed here. + // `offset` is set to the element's position in array element order. + bool element(ASR::stmt_t *s, int64_t *offset) { + if (!ASR::is_a(*s)) return false; + ASR::Assignment_t *a = ASR::down_cast(s); + if (a->m_overloaded != nullptr || + !ASR::is_a(*a->m_target) || + !reads_defined(a->m_value)) { + return false; + } + for (auto &c : counters) { + if (access.of(c.first).expr(a->m_value)) return false; + } + int64_t position = 0; + if (!known_element(*ASR::down_cast(a->m_target), + position, false)) { + return false; + } + if (offset) *offset = position; + return true; + } + + // The number of elements of the array, when it is a constant. + bool extent(int64_t &n) { + n = 1; + for (size_t d = 0; d < arr->n_dims; d++) { + int64_t length = 0; + if (!constant(arr->m_dims[d].m_length, length)) return false; + n *= length; + } + return true; + } + static bool constant(ASR::expr_t *e, int64_t &v) { return e != nullptr && ASRUtils::extract_value(ASRUtils::expr_value(e), v); @@ -362,8 +558,16 @@ class GpuArrayFlowReader { // early may go on past the statement that holds it without having // defined the array (`exit` of a BLOCK construct). GpuArrayFlow nested(ASR::stmt_t **body, size_t n_body) { + // The list is read on its own; what the run around it knows is + // taken up again after it. + std::map outer_counters; + std::set outer_elements; + std::swap(outer_counters, counters); + std::swap(outer_elements, elements); bool escaped = false; GpuArrayFlow f = run(body, n_body, escaped); + std::swap(outer_counters, counters); + std::swap(outer_elements, elements); return escaped && f == GpuArrayFlow::Defined ? GpuArrayFlow::Untouched : f; } @@ -399,8 +603,12 @@ class GpuArrayFlowReader { if (!access.stmt(s)) return GpuArrayFlow::Untouched; switch (s->type) { case ASR::stmtType::Assignment: { - return defines_whole(s) ? GpuArrayFlow::Defined - : GpuArrayFlow::Read; + if (defines_whole(s)) return GpuArrayFlow::Defined; + int64_t offset = 0, n = 0; + if (!element(s, &offset)) return GpuArrayFlow::Read; + elements.insert(offset); + return extent(n) && (int64_t)elements.size() == n + ? GpuArrayFlow::Defined : GpuArrayFlow::Untouched; } case ASR::stmtType::If: { ASR::If_t *x = ASR::down_cast(s); @@ -425,6 +633,22 @@ class GpuArrayFlowReader { } return nested(blk->m_body, blk->n_body); } + case ASR::stmtType::AssociateBlockCall: { + // The selectors are bound by the leading statements of + // the body, which `access` reads like any other: one that + // names the array is taken to read it. + ASR::symbol_t *b = ASRUtils::symbol_get_past_external( + ASR::down_cast(s)->m_m); + if (!ASR::is_a(*b)) { + return GpuArrayFlow::Read; + } + ASR::AssociateBlock_t *ab = + ASR::down_cast(b); + if (access.declarations(ab->m_symtab)) { + return GpuArrayFlow::Read; + } + return nested(ab->m_body, ab->n_body); + } case ASR::stmtType::DoLoop: { ASR::DoLoop_t *x = ASR::down_cast(s); if (defines_by_loops(x)) return GpuArrayFlow::Defined; @@ -606,8 +830,9 @@ bool read_after_region(GpuArrayFlowReader &reader, // // An array is only made local where that cannot be told apart: every // path through the body that accesses it first defines all of it -- by -// an assignment to the whole array, or by a nest of DO loops over its full -// declared extent -- and no statement that can run after the loop, however +// an assignment to the whole array, by a nest of DO loops over its full +// declared extent, or by assignments to each of its elements in turn, as +// the lowering of an array constructor fills its temporary -- and no statement that can run after the loop, however // a jump gets there, may read it before it is defined again. So no // iteration reads a value it did not define, whether every iteration, // some or none define the array, and nothing after the loop reads what @@ -753,7 +978,7 @@ GpuOffloadVisitor::iteration_array_candidates( } if (named_outside_body) continue; - GpuArrayFlowReader reader(sym, access); + GpuArrayFlowReader reader(sym, access, host_associated); bool escaped = false; if (reader.run(work.body, work.n_body, escaped) == GpuArrayFlow::Read) { @@ -769,15 +994,103 @@ GpuOffloadVisitor::iteration_array_candidates( return candidates; } +// A variable of LOCAL locality (the OMPPrivate clause of the canonical +// region, from `local(t)` or an OpenMP `private(t)`) is a construct +// entity: each iteration has its own, undefined on entry, and the +// variable outside the loop is not affected by it (Fortran 2018, +// 11.1.7.5). It becomes a local of the BLOCK around the body, with no +// analysis of the body. False, when an array the body names is not one +// the kernel can hold as a local of a thread: its one buffer would be +// shared by every thread. +bool GpuOffloadVisitor::locality_spec_variables( + const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, + const std::map &enclosing_assoc_map, + std::vector &local, std::string &rejected) { + std::set named; + { + VarSymbolCollector c(named); + for (size_t i = 0; i < work.n_body; i++) { + c.visit_stmt(*work.body[i]); + } + } + std::set indices; + for (size_t d = 0; d < work.n_heads(); d++) { + if (work.head(d).m_v && ASR::is_a(*work.head(d).m_v)) { + indices.insert(ASR::down_cast( + work.head(d).m_v)->m_v); + } + } + std::set in_associates; + { + VarSymbolCollector c(in_associates); + for (auto &assoc : enclosing_assoc_map) { + in_associates.insert(assoc.first); + c.visit_expr(*assoc.second); + } + } + bool inlined = gpu_associates_inlined(work.body, work.n_body, true); + for (size_t i = 0; i < region.n_clauses; i++) { + if (!ASR::is_a(*region.m_clauses[i])) continue; + ASR::OMPPrivate_t *clause = ASR::down_cast( + region.m_clauses[i]); + for (size_t k = 0; k < clause->n_vars; k++) { + if (!ASR::is_a(*clause->m_vars[k])) continue; + ASR::symbol_t *sym = ASR::down_cast( + clause->m_vars[k])->m_v; + if (!named.count(sym) || indices.count(sym) || + std::find(local.begin(), local.end(), sym) + != local.end()) { + continue; + } + bool array = ASR::is_a(*sym) && + ASRUtils::is_array(ASRUtils::symbol_type(sym)); + ASR::ttype_t *elem = ASR::is_a(*sym) + ? ASRUtils::type_get_past_array(ASRUtils::symbol_type(sym)) + : nullptr; + bool holdable = elem != nullptr && inlined && + !in_associates.count(sym) && + ASR::down_cast(sym)->n_codims == 0 && + (ASR::is_a(*elem) || + ASR::is_a(*elem) || + ASR::is_a(*elem) || + ASR::is_a(*elem)); + if (!holdable) { + // A scalar is still a local of each thread when the body + // assigns it (see visit_OMPRegion); an array is a buffer. + if (array) { + rejected = ASRUtils::symbol_name(sym); + return false; + } + continue; + } + local.push_back(sym); + } + } + return true; +} + // Locality is a correctness decision. Storage is assigned only after // shared lowering has materialized the kernel's arrays. -void GpuOffloadVisitor::privatize_iteration_arrays( +bool GpuOffloadVisitor::privatize_iteration_arrays( const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, const std::map &enclosing_assoc_map, Vec &private_shapes) { - std::vector privatized = - iteration_array_candidates(region, work, enclosing_assoc_map); - if (privatized.empty()) return; + std::vector privatized; + std::string rejected; + if (!locality_spec_variables(region, work, enclosing_assoc_map, + privatized, rejected)) { + report_not_offloaded(region.base.base.loc, + GpuDecline(GpuDeclineReason::LocalityNotPrivate, rejected)); + return false; + } + for (ASR::symbol_t *sym : iteration_array_candidates(region, work, + enclosing_assoc_map)) { + if (std::find(privatized.begin(), privatized.end(), sym) + == privatized.end()) { + privatized.push_back(sym); + } + } + if (privatized.empty()) return true; std::sort(privatized.begin(), privatized.end(), [](ASR::symbol_t *a, ASR::symbol_t *b) { return std::string(ASRUtils::symbol_name(a)) @@ -810,11 +1123,13 @@ void GpuOffloadVisitor::privatize_iteration_arrays( for (ASR::symbol_t *sym : privatized) { ASR::Variable_t *v = ASR::down_cast(sym); ASR::ttype_t *type = ASRUtils::duplicate_type(al, v->m_type); - auto *array = ASR::down_cast(type); ASRUtils::ASRBuilder b(al, v->base.base.loc); ASR::expr_t *source = ASRUtils::EXPR( ASR::make_Var_t(al, v->base.base.loc, sym)); - for (size_t d = 0; d < array->n_dims; d++) { + size_t n_dims = ASR::is_a(*type) + ? ASR::down_cast(type)->n_dims : 0; + for (size_t d = 0; d < n_dims; d++) { + auto *array = ASR::down_cast(type); auto capture = [&](ASR::expr_t *&dimension, ASR::expr_t *value) { int64_t constant_value; if (dimension && ASRUtils::extract_value( @@ -860,6 +1175,7 @@ void GpuOffloadVisitor::privatize_iteration_arrays( body.push_back(al, ASRUtils::STMT(ASR::make_BlockCall_t(al, loc, -1, block_sym))); work.set_body(body.p, body.n); + return true; } } // namespace LCompilers diff --git a/src/libasr/pass/gpu_offload_visitor.h b/src/libasr/pass/gpu_offload_visitor.h index 7c10145bc2f..4a8a3bd5585 100644 --- a/src/libasr/pass/gpu_offload_visitor.h +++ b/src/libasr/pass/gpu_offload_visitor.h @@ -548,15 +548,22 @@ class GpuOffloadVisitor : public ASR::StatementWalkVisitor void resolve_enclosing_associates(ParallelLoopNest &work, size_t n_dims, std::map &enclosing_assoc_map); - // Gives each iteration its own copy of an array of unspecified - // locality that the iteration defines whole before it references it, - // by making it a local of a BLOCK around the body (see - // gpu_offload_privatize.cpp). - void privatize_iteration_arrays(const ASR::OMPRegion_t ®ion, + // Gives each iteration its own copy of a variable of LOCAL + // locality, and of an array of unspecified locality that + // the iteration defines whole before it references it, by making it a + // local of a BLOCK around the body (see gpu_offload_privatize.cpp). + // False when the loop has been reported as one the kernel cannot run. + bool privatize_iteration_arrays(const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, const std::map &enclosing_assoc_map, Vec &private_shapes); + // The variables of LOCAL locality the body names. + bool locality_spec_variables(const ASR::OMPRegion_t ®ion, + ParallelLoopNest &work, + const std::map &enclosing_assoc_map, + std::vector &local, std::string &rejected); + // The arrays privatize_iteration_arrays may make local. std::vector iteration_array_candidates( const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.json new file mode 100644 index 00000000000..6c880404d7a --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_cuda_kernel-gpu_kernel_source_14-ae38410", + "cmd": "lfortran --no-color --gpu=cuda --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_14.f90", + "infile_hash": "57ad8288c319097f019dbae086cd1dfa65b028269532a66e5a61edeb", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_cuda_kernel-gpu_kernel_source_14-ae38410.stdout", + "stdout_hash": "92be949a202b305a6a23ea3682152c9dc840e562924b7dfb40d843c8", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.stdout new file mode 100644 index 00000000000..c793d6a1232 --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_14-ae38410.stdout @@ -0,0 +1,106 @@ +#include + +struct __ScalarArgs___lfortran_gpu_kernel_0 { + int __loop_end_0; +}; + +extern "C" __global__ void __lfortran_gpu_kernel_0( + float* g, + float* x, + __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __flat_idx; + int __gpu_elem_i; + int __gpu_sec_i; + int j; + const int n = 8; + if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); + j = (__flat_idx + 1); + { + float t[4]; + { + int __1__libasr_index_; + int __do_loop_end; + float __libasr__created__var__0__array_constructor_[4]; + float e; + __1__libasr_index_ = 1; + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = x[((int)(j) - (1))]; + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 1.00000000000000000e+01f * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = (( 1.00000000000000000e+01f * x[((int)(j) - (1))]) + 1.00000000000000000e+00f); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = (( 1.00000000000000000e+01f * x[((int)(j) - (1))]) + 2.00000000000000000e+00f); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __gpu_elem_i = (1 - 1); + while (((__gpu_elem_i + 1) <= 4)) { + __gpu_elem_i = (__gpu_elem_i + 1); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + } + __do_loop_end = ((((int)4) + ((int)1)) - 1); + __gpu_sec_i = (1 - 1); + while (((__gpu_sec_i + 1) <= __do_loop_end)) { + __gpu_sec_i = (__gpu_sec_i + 1); + g[((int)(__gpu_sec_i) - (1)) + (4 * ((int)(j) - (1)))] = t[((int)(__gpu_sec_i) - (1))]; + } + } + } +} + +struct __ScalarArgs___lfortran_gpu_kernel_1 { + int __loop_end_0; +}; + +extern "C" __global__ void __lfortran_gpu_kernel_1( + float* g, + float* x, + __ScalarArgs___lfortran_gpu_kernel_1 __scalar_args) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __1__libasr_index_; + int __flat_idx; + int __gpu_elem_i1; + int __gpu_sec_i1; + int j; + const int n = 8; + if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); + j = (__flat_idx + 1); + { + int __do_loop_end; + float __libasr__created__var__1__array_constructor_[4]; + float t[4]; + float u[4]; + __1__libasr_index_ = 1; + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = x[((int)(j) - (1))]; + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 2.00000000000000000e+00f * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 3.00000000000000000e+00f * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 4.00000000000000000e+00f * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __gpu_elem_i1 = (1 - 1); + while (((__gpu_elem_i1 + 1) <= 4)) { + __gpu_elem_i1 = (__gpu_elem_i1 + 1); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + } + u[((int)(1) - (1))] = t[((int)(4) - (1))]; + u[((int)(2) - (1))] = t[((int)(3) - (1))]; + u[((int)(3) - (1))] = t[((int)(2) - (1))]; + u[((int)(4) - (1))] = t[((int)(1) - (1))]; + __do_loop_end = ((((int)4) + ((int)1)) - 1); + __gpu_sec_i1 = (1 - 1); + while (((__gpu_sec_i1 + 1) <= __do_loop_end)) { + __gpu_sec_i1 = (__gpu_sec_i1 + 1); + g[((int)(__gpu_sec_i1) - (1)) + (4 * ((int)(j) - (1)))] = u[((int)(__gpu_sec_i1) - (1))]; + } + } +} + diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json index 817bba7c597..f453029bbfc 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_474-0583450.stdout", - "stdout_hash": "f6f0f5651c82a9a53c4edd92d61d0080479570398c0f266be86eec64", + "stdout_hash": "aeec474ccd4bb100eeaed7b040e2a86d2bb5e5f0522626859924f59d", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout index 39d38424a11..5bff8cd4e9c 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout @@ -114,40 +114,42 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( } extern "C" __global__ void __lfortran_gpu_kernel_3( - float* __libasr__created__var__0__array_constant_, float* u, float* y) { int __1_k; int __flat_idx; int __gpu_elem_i1; - int __gpu_sum_k; - float __gpu_sum_res; int j; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= 1)) { return; } __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); j = (__flat_idx + 1); - __1_k = 1; - __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 1.00000000000000000e+00f; - __1_k = 2; - __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 2.00000000000000000e+00f; - __1_k = 3; - __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 3.00000000000000000e+00f; - __1_k = 4; - __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 4.00000000000000000e+00f; - __gpu_elem_i1 = (1 - 1); - while (((__gpu_elem_i1 + 1) <= 4)) { - __gpu_elem_i1 = (__gpu_elem_i1 + 1); - u[((int)(__gpu_elem_i1) - (1))] = (__libasr__created__var__0__array_constant_[((int)(__gpu_elem_i1) - (1))] * ((float)j)); - } - __gpu_sum_res = 0.00000000000000000e+00f; - __gpu_sum_k = (1 - 1); - while (((__gpu_sum_k + 1) <= 4)) { - __gpu_sum_k = (__gpu_sum_k + 1); - __gpu_sum_res = (__gpu_sum_res + u[((int)(__gpu_sum_k) - (1))]); + { + int __gpu_sum_k; + float __gpu_sum_res; + float __libasr__created__var__0__array_constant_[4]; + __1_k = 1; + __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 1.00000000000000000e+00f; + __1_k = 2; + __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 2.00000000000000000e+00f; + __1_k = 3; + __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 3.00000000000000000e+00f; + __1_k = 4; + __libasr__created__var__0__array_constant_[((int)(__1_k) - (1))] = 4.00000000000000000e+00f; + __gpu_elem_i1 = (1 - 1); + while (((__gpu_elem_i1 + 1) <= 4)) { + __gpu_elem_i1 = (__gpu_elem_i1 + 1); + u[((int)(__gpu_elem_i1) - (1))] = (__libasr__created__var__0__array_constant_[((int)(__gpu_elem_i1) - (1))] * ((float)j)); + } + __gpu_sum_res = 0.00000000000000000e+00f; + __gpu_sum_k = (1 - 1); + while (((__gpu_sum_k + 1) <= 4)) { + __gpu_sum_k = (__gpu_sum_k + 1); + __gpu_sum_res = (__gpu_sum_res + u[((int)(__gpu_sum_k) - (1))]); + } + y[((int)(j) - (1))] = __gpu_sum_res; } - y[((int)(j) - (1))] = __gpu_sum_res; } diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.json b/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.json new file mode 100644 index 00000000000..2c03ca7d31c --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4", + "cmd": "lfortran --no-color --gpu=metal --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_14.f90", + "infile_hash": "57ad8288c319097f019dbae086cd1dfa65b028269532a66e5a61edeb", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.stdout", + "stdout_hash": "ca87fec75596f4cb9f7cf84bb3af6e421b31ff1e4d130e874bc1655b", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.stdout b/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.stdout new file mode 100644 index 00000000000..4c3b1732493 --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_14-4e9d9d4.stdout @@ -0,0 +1,201 @@ +#include +using namespace metal; + +struct __ScalarArgs___lfortran_gpu_kernel_0 { + int __loop_end_0; + int __gpu_lanes; +}; + +kernel void __lfortran_gpu_kernel_0( + device float* g [[buffer(0)]], + device float* x [[buffer(1)]], + constant __ScalarArgs___lfortran_gpu_kernel_0& __scalar_args [[buffer(2)]], + uint __gpu_grid_thread [[thread_position_in_grid]], + uint __gpu_simd_lane [[thread_index_in_simdgroup]]) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __gpu_lanes = __scalar_args.__gpu_lanes; + uint __thread_id = __gpu_grid_thread / (uint)__gpu_lanes; + int __gpu_lane = (int)(__gpu_grid_thread % (uint)__gpu_lanes); + int __flat_idx; + int __gpu_elem_i; + int __gpu_sec_i; + int j; + const int n = 8; + if ((((0 * 0) + __thread_id) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((0 * 0) + __thread_id); + j = (__flat_idx + 1); + { + float t[4]; + { + int __1__libasr_index_; + int __do_loop_end; + int __do_loop_inc; + int __gpu_loop_end; + int __gpu_loop_group; + float __libasr__created__var__0__array_constructor_[4]; + float e; + __1__libasr_index_ = 1; + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = x[((int)(j) - (1))]; + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 1.00000000000000000e+01 * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = (( 1.00000000000000000e+01 * x[((int)(j) - (1))]) + 1.00000000000000000e+00); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__0__array_constructor_[((int)(__1__libasr_index_) - (1))] = (( 1.00000000000000000e+01 * x[((int)(j) - (1))]) + 2.00000000000000000e+00); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __gpu_loop_end = 4; + __gpu_elem_i = 1; + if ((__gpu_loop_end >= 1)) { + for (__gpu_loop_group = 1; __gpu_loop_group <= (__gpu_loop_end - 15); __gpu_loop_group += 16) { + __gpu_elem_i = __gpu_loop_group; + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 1); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 2); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 3); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 4); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 5); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 6); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 7); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 8); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 9); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 10); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 11); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 12); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 13); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 14); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + __gpu_elem_i = (__gpu_loop_group + 15); + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + } + for (__gpu_elem_i = __gpu_loop_group; __gpu_elem_i <= __gpu_loop_end; __gpu_elem_i++) { + t[((int)(__gpu_elem_i) - (1))] = __libasr__created__var__0__array_constructor_[((int)(__gpu_elem_i) - (1))]; + } + } + __do_loop_end = ((((int)4) + ((int)1)) - 1); + __do_loop_inc = (1 * ((int)__gpu_lanes)); + __gpu_sec_i = ((1 + (((int)__gpu_lane) * 1)) - __do_loop_inc); + while (((int)(((int)((__do_loop_inc > 0) && ((__gpu_sec_i + __do_loop_inc) <= __do_loop_end))) || ((int)((__do_loop_inc <= 0) && ((__gpu_sec_i + __do_loop_inc) >= __do_loop_end)))))) { + __gpu_sec_i = (__gpu_sec_i + __do_loop_inc); + g[((int)(__gpu_sec_i) - (1)) + (4 * ((int)(j) - (1)))] = t[((int)(__gpu_sec_i) - (1))]; + } + if (__gpu_lanes > 1) simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); + } + } +} + +struct __ScalarArgs___lfortran_gpu_kernel_1 { + int __loop_end_0; + int __gpu_lanes; +}; + +kernel void __lfortran_gpu_kernel_1( + device float* g [[buffer(0)]], + device float* x [[buffer(1)]], + constant __ScalarArgs___lfortran_gpu_kernel_1& __scalar_args [[buffer(2)]], + uint __gpu_grid_thread [[thread_position_in_grid]], + uint __gpu_simd_lane [[thread_index_in_simdgroup]]) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __gpu_lanes = __scalar_args.__gpu_lanes; + uint __thread_id = __gpu_grid_thread / (uint)__gpu_lanes; + int __gpu_lane = (int)(__gpu_grid_thread % (uint)__gpu_lanes); + int __1__libasr_index_; + int __flat_idx; + int __gpu_elem_i1; + int __gpu_sec_i1; + int j; + const int n = 8; + if ((((0 * 0) + __thread_id) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((0 * 0) + __thread_id); + j = (__flat_idx + 1); + { + int __do_loop_end; + int __do_loop_inc; + int __gpu_loop_end; + int __gpu_loop_group; + float __libasr__created__var__1__array_constructor_[4]; + float t[4]; + float u[4]; + __1__libasr_index_ = 1; + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = x[((int)(j) - (1))]; + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 2.00000000000000000e+00 * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 3.00000000000000000e+00 * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __libasr__created__var__1__array_constructor_[((int)(__1__libasr_index_) - (1))] = ( 4.00000000000000000e+00 * x[((int)(j) - (1))]); + __1__libasr_index_ = (__1__libasr_index_ + 1); + __gpu_loop_end = 4; + __gpu_elem_i1 = 1; + if ((__gpu_loop_end >= 1)) { + for (__gpu_loop_group = 1; __gpu_loop_group <= (__gpu_loop_end - 15); __gpu_loop_group += 16) { + __gpu_elem_i1 = __gpu_loop_group; + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 1); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 2); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 3); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 4); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 5); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 6); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 7); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 8); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 9); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 10); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 11); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 12); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 13); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 14); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + __gpu_elem_i1 = (__gpu_loop_group + 15); + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + } + for (__gpu_elem_i1 = __gpu_loop_group; __gpu_elem_i1 <= __gpu_loop_end; __gpu_elem_i1++) { + t[((int)(__gpu_elem_i1) - (1))] = __libasr__created__var__1__array_constructor_[((int)(__gpu_elem_i1) - (1))]; + } + } + u[((int)(1) - (1))] = t[((int)(4) - (1))]; + u[((int)(2) - (1))] = t[((int)(3) - (1))]; + u[((int)(3) - (1))] = t[((int)(2) - (1))]; + u[((int)(4) - (1))] = t[((int)(1) - (1))]; + __do_loop_end = ((((int)4) + ((int)1)) - 1); + __do_loop_inc = (1 * ((int)__gpu_lanes)); + __gpu_sec_i1 = ((1 + (((int)__gpu_lane) * 1)) - __do_loop_inc); + while (((int)(((int)((__do_loop_inc > 0) && ((__gpu_sec_i1 + __do_loop_inc) <= __do_loop_end))) || ((int)((__do_loop_inc <= 0) && ((__gpu_sec_i1 + __do_loop_inc) >= __do_loop_end)))))) { + __gpu_sec_i1 = (__gpu_sec_i1 + __do_loop_inc); + g[((int)(__gpu_sec_i1) - (1)) + (4 * ((int)(j) - (1)))] = u[((int)(__gpu_sec_i1) - (1))]; + } + if (__gpu_lanes > 1) simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); + } +} + diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json new file mode 100644 index 00000000000..bd9c1eacaae --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_offload_cuda-gpu_decline_17-d2b52ed", + "cmd": "lfortran --no-color --gpu=cuda -c {infile} -o {outfile}", + "infile": "tests/../integration_tests/gpu_decline_17.f90", + "infile_hash": "24c5fc3990e838a979e7d6750fa390aa01898aaf71d8ad681c202ae2", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr", + "stderr_hash": "a6f51824604cdb4339b0982f40bc3c880ab84a90fc6944307fa28c40", + "returncode": 5 +} \ No newline at end of file diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr new file mode 100644 index 00000000000..da443cf2835 --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr @@ -0,0 +1,9 @@ +ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of local locality cannot be given a copy per gpu thread + --> tests/../integration_tests/gpu_decline_17.f90:18:1 - 22:6 + | +18 | do concurrent (j = 1:n) local(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... +... + | +22 | end do + | ...^^^^^^ array 't' of local locality cannot be given a copy per gpu thread diff --git a/tests/tests.toml b/tests/tests.toml index 6eaf43787bc..b23f01f0c90 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -4596,6 +4596,10 @@ gpu_offload_cuda = true filename = "../integration_tests/gpu_decline_16.f90" gpu_offload_cuda = true +[[test]] +filename = "../integration_tests/gpu_decline_17.f90" +gpu_offload_cuda = true + [[test]] filename = "gpu_decline_impure_condition.f90" gpu_offload_cuda = true @@ -4846,6 +4850,11 @@ filename = "../integration_tests/gpu_kernel_source_13.f90" gpu_metal_kernel = true gpu_cuda_kernel = true +[[test]] +filename = "../integration_tests/gpu_kernel_source_14.f90" +gpu_metal_kernel = true +gpu_cuda_kernel = true + [[test]] filename = "errors/array_bounds_check_01.f90" run = true From e569d5a0e8c3da40988e5b3c49c4c3dad2bbfa5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:33:14 +0000 Subject: [PATCH 12/19] test: restore cuda labels from #15562/#15563 dropped while merging The CMakeLists.txt conflicts of the label PRs were resolved with our side; re-add every cuda label those PRs carry. --- integration_tests/CMakeLists.txt | 908 +++++++++++++++---------------- 1 file changed, 454 insertions(+), 454 deletions(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index e592267d3ed..b4f38a6878a 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -3210,7 +3210,7 @@ RUN(NAME realloc_lhs_30 LABELS gfortran llvm RUN(NAME automatic_allocation_01 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) RUN(NAME automatic_allocation_02 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) RUN(NAME automatic_allocation_03 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc EXTRA_ARGS --std=f23) -RUN(NAME automatic_array_01 LABELS gfortran llvm cuda_cpu) +RUN(NAME automatic_array_01 LABELS gfortran llvm cuda cuda_cpu) RUN(NAME automatic_array_02 LABELS gfortran llvm) RUN(NAME automatic_array_03 LABELS gfortran llvm) @@ -5414,16 +5414,16 @@ RUN(NAME openmp_66 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_67 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_68 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_69 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) -RUN(NAME openmp_70 LABELS metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_71 LABELS metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_72 LABELS metal cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_70 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_71 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_72 LABELS metal cuda cuda_cpu EXTRA_ARGS --openmp) RUN(NAME openmp_73 LABELS llvm_omp gfortran GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_74 LABELS gfortran llvm) -RUN(NAME openmp_75 LABELS gfortran metal cuda_cpu EXTRA_ARGS --openmp) -RUN(NAME openmp_76 LABELS gfortran metal cuda_cpu EXTRA_ARGS --openmp --gpu-offload-omp-loops GFORTRAN_ARGS -fopenmp) +RUN(NAME openmp_75 LABELS gfortran metal cuda cuda_cpu EXTRA_ARGS --openmp) +RUN(NAME openmp_76 LABELS gfortran metal cuda cuda_cpu EXTRA_ARGS --openmp --gpu-offload-omp-loops GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_77 LABELS llvm llvm_omp) RUN(NAME openmp_78 LABELS gfortran llvm llvm_omp GFORTRAN_ARGS -fopenmp) -RUN(NAME openmp_79 LABELS gfortran metal cuda_cpu llvm_omp EXTRA_ARGS --openmp) +RUN(NAME openmp_79 LABELS gfortran metal cuda cuda_cpu llvm_omp EXTRA_ARGS --openmp) RUN(NAME openmp_80 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_82 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) RUN(NAME openmp_83 LABELS gfortran llvm_omp GFORTRAN_ARGS -fopenmp) @@ -5930,217 +5930,217 @@ RUN(NAME coarrays_53 EXTRA_ARGS --coarray=true EXTRAFILES coarrays_53_sub.f90) # is registered below without the gpu labels until the gap is closed, and the # diagnostic is tracked by a `gpu_offload_cuda` or `gpu_offload_metal` # reference test in tests/tests.toml. -RUN(NAME gpu_metal_01 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_02 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_03 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_04 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_01 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_02 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_03 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_04 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_05 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_06 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_07 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_08 LABELS gfortran llvm metal cuda cuda_cpu) -RUN(NAME gpu_metal_09 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_10 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_11 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_12 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_13 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_14 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_15 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_16 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_17 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_18 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_19 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_20 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_21 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_22 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_23 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_24 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_25 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_26 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_27 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_28 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_29 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_30 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_31 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_32 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_33 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_34 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_35 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_36 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_37 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_38 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_39 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_40 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_41 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_42 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_43 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_44 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_45 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_46 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_47 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_48 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_49 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_50 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_51 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_52 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_53 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_54 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_55 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_56 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_57 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_58 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_59 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_09 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_10 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_11 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_12 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_13 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_14 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_15 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_16 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_17 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_18 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_19 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_20 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_21 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_22 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_23 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_24 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_25 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_26 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_27 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_28 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_29 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_30 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_31 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_32 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_33 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_34 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_35 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_36 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_37 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_38 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_39 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_40 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_41 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_42 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_43 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_44 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_45 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_46 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_47 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_48 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_49 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_50 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_51 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_52 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_53 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_54 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_55 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_56 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_57 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_58 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_59 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_60 LABELS gfortran llvm) -RUN(NAME gpu_metal_61 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_62 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_63 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_64 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_65 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_66 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_67 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_68 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_69 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_70 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_71 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_72 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_73 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_74 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_75 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_76 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_77 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_78 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_79 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_80 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_81 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_82 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_83 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_84 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_85 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_86 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_87 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_88 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_89 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_90 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_91 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_92 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_93 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_94 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_95 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_96 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_97 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_98 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_99 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_100 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_101 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_102 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_103 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_104 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_105 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_106 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_107 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_108 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_109 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_110 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_111 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_112 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_113 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_114 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_115 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_116 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_117 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_118 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_119 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_120 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_121 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_122 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_123 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_124 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_125 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_126 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_127 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_128 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_129 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_130 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_131 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_132 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_133 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_61 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_62 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_63 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_64 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_65 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_66 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_67 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_68 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_69 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_70 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_71 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_72 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_73 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_74 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_75 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_76 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_77 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_78 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_79 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_80 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_81 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_82 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_83 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_84 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_85 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_86 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_87 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_88 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_89 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_90 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_91 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_92 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_93 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_94 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_95 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_96 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_97 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_98 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_99 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_100 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_101 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_102 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_103 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_104 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_105 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_106 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_107 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_108 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_109 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_110 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_111 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_112 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_113 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_114 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_115 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_116 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_117 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_118 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_119 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_120 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_121 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_122 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_123 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_124 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_125 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_126 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_127 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_128 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_129 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_130 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_131 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_132 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_133 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_134 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_134_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_135 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_135_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_136 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_136_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_137 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_138 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_139 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_137 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_138 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_139 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_140 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_140_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_141 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_141 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_142 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_142_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_143 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_143 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_144 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_144_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_145 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_146 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_145 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_146 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_147 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_147_activation.f90 gpu_metal_147_neural_network.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_148 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_149 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_150 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_cuda_cpu_01 LABELS gfortran llvm cuda_cpu EXTRAFILES gpu_cuda_cpu_01_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_cuda_cpu_archive_01 LABELS gfortran llvm cuda_cpu STATIC_LIBRARY_FILES gpu_cuda_cpu_archive_01_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_151 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_151_dep.f90 gpu_metal_151_net.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_154 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_155 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_156 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_157 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_158 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_159 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_160 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_152 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_153 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_154 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_155 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_156 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_157 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_158 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_159 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_160 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_161 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_161_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_162 LABELS gfortran llvm) -RUN(NAME gpu_metal_163 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_164 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_165 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_166 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_167 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_168 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_169 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_170 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_171 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_172 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_173 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_174 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_175 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_176 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_177 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_178 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_179 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_180 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_181 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_182 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_183 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_184 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_185 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_186 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_187 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_188 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_189 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_190 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_191 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_192 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_193 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_194 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_195 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_196 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_197 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_198 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_199 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_200 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_201 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_202 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_203 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_204 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_metal_205 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_206 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_163 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_164 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_165 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_166 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_167 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_168 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_169 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_170 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_171 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_172 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_173 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_174 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_175 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_176 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_177 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_178 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_179 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_180 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_181 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_182 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_183 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_184 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_185 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_186 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_187 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_188 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_189 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_190 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_191 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_192 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_193 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_194 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_195 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_196 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_197 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_198 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_199 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_200 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_201 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_202 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_203 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_204 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_metal_205 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_206 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_207 LABELS gfortran llvm) -RUN(NAME gpu_metal_208 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_208 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda cuda_cpu) # gpu_metal_210 onward were written against the Metal path. Twelve of # them are not labelled cuda_cpu: the CUDA lowering does not yet compile # them, and labelling a test for a backend that cannot run it says nothing @@ -6148,295 +6148,295 @@ RUN(NAME gpu_metal_209 LABELS gfortran llvm metal cuda_cpu) # CUDA path used to lower its logical(8) loop to a 4-byte int kernel rather # than decline it, so the label would have caught a wrong answer. It does # decline it now, and carries the label. -RUN(NAME gpu_metal_210 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_211 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_212 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_213 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_214 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_215 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_216 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_210 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_211 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_212 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_213 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_214 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_215 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_216 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_217 LABELS gfortran llvm) -RUN(NAME gpu_metal_218 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_219 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_218 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_219 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) RUN(NAME gpu_metal_220 LABELS gfortran llvm) -RUN(NAME gpu_metal_221 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_222 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_223 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_224 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_225 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_226 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_227 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_228 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_229 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_230 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_231 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_232 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_233 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_234 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_235 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_236 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_237 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_238 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_239 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_240 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_241 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_242 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_243 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_244 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_245 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_221 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_222 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_223 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_224 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_225 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_226 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_227 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_228 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_229 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_230 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_231 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_232 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_233 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_234 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_235 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_236 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_237 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_238 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_239 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_240 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_241 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_242 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_243 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_244 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_245 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_246 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_247 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_248 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_249 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_250 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_251 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_252 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_253 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_254 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_255 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_256 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_257 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_258 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_259 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_260 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_261 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_262 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_247 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_248 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_249 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_250 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_251 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_252 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_253 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_254 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_255 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_256 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_257 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_258 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_259 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_260 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_261 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_262 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_263 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_263_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_264 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_265 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_266 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_267 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_268 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_269 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_270 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_264 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_265 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_266 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_267 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_268 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_269 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_270 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_271 LABELS gfortran llvm) -RUN(NAME gpu_metal_272 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_272 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_273 LABELS gfortran llvm) -RUN(NAME gpu_metal_274 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_275 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_274 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_275 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_276 LABELS gfortran llvm) -RUN(NAME gpu_metal_277 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_278 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_279 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_280 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_277 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_278 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_279 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_280 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_281 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_281_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) -RUN(NAME gpu_metal_282 LABELS gfortran llvm metal cuda_cpu EXTRAFILES gpu_metal_282_mod.f90 EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_282 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_282_mod.f90 EXTRA_ARGS --realloc-lhs-arrays) RUN(NAME gpu_metal_283 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_283_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_284 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_284_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_285 LABELS gfortran llvm EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_286 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_287 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_288 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_289 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_290 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_291 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_metal_292 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_293 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_294 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_295 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_296 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_286 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_287 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_288 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_289 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_290 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_291 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_metal_292 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_293 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_294 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_295 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_296 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_297 LABELS gfortran llvm) -RUN(NAME gpu_metal_298 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_298 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_299 LABELS gfortran llvm) -RUN(NAME gpu_metal_300 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_300 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_301 LABELS gfortran llvm) -RUN(NAME gpu_metal_302 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_303 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_304 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_305 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_306 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_302 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_303 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_304 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_305 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_306 LABELS gfortran llvm metal cuda cuda_cpu) # Fortran 2023 `(cond ? a : b)`; no gfortran, same reason as conditional_expr_*. -RUN(NAME gpu_metal_307 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_308 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_309 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_310 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_311 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_312 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_313 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_314 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_315 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_316 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_317 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_318 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_319 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_320 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_321 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_322 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_323 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_324 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_325 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_326 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_307 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_308 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_309 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_310 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_311 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_312 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_313 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_314 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_315 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_316 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_317 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_318 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_319 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_320 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_321 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_322 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_323 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_324 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_325 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_326 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_327 LABELS gfortran llvm EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_328 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_329 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_330 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_331 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_332 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_333 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_334 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_335 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_336 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_337 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_338 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_328 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_329 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_330 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_331 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_332 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_333 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_334 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_335 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_336 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_337 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_338 LABELS gfortran llvm metal cuda cuda_cpu) # No gfortran label: `reduce` is F2023, and the gfortran the CI builds with # rejects it outright ("Syntax error in DO statement"). Same reason # gpu_metal_21 above carries none. Checked by hand against gfortran 16, # which does accept it. -RUN(NAME gpu_metal_339 LABELS llvm metal cuda_cpu) -RUN(NAME gpu_metal_340 LABELS llvm metal cuda_cpu EXTRA_ARGS --separate-compilation) # `shared` locality is not accepted by every supported gfortran -RUN(NAME gpu_metal_341 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_342 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_343 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_344 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_345 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_346 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_347 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_348 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_349 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_350 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_351 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_352 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_353 LABELS llvm metal cuda_cpu) # conditional expressions are not accepted by every supported gfortran -RUN(NAME gpu_metal_354 LABELS llvm metal cuda_cpu) # conditional expressions are not accepted by every supported gfortran -RUN(NAME gpu_metal_355 LABELS llvm metal cuda_cpu) # `local` locality is not accepted by every supported gfortran -RUN(NAME gpu_metal_356 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_372 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_357 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_360 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_361 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_362 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_365 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_366 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_371 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_367 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_373 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_374 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_378 LABELS llvm cuda_cpu) # integer(8) loop index is supported on cuda_cpu; metal declines integer(8); gfortran on CI lacks reduce clause -RUN(NAME gpu_metal_379 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_380 LABELS llvm metal cuda_cpu) # gfortran on CI lacks reduce clause -RUN(NAME gpu_metal_383 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_384 FAIL LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_339 LABELS llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_340 LABELS llvm metal cuda cuda_cpu EXTRA_ARGS --separate-compilation) # `shared` locality is not accepted by every supported gfortran +RUN(NAME gpu_metal_341 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_342 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_343 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_344 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_345 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_346 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_347 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_348 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_349 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_350 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_351 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_352 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_353 LABELS llvm metal cuda cuda_cpu) # conditional expressions are not accepted by every supported gfortran +RUN(NAME gpu_metal_354 LABELS llvm metal cuda cuda_cpu) # conditional expressions are not accepted by every supported gfortran +RUN(NAME gpu_metal_355 LABELS llvm metal cuda cuda_cpu) # `local` locality is not accepted by every supported gfortran +RUN(NAME gpu_metal_356 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_372 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_357 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_360 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_361 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_362 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_365 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_366 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_371 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_367 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_373 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_374 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_378 LABELS llvm cuda cuda_cpu) # integer(8) loop index is supported on cuda_cpu; metal declines integer(8); gfortran on CI lacks reduce clause +RUN(NAME gpu_metal_379 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_380 LABELS llvm metal cuda cuda_cpu) # gfortran on CI lacks reduce clause +RUN(NAME gpu_metal_383 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_384 FAIL LABELS gfortran llvm metal cuda cuda_cpu) # gpu_metal_381 has a BLOCK array whose extent is known only at run time, # which a Metal shader cannot declare yet, so it has no metal label. -RUN(NAME gpu_metal_381 LABELS gfortran llvm cuda_cpu) -RUN(NAME gpu_metal_382 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_386 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_387 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_388 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_389 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_390 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_391 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_381 LABELS gfortran llvm cuda cuda_cpu) +RUN(NAME gpu_metal_382 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_386 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_387 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_388 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_389 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_390 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_391 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_406 LABELS gfortran llvm) # the GPU backends report an error, see tests/tests.toml RUN(NAME gpu_metal_407 LABELS gfortran llvm) # the GPU backends report an error, see tests/tests.toml -RUN(NAME gpu_metal_408 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_392 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_393 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_394 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_409 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_410 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_411 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_412 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_408 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_392 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_393 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_394 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_409 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_410 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_411 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_412 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # A component whose size the host cannot work out before the loop: the # value is made on the device heap and copied out after the launch. -RUN(NAME gpu_metal_358 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_368 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_376 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_358 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_368 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_376 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # A launch that allocates more than the device heap holds stops; on the CPU # each iteration frees what it allocates, so the test is GPU-only. -RUN(NAME gpu_metal_414 FAIL LABELS metal cuda_cpu) -RUN(NAME gpu_metal_415 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_416 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays --no-array-bounds-checking) -RUN(NAME gpu_metal_419 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_420 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_417 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_418 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_421 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_422 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_423 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_424 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_425 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_426 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_427 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_428 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_429 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_430 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_431 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_432 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_433 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_434 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_metal_436 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_437 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_438 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_439 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_440 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_441 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_442 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_443 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_444 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_450 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_414 FAIL LABELS metal cuda cuda_cpu) +RUN(NAME gpu_metal_415 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_416 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays --no-array-bounds-checking) +RUN(NAME gpu_metal_419 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_420 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_417 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_418 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_421 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_422 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_423 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_424 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_425 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_426 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_427 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_428 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_429 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_430 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_431 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_432 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_433 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_434 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_metal_436 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_437 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_438 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_439 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_440 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_441 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_442 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_443 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_444 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_450 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_449 LABELS gfortran llvm metal cuda_cpu cuda) -RUN(NAME gpu_metal_454 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_445 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_460 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_461 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_462 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_463 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_464 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_465 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_447 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_448 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_455 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_456 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_451 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_452 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_453 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_470 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_471 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_472 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_473 FAIL LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_474 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_475 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_476 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_477 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_454 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_445 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_460 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_461 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_462 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_463 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_464 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_465 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_447 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_448 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_455 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_456 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_451 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_452 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_453 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_470 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_471 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_472 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_473 FAIL LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_474 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_475 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_476 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_477 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_482 LABELS gfortran llvm metal cuda_cpu cuda) # gfortran evaluates a `do concurrent` limit twice, so gpu_metal_369 has no # gfortran label. The llvm backend and gfortran evaluate the limits of an # inner index again for every value of the outer one, so gpu_metal_370 is for # the GPU backends only. -RUN(NAME gpu_metal_369 LABELS llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_370 LABELS metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_369 LABELS llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_370 LABELS metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) # Expected run-time errors on the GPU backends only. gpu_metal_359 and # gpu_metal_363 are GPU-only because the llvm backend still allocates array # components in `t(i) = f(...)` without --realloc-lhs-arrays (#9738). # gpu_metal_375 is GPU-only for the same reason as gpu_metal_363 (#9738). -RUN(NAME gpu_metal_375 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component written in both branches of an `if` that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_359 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_363 FAIL NO_FAST LABELS metal cuda_cpu) # bounds checking reports a component an `if` lets the loop write that is not allocated without --realloc-lhs-arrays -RUN(NAME gpu_metal_364 FAIL NO_FAST NO_STD_F23 LABELS llvm metal cuda_cpu) # bounds checking reports a component the loop assigns an array to that is not allocated without --realloc-lhs-arrays; --std=f23 allocates it on assignment +RUN(NAME gpu_metal_375 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component written in both branches of an `if` that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_359 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_363 FAIL NO_FAST LABELS metal cuda cuda_cpu) # bounds checking reports a component an `if` lets the loop write that is not allocated without --realloc-lhs-arrays +RUN(NAME gpu_metal_364 FAIL NO_FAST NO_STD_F23 LABELS llvm metal cuda cuda_cpu) # bounds checking reports a component the loop assigns an array to that is not allocated without --realloc-lhs-arrays; --std=f23 allocates it on assignment RUN(NAME gpu_metal_377 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_377_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_385 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_385_mod.f90 EXTRA_ARGS --separate-compilation) RUN(NAME gpu_metal_395 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_395_mod.f90 EXTRA_ARGS --separate-compilation) -RUN(NAME gpu_metal_396 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --fast) -RUN(NAME gpu_metal_397 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_398 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_399 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_400 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_401 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_402 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_403 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) -RUN(NAME gpu_metal_404 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_metal_405 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_396 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --fast) +RUN(NAME gpu_metal_397 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_398 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_399 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_400 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_401 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_402 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_403 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --realloc-lhs-arrays) +RUN(NAME gpu_metal_404 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_metal_405 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_metal_413 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_413_mod.f90 EXTRA_ARGS --separate-compilation --realloc-lhs-arrays) RUN(NAME gpu_metal_435 LABELS gfortran llvm metal cuda cuda_cpu EXTRAFILES gpu_metal_435_mod.f90 EXTRA_ARGS --separate-compilation $<$:--gpu-allow-cpu-fallback>) RUN(NAME inline_scoped_01 LABELS gfortran llvm EXTRA_ARGS --fast) RUN(NAME inline_function_calls_01 LABELS gfortran llvm EXTRA_ARGS --fast) -RUN(NAME gpu_decline_01 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_decline_02 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_decline_01 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_decline_02 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_decline_03 LABELS gfortran llvm EXTRAFILES gpu_decline_03_ext.f90) RUN(NAME gpu_decline_04 LABELS gfortran llvm) RUN(NAME gpu_decline_05 LABELS gfortran llvm) @@ -6457,14 +6457,14 @@ RUN(NAME gpu_decline_16 LABELS gfortran llvm) # One program per entry of the GPU unsupported list. Each runs on the CPU with # --gpu-allow-cpu-fallback where its loop is on the list, and the error # without the flag is kept by a reference test in tests/tests.toml. -RUN(NAME gpu_unsupported_01 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_02 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_03 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_04 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) -RUN(NAME gpu_unsupported_05 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_unsupported_06 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_unsupported_07 LABELS gfortran llvm metal cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) -RUN(NAME gpu_unsupported_08 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_unsupported_01 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_02 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_03 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_04 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS $<$:--gpu-allow-cpu-fallback>) +RUN(NAME gpu_unsupported_05 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_unsupported_06 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_unsupported_07 LABELS gfortran llvm metal cuda cuda_cpu EXTRA_ARGS --gpu-allow-cpu-fallback) +RUN(NAME gpu_unsupported_08 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_01 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_02 LABELS gfortran llvm) @@ -6475,10 +6475,10 @@ RUN(NAME gpu_kernel_source_06 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_07 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_08 LABELS gfortran llvm) RUN(NAME gpu_kernel_source_09 LABELS gfortran llvm) -RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda_cpu) -RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu cuda) -RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) RUN(NAME real128_arith_02 LABELS gfortran llvm) From 8d5b1ed3289b61e071140e7121c1a5c269851774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 02:33:28 +0000 Subject: [PATCH 13/19] fix: declare only the variables a GPU kernel scope refers to Every generated CUDA kernel unpacked all scalar arguments and declared all named constants and locals, even those the body never uses, so nvcc warned with #177-D (and host c++ with -Wunused-variable for cuda_cpu). Collect the declarations of a kernel, device function or block, emit its body first, and write only the declarations the body (or another kept declaration) refers to. The scalar argument struct keeps every field, so the host/device launch layout is unchanged. --- integration_tests/CMakeLists.txt | 1 + integration_tests/gpu_kernel_source_15.f90 | 36 ++++ src/libasr/codegen/asr_to_gpu_c.h | 171 +++++++++++------- src/libasr/codegen/gpu_kernel_signature.h | 23 ++- src/libasr/codegen/gpu_utils.h | 61 +++++++ ...a_kernel-gpu_kernel_source_01-0428e9e.json | 2 +- ...kernel-gpu_kernel_source_01-0428e9e.stdout | 1 - ...a_kernel-gpu_kernel_source_02-50a3dd7.json | 2 +- ...kernel-gpu_kernel_source_02-50a3dd7.stdout | 1 - ...a_kernel-gpu_kernel_source_03-049e8d1.json | 2 +- ...kernel-gpu_kernel_source_03-049e8d1.stdout | 1 - ...a_kernel-gpu_kernel_source_04-6974c93.json | 2 +- ...kernel-gpu_kernel_source_04-6974c93.stdout | 1 - ...a_kernel-gpu_kernel_source_05-7a49d7a.json | 2 +- ...kernel-gpu_kernel_source_05-7a49d7a.stdout | 1 - ...a_kernel-gpu_kernel_source_06-e2e24ed.json | 2 +- ...kernel-gpu_kernel_source_06-e2e24ed.stdout | 2 - ...a_kernel-gpu_kernel_source_07-85c87ca.json | 2 +- ...kernel-gpu_kernel_source_07-85c87ca.stdout | 1 - ...a_kernel-gpu_kernel_source_08-7107bec.json | 2 +- ...kernel-gpu_kernel_source_08-7107bec.stdout | 4 - ...a_kernel-gpu_kernel_source_09-d292d10.json | 2 +- ...kernel-gpu_kernel_source_09-d292d10.stdout | 4 - ...a_kernel-gpu_kernel_source_15-6a73706.json | 13 ++ ...kernel-gpu_kernel_source_15-6a73706.stdout | 49 +++++ ...gpu_cuda_kernel-gpu_metal_167-53cda6a.json | 2 +- ...u_cuda_kernel-gpu_metal_167-53cda6a.stdout | 4 - ...gpu_cuda_kernel-gpu_metal_176-d54ae7a.json | 2 +- ...u_cuda_kernel-gpu_metal_176-d54ae7a.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_177-e8939af.json | 2 +- ...u_cuda_kernel-gpu_metal_177-e8939af.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_213-3f07f96.json | 2 +- ...u_cuda_kernel-gpu_metal_213-3f07f96.stdout | 6 - ...gpu_cuda_kernel-gpu_metal_265-880d0b8.json | 2 +- ...u_cuda_kernel-gpu_metal_265-880d0b8.stdout | 7 - ...gpu_cuda_kernel-gpu_metal_277-2406dc4.json | 2 +- ...u_cuda_kernel-gpu_metal_277-2406dc4.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_289-b8995a9.json | 2 +- ...u_cuda_kernel-gpu_metal_289-b8995a9.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_290-febb906.json | 2 +- ...u_cuda_kernel-gpu_metal_290-febb906.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_291-460362f.json | 2 +- ...u_cuda_kernel-gpu_metal_291-460362f.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_292-0dd7a4a.json | 2 +- ...u_cuda_kernel-gpu_metal_292-0dd7a4a.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_296-10ab30d.json | 2 +- ...u_cuda_kernel-gpu_metal_296-10ab30d.stdout | 3 - ...gpu_cuda_kernel-gpu_metal_298-e543a30.json | 2 +- ...u_cuda_kernel-gpu_metal_298-e543a30.stdout | 4 - ...gpu_cuda_kernel-gpu_metal_302-c945ed1.json | 2 +- ...u_cuda_kernel-gpu_metal_302-c945ed1.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_304-0ced324.json | 2 +- ...u_cuda_kernel-gpu_metal_304-0ced324.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_307-eb7dd8e.json | 2 +- ...u_cuda_kernel-gpu_metal_307-eb7dd8e.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_309-c5214d3.json | 2 +- ...u_cuda_kernel-gpu_metal_309-c5214d3.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_310-c1a4744.json | 2 +- ...u_cuda_kernel-gpu_metal_310-c1a4744.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_316-6447449.json | 2 +- ...u_cuda_kernel-gpu_metal_316-6447449.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_317-ecc259a.json | 2 +- ...u_cuda_kernel-gpu_metal_317-ecc259a.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_318-5a5bfbd.json | 2 +- ...u_cuda_kernel-gpu_metal_318-5a5bfbd.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_320-082cdda.json | 2 +- ...u_cuda_kernel-gpu_metal_320-082cdda.stdout | 4 - ...gpu_cuda_kernel-gpu_metal_328-cc3334c.json | 2 +- ...u_cuda_kernel-gpu_metal_328-cc3334c.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_334-124b176.json | 2 +- ...u_cuda_kernel-gpu_metal_334-124b176.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_337-9610a4e.json | 2 +- ...u_cuda_kernel-gpu_metal_337-9610a4e.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_391-0cf1271.json | 2 +- ...u_cuda_kernel-gpu_metal_391-0cf1271.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_408-553c2f1.json | 2 +- ...u_cuda_kernel-gpu_metal_408-553c2f1.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_452-b86afe3.json | 2 +- ...u_cuda_kernel-gpu_metal_452-b86afe3.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_453-087cbdb.json | 2 +- ...u_cuda_kernel-gpu_metal_453-087cbdb.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_455-ec807a4.json | 2 +- ...u_cuda_kernel-gpu_metal_455-ec807a4.stdout | 1 - ...gpu_cuda_kernel-gpu_metal_474-0583450.json | 2 +- ...u_cuda_kernel-gpu_metal_474-0583450.stdout | 3 - ...gpu_cuda_kernel-gpu_metal_476-6b797c7.json | 2 +- ...u_cuda_kernel-gpu_metal_476-6b797c7.stdout | 5 - ...gpu_cuda_kernel-gpu_metal_477-3f086b7.json | 2 +- ...u_cuda_kernel-gpu_metal_477-3f086b7.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_478-5c1241e.json | 2 +- ...u_cuda_kernel-gpu_metal_478-5c1241e.stdout | 2 - ...gpu_cuda_kernel-gpu_metal_479-7e99684.json | 2 +- ...u_cuda_kernel-gpu_metal_479-7e99684.stdout | 1 - ...l_kernel-gpu_kernel_source_15-ddc1d80.json | 13 ++ ...kernel-gpu_kernel_source_15-ddc1d80.stdout | 62 +++++++ ...pu_metal_kernel-gpu_metal_480-8fa07de.json | 2 +- ..._metal_kernel-gpu_metal_480-8fa07de.stdout | 1 - tests/tests.toml | 5 + 98 files changed, 409 insertions(+), 202 deletions(-) create mode 100644 integration_tests/gpu_kernel_source_15.f90 create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.json create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.stdout create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.json create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.stdout diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0bc1f0a8de6..5aa1345522c 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6449,6 +6449,7 @@ RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_15 LABELS gfortran llvm metal cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) RUN(NAME real128_arith_02 LABELS gfortran llvm) diff --git a/integration_tests/gpu_kernel_source_15.f90 b/integration_tests/gpu_kernel_source_15.f90 new file mode 100644 index 00000000000..eb5f19b78d2 --- /dev/null +++ b/integration_tests/gpu_kernel_source_15.f90 @@ -0,0 +1,36 @@ +program gpu_kernel_source_15 + ! A kernel, a block in it and a routine it calls declare only the + ! scalars and locals they refer to: the kernel does not use the + ! extent of `x` or `y` or the named constant `n`, but it does use the + ! leading extent of `z`; the block does not use `unused`, and the + ! function does not use `width` or `unused`. + implicit none + integer, parameter :: n = 8 + real, allocatable :: x(:), y(:), z(:,:) + real :: a + integer :: i + allocate(x(n), y(n), z(n, 2)) + a = 2.0 + x = 1.0 + y = 3.0 + z = 0.0 + do concurrent (i = 1:n) + block + real :: t, unused + t = a*x(i) + y(i) = t + y(i) + end block + z(i, 2) = twice(y(i)) + end do + if (any(abs(y - 5.0) > 1e-6)) error stop 1 + if (any(abs(z(:, 2) - 10.0) > 1e-6)) error stop 2 + if (any(z(:, 1) /= 0.0)) error stop 3 + print *, "ok" +contains + pure real function twice(v) + real, intent(in) :: v + integer, parameter :: width = 2 + real :: unused + twice = 2*v + end function +end program diff --git a/src/libasr/codegen/asr_to_gpu_c.h b/src/libasr/codegen/asr_to_gpu_c.h index 0d918b05a40..a0543a7f616 100644 --- a/src/libasr/codegen/asr_to_gpu_c.h +++ b/src/libasr/codegen/asr_to_gpu_c.h @@ -618,6 +618,10 @@ class ASRToGpuCVisitor // host runtime binds them. A dialect epilogue reads this back. std::vector kernel_params; + // What the kernel being emitted declares ahead of its body, which it + // writes once the body shows which of them it refers to. + std::vector kernel_declarations; + // The spellings this instantiation emits. It is a value rather than a // set of static members so that a dialect can carry per-invocation state, // such as whether the CUDA backend is emitting for the CPU emulation. @@ -3440,6 +3444,8 @@ class ASRToGpuCVisitor ASR::down_cast(fn->m_return_var)->m_v); src << get_indent() << ret_type << " " << sanitize_name(rv->m_name) << ";\n"; } + // The function writes only the declarations its body refers to. + std::vector declarations; // Declare Parameter (constant) variables from the function scope for (auto &item : fn->m_symtab->get_scope()) { if (!ASR::is_a(*item.second)) continue; @@ -3447,7 +3453,8 @@ class ASRToGpuCVisitor item.second); if (var->m_storage != ASR::storage_typeType::Parameter) continue; if (!var->m_value) continue; - emit_named_constant_decl(var); + declarations.push_back(variable_declaration(*var, + [&]() { emit_named_constant_decl(var); })); } // Declare local variables (non-argument, non-return, non-parameter) in_inline_function = true; @@ -3470,7 +3477,8 @@ class ASRToGpuCVisitor if (var->m_storage == ASR::storage_typeType::Parameter) continue; if (declared_by_signature.count(item.second)) continue; - emit_local_var_decl(var); + declarations.push_back(variable_declaration(*var, + [&]() { emit_local_var_decl(var); })); } } // Pre-scan the inline function body for Allocate statements @@ -3580,9 +3588,12 @@ class ASRToGpuCVisitor ASR::down_cast(fn->m_return_var)->m_v) ->m_name); } - for (size_t i = 0; i < fn->n_body; i++) { - visit_stmt(fn->m_body[i]); - } + std::string body = captured_source([&]() { + for (size_t i = 0; i < fn->n_body; i++) { + visit_stmt(fn->m_body[i]); + } + }); + src << gpu_referenced_declarations(declarations, body) << body; current_return_name.clear(); in_inline_function = false; if (fn->m_return_var) { @@ -3604,6 +3615,23 @@ class ASRToGpuCVisitor current_kernel_layout = nullptr; } + // What `emit` writes to `src`, which it leaves as it was. + template + std::string captured_source(F emit) { + std::stringstream saved; + saved.swap(src); + emit(); + saved.swap(src); + return saved.str(); + } + + // The declaration `emit` writes for `var`. + template + GpuDeclaration variable_declaration(const ASR::Variable_t &var, F emit) { + std::string name(var.m_name); + return {{name, sanitize_name(name)}, captured_source(emit)}; + } + void emit_kernel_signature(const ASR::Function_t &x); void bind_kernel_arguments(const ASR::Function_t &x); @@ -3656,12 +3684,18 @@ class ASRToGpuCVisitor } for (ASR::Variable_t *var : gpu_scope_declaration_order( x.m_symtab, current_vla_infos, arg_names)) { - emit_local_var_decl(var); + kernel_declarations.push_back(variable_declaration(*var, + [&]() { emit_local_var_decl(var); })); } - for (size_t i = 0; i < x.n_body; i++) { - visit_stmt(x.m_body[i]); - } + std::string body = captured_source([&]() { + for (size_t i = 0; i < x.n_body; i++) { + visit_stmt(x.m_body[i]); + } + }); + src << gpu_referenced_declarations(kernel_declarations, body) + << body; + kernel_declarations.clear(); indent_level--; src << "}\n\n"; @@ -4402,59 +4436,68 @@ class ASRToGpuCVisitor BlockNameScope block_names(*this, block->m_symtab); src << get_indent() << "{\n"; indent_level++; + // The block writes only the declarations its body refers to. + std::vector declarations; for (ASR::Variable_t *v : gpu_scope_declaration_order( block->m_symtab, current_vla_infos)) { - // Check if this variable is a VLA backed by a workspace - // buffer (populated during kernel signature generation). - std::string vname(v->m_name); - auto vla_it = std::find_if( - current_vla_infos.begin(), current_vla_infos.end(), - [&](const GpuVlaWorkspace &ws) { - return ws.var == &v->base; - }); - if (vla_it != current_vla_infos.end()) { - std::string elem_type_str; - ASR::ttype_t *vtype = - ASRUtils::type_get_past_allocatable(v->m_type); - if (ASR::is_a(*vtype)) { - elem_type_str = gpu_type( - ASR::down_cast( - vtype)->m_type); - } - if (elem_type_str.empty() - || elem_type_str.find("unsupported") - != std::string::npos) { - throw CodeGenError( - "gpu offload: workspace '" + vname + - "' has no gpu type of the same width"); - } - // Emit a device pointer into the per-thread slice - std::string extent = - workspace_extent_str(*vla_it); - std::string slice = workspace_slice_str(*vla_it); - src << get_indent() << global_prefix() - << elem_type_str << "* " << vname - << " = " << gpu_workspace_buffer_name( - vla_it->buffer_index) - << " + " << dialect.global_thread_id() - << " * "; - if (vla_it->dims.size() == 1) { - src << slice; + declarations.push_back(variable_declaration(*v, [&]() { + // Check if this variable is a VLA backed by a + // workspace buffer (populated during kernel + // signature generation). + std::string vname(v->m_name); + auto vla_it = std::find_if( + current_vla_infos.begin(), current_vla_infos.end(), + [&](const GpuVlaWorkspace &ws) { + return ws.var == &v->base; + }); + if (vla_it != current_vla_infos.end()) { + std::string elem_type_str; + ASR::ttype_t *vtype = + ASRUtils::type_get_past_allocatable(v->m_type); + if (ASR::is_a(*vtype)) { + elem_type_str = gpu_type( + ASR::down_cast( + vtype)->m_type); + } + if (elem_type_str.empty() + || elem_type_str.find("unsupported") + != std::string::npos) { + throw CodeGenError( + "gpu offload: workspace '" + vname + + "' has no gpu type of the same width"); + } + // Emit a device pointer into the per-thread slice + std::string extent = + workspace_extent_str(*vla_it); + std::string slice = workspace_slice_str(*vla_it); + src << get_indent() << global_prefix() + << elem_type_str << "* " << vname + << " = " << gpu_workspace_buffer_name( + vla_it->buffer_index) + << " + " << dialect.global_thread_id() + << " * "; + if (vla_it->dims.size() == 1) { + src << slice; + } else { + src << "(" << slice << ")"; + } + src << ";\n"; + local_alloc_arrays.insert(&v->base); + // Record the size expression for alloc-assign + // and copy-loop codegen + alloc_array_size_exprs[vname] = extent; } else { - src << "(" << slice << ")"; + emit_local_var_decl(v); } - src << ";\n"; - local_alloc_arrays.insert(&v->base); - // Record the size expression for alloc-assign - // and copy-loop codegen - alloc_array_size_exprs[vname] = extent; - } else { - emit_local_var_decl(v); - } - } - for (size_t i = 0; i < block->n_body; i++) { - visit_stmt(block->m_body[i]); + })); } + std::string body = captured_source([&]() { + for (size_t i = 0; i < block->n_body; i++) { + visit_stmt(block->m_body[i]); + } + }); + src << gpu_referenced_declarations(declarations, body) + << body; indent_level--; src << get_indent() << "}\n"; break; @@ -4468,13 +4511,19 @@ class ASRToGpuCVisitor BlockNameScope block_names(*this, ab->m_symtab); src << get_indent() << "{\n"; indent_level++; + std::vector declarations; for (ASR::Variable_t *v : gpu_scope_declaration_order( ab->m_symtab, current_vla_infos)) { - emit_local_var_decl(v); - } - for (size_t i = 0; i < ab->n_body; i++) { - visit_stmt(ab->m_body[i]); + declarations.push_back(variable_declaration(*v, + [&]() { emit_local_var_decl(v); })); } + std::string body = captured_source([&]() { + for (size_t i = 0; i < ab->n_body; i++) { + visit_stmt(ab->m_body[i]); + } + }); + src << gpu_referenced_declarations(declarations, body) + << body; indent_level--; src << get_indent() << "}\n"; break; diff --git a/src/libasr/codegen/gpu_kernel_signature.h b/src/libasr/codegen/gpu_kernel_signature.h index 57bd016e9d2..2100a657f0c 100644 --- a/src/libasr/codegen/gpu_kernel_signature.h +++ b/src/libasr/codegen/gpu_kernel_signature.h @@ -82,18 +82,24 @@ void ASRToGpuCVisitor::emit_kernel_signature(const ASR::Function_t &kernel) { } src << ")\n{\n"; indent_level++; + // The declarations ahead of the body are collected rather than written, + // so that the kernel writes only those its body refers to. + kernel_declarations.clear(); for (size_t i = 0; i < layout.n_scalars; i++) { const auto &arg = layout.m_scalars[i]; if (arg.m_kind == ASR::gpu_argument_kindType::GpuPackedOffset) continue; std::string parameter = gpu_argument_name(arg, layout); - src << get_indent() << gpu_type(arg.m_type) << " " << parameter - << " = __scalar_args." << parameter << ";\n"; + kernel_declarations.push_back({{parameter}, get_indent() + + gpu_type(arg.m_type) + " " + parameter + + " = __scalar_args." + parameter + ";\n"}); } // Each iteration runs on `lanes` consecutive threads: the thread index // the body sees is the iteration's, and the lane tells them apart. if (layout.m_lanes) { - dialect.emit_lane_prologue(src, get_indent(), + std::stringstream prologue; + dialect.emit_lane_prologue(prologue, get_indent(), ASRUtils::symbol_name(layout.m_lanes)); + kernel_declarations.push_back({{}, prologue.str()}); } if (layout.m_packed) { for (size_t i = 0; i < layout.n_buffers; i++) { @@ -101,11 +107,12 @@ void ASRToGpuCVisitor::emit_kernel_signature(const ASR::Function_t &kernel) { std::string type = element_type(arg); std::string parameter = gpu_argument_name(arg, layout); bool reference = is_reference(arg); - src << get_indent() << global_prefix() << type - << (reference ? "& " : "* ") << parameter << " = " - << (reference ? "*" : "") << "(" << global_prefix() - << type << "*)(__packed_arrays + __scalar_args.__offset_" - << parameter << ");\n"; + kernel_declarations.push_back({{parameter}, get_indent() + + global_prefix() + type + (reference ? "& " : "* ") + + parameter + " = " + (reference ? "*" : "") + "(" + + global_prefix() + type + + "*)(__packed_arrays + __scalar_args.__offset_" + + parameter + ");\n"}); } } } diff --git a/src/libasr/codegen/gpu_utils.h b/src/libasr/codegen/gpu_utils.h index b6f7c4ded92..8f081c83736 100644 --- a/src/libasr/codegen/gpu_utils.h +++ b/src/libasr/codegen/gpu_utils.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -361,6 +362,66 @@ struct GpuKernelParam { GpuKernelParamKind kind; }; +// A declaration a kernel, a device function or a block makes ahead of its +// body: a scalar unpacked from the scalar argument struct, a buffer unpacked +// from the packed arrays, or a local variable. It declares the names in +// `names`; one that declares none is always written. +struct GpuDeclaration { + std::vector names; + std::string text; +}; + +// Adds the identifiers the generated source `code` refers to to `result`. +// A member name, which follows `.` or `->`, refers to no variable. +inline void gpu_referenced_identifiers(const std::string &code, + std::set &result) { + auto is_word = [](char c) { + return std::isalnum(static_cast(c)) || c == '_'; + }; + size_t i = 0; + while (i < code.size()) { + if (!is_word(code[i])) { + i++; + continue; + } + size_t start = i; + while (i < code.size() && is_word(code[i])) i++; + if (std::isdigit(static_cast(code[start]))) continue; + bool member = (start >= 1 && code[start - 1] == '.') || + (start >= 2 && code[start - 2] == '-' && code[start - 1] == '>'); + if (!member) result.insert(code.substr(start, i - start)); + } +} + +// The declarations of `declarations` that `body`, or another declaration +// written, refers to, in order. The device compilers warn about a variable +// that is declared and never referred to, so a scope does not unpack the +// scalars or declare the locals it has no use for. Dropping one changes no +// behavior: none has side effects, and the scalar argument struct the host +// fills keeps every field, so the launch is laid out as before. +inline std::string gpu_referenced_declarations( + const std::vector &declarations, + const std::string &body) { + std::set referenced; + gpu_referenced_identifiers(body, referenced); + // A declaration refers only to names declared ahead of it, so walking + // them backwards sees every use of a name before its declaration. + std::vector keep(declarations.size()); + for (size_t i = declarations.size(); i-- > 0;) { + const GpuDeclaration &declaration = declarations[i]; + keep[i] = declaration.names.empty(); + for (const std::string &name : declaration.names) { + keep[i] = keep[i] || referenced.count(name) > 0; + } + if (keep[i]) gpu_referenced_identifiers(declaration.text, referenced); + } + std::string result; + for (size_t i = 0; i < declarations.size(); i++) { + if (keep[i]) result += declarations[i].text; + } + return result; +} + // An allocatable array component of a kernel argument that is an array of a // derived type reaches the device as three buffers: the elements' data laid // out end to end, the per-element offsets into it, and the per-element sizes. diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.json index 7fc75a47c3e..d79aca8ca00 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.stdout", - "stdout_hash": "9e5baeb341e1fccb5d6c5a731e1de6bd35c42b09f31690af45dcadc7", + "stdout_hash": "20675d89e913b63d1a3a9a03bd2c01ec5a310ca40aac399e699f7fba", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.stdout index 38510ed2a99..60b1b00765b 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_01-0428e9e.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 1000; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.json index fe92f3af591..dfd01da1324 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.stdout", - "stdout_hash": "e3a7573f396bf38e2650fdb26801a84b4d79fe2898a79e03ac52c8f0", + "stdout_hash": "51176f44c2d293be2b3fcd815c7cc2eb428fa2686e00a903e34afe82", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.stdout index 3ab966b354e..5277b5e3eea 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_02-50a3dd7.stdout @@ -13,7 +13,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; const float a = 2.50000000000000000e+00f; int i; - const int n = 12; const int tbl[3] = {7, 8, 9}; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.json index d5d83a59fc6..83915ebd8aa 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.stdout", - "stdout_hash": "d419f06f3641a658693363b54728f2fbca9738ca550cfb763cb07c86", + "stdout_hash": "cb4701ab1a34a491ad67250dd07f87b1fc252559dafa7a9596b73bf1", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.stdout index d2ebb2095b3..81f15c8e1f1 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_03-049e8d1.stdout @@ -18,7 +18,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( const float cs[5] = {1.00000000e+00, 5.00000000e-01, 2.50000000e-01, 1.25000000e-01, 6.25000000e-02}; int i; int j; - const int n = 16; const int nc = 5; float twox; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.json index 9c959aec123..1225624821e 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_04-6974c93.stdout", - "stdout_hash": "b39a591b178134562b1f23b25867cdd7060f64261f4b981550fcbe57", + "stdout_hash": "2bf25ac26a093e976c44b9794270c89e3f91df4e25d442b3036939ee", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.stdout index f0698714ed2..50213a4808e 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_04-6974c93.stdout @@ -12,7 +12,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.json index f41476fd2e4..6f25c8dccca 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.stdout", - "stdout_hash": "3410351a4e1150685a5597cde8f8df42c57a9735e4d0d8cbdef13a8f", + "stdout_hash": "78ef015b7356a4b6289f4d24fefc71486f5eb9f712e68ab8bd717edb", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.stdout index e99005a5fcc..49bd4fc0288 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_05-7a49d7a.stdout @@ -12,7 +12,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.json index 62d6806ffd7..59fdd403a04 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.stdout", - "stdout_hash": "ae1f7381390616b838db8e5095f82f91ceb411dd735dd070bd10c43a", + "stdout_hash": "8d94698b68e709f5913ca60463123f5079a12570ac4882ee931513be", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.stdout index a455747317a..fa9419d70c8 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_06-e2e24ed.stdout @@ -15,8 +15,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; int i; int j; - const int m = 4; - const int nc = 5; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= ((((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)) * (((__loop_end_1 >= 1)) ? (((__loop_end_1 - 1) + 1)) : (0))))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.json index 0a878c86f17..6f7496075fd 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.stdout", - "stdout_hash": "b668d8afad59d24f39d3b5a2cd680cd26741b87d43df85f394c46c05", + "stdout_hash": "a16607ee7b4980710ec6f58d65b86c4de1147b5510dcc6d270071a9a", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.stdout index d2210c799f0..03b7f3c9b44 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_07-85c87ca.stdout @@ -13,7 +13,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; const double c = 2.82094791773878140e-01; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.json index 2b34a3a75d5..f4f3ff0e3b4 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_08-7107bec.stdout", - "stdout_hash": "d50834fb279d7ecb6d4fe078729bfc6dd9b18ec6fc657f2f1d794885", + "stdout_hash": "72cea0b9caf978c64d13573b7e78db7cfad73c48eb308ef4a35ffce4", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.stdout index c12c26cf964..9efae7ea169 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_08-7107bec.stdout @@ -32,7 +32,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int j; int k; const int m = 10000; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -96,7 +95,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int j; int k; const int m = 10000; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -145,7 +143,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( int j; int k; const int m = 10000; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -198,7 +195,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_3( int j; int k; const int m = 10000; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.json index a0d586db72d..dac6f5af063 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.json +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_kernel_source_09-d292d10.stdout", - "stdout_hash": "8c0bfa88e57643432ca7b9570301b78a368ee82dd72ee601f9645d9a", + "stdout_hash": "806cc4001d0860a73e8652009c4616c07d2a7ae8d89818a6e84204d4", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.stdout index 1da87099fcc..75476d1a4e9 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_09-d292d10.stdout @@ -22,7 +22,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; int j; int k; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -79,7 +78,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __flat_idx; int j; int k; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -133,7 +131,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( aggregate __gpu_struct_argument; int j; int k; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -173,7 +170,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_3( int __flat_idx; int j; int k; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.json new file mode 100644 index 00000000000..a396530d50d --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_cuda_kernel-gpu_kernel_source_15-6a73706", + "cmd": "lfortran --no-color --gpu=cuda --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_15.f90", + "infile_hash": "b548262f1790e25efae0005dfec351f092d5bd7ec7fc20b287feb76d", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_cuda_kernel-gpu_kernel_source_15-6a73706.stdout", + "stdout_hash": "18f28f02a5808826efe5328a73e05ac8d00dd72e780ffad8b4992905", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.stdout new file mode 100644 index 00000000000..5f4cae90c65 --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_15-6a73706.stdout @@ -0,0 +1,49 @@ +#include + +__device__ inline float twice_gpu_11(float v) { + float twice; + twice = (((float)2) * v); + return twice; +} + +struct __ScalarArgs___lfortran_gpu_kernel_0 { + float a; + int __dim_x_0; + int __lb_x_0; + int __dim_y_0; + int __lb_y_0; + int __dim_z_0; + int __lb_z_0; + int __dim_z_1; + int __lb_z_1; + int __loop_end_0; +}; + +extern "C" __global__ void __lfortran_gpu_kernel_0( + float* x, + float* y, + float* z, + __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) +{ + float a = __scalar_args.a; + int __lb_x_0 = __scalar_args.__lb_x_0; + int __lb_y_0 = __scalar_args.__lb_y_0; + int __dim_z_0 = __scalar_args.__dim_z_0; + int __lb_z_0 = __scalar_args.__lb_z_0; + int __lb_z_1 = __scalar_args.__lb_z_1; + int __loop_end_0 = __scalar_args.__loop_end_0; + int __flat_idx; + int i; + if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); + i = (__flat_idx + 1); + { + float t; + t = (a * x[((int)(i) - (__lb_x_0))]); + y[((int)(i) - (__lb_y_0))] = (t + y[((int)(i) - (__lb_y_0))]); + } + z[((int)(i) - (__lb_z_0)) + (__dim_z_0 * ((int)(2) - (__lb_z_1)))] = twice_gpu_11(y[((int)(i) - (__lb_y_0))]); +} + diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.json b/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.json index 4071c2d3922..3b63bdc062c 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_167-53cda6a.stdout", - "stdout_hash": "2682b9a1aecf8937c6e1796fea26c5f2ee23f30fad8702783f402390", + "stdout_hash": "88fcca9a21c41a30db16054c4c2317cd5cb4da31c4d1d3fb086388d6", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.stdout index 37887715a08..244d5615128 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_167-53cda6a.stdout @@ -51,12 +51,8 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args, float* __workspace_5) { - int nb = __scalar_args.nb; int __dim_a_0 = __scalar_args.__dim_a_0; - int __lb_a_0 = __scalar_args.__lb_a_0; int __dim_a_1 = __scalar_args.__dim_a_1; - int __lb_a_1 = __scalar_args.__lb_a_1; - int __dim_d_0 = __scalar_args.__dim_d_0; int __lb_d_0 = __scalar_args.__lb_d_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.json b/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.json index 2bcfe3cddcf..08738344ff5 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_176-d54ae7a.stdout", - "stdout_hash": "6d28ce09241743b6b6c9832898851d93ee81bed4d4cf705513621a48", + "stdout_hash": "e298f23511484cb548f5d69ceec5cce037fbcbf4a3d9baf27ecb09fb", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.stdout index 14785f67bcb..958e0be1321 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_176-d54ae7a.stdout @@ -22,7 +22,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_6, float* __workspace_7) { - int mbs = __scalar_args.mbs; int n = __scalar_args.n; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.json b/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.json index a430a346980..74c42a5d51f 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_177-e8939af.stdout", - "stdout_hash": "49623cd55e0e32e9e5459fe55e2f0c6617ec2761c86c8c9326457fc6", + "stdout_hash": "9a0bb5cc42eb8d4b2764cc2cb156258f88a2bf1d588062cf1251750a", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.stdout index 28f19f5ea7f..d2efb5d9dcc 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_177-e8939af.stdout @@ -43,7 +43,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_7) { int n = __scalar_args.n; - int __dim_arr_0 = __scalar_args.__dim_arr_0; int __lb_arr_0 = __scalar_args.__lb_arr_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.json b/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.json index ae6eb5447a9..c13025f90ba 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_213-3f07f96.stdout", - "stdout_hash": "519b328f21fcf6deb10e056a686f31a0f2de31481b42c3347ebb3e2f", + "stdout_hash": "f5d0139122c2cae533a473cb36ef5ab79456be04dc1c113b6e2bd191", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.stdout index ecae1eacac8..ec4650db65b 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_213-3f07f96.stdout @@ -37,7 +37,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( double* d, __ScalarArgs___lfortran_gpu_kernel_1 __scalar_args) { - int __dim_d_0 = __scalar_args.__dim_d_0; int __lb_d_0 = __scalar_args.__lb_d_0; int __flat_idx; int i; @@ -61,9 +60,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( double* y, __ScalarArgs___lfortran_gpu_kernel_2 __scalar_args) { - int __dim_x_0 = __scalar_args.__dim_x_0; int __lb_x_0 = __scalar_args.__lb_x_0; - int __dim_y_0 = __scalar_args.__dim_y_0; int __lb_y_0 = __scalar_args.__lb_y_0; int __flat_idx; int i; @@ -88,7 +85,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_3( { int __dim_m_0 = __scalar_args.__dim_m_0; int __lb_m_0 = __scalar_args.__lb_m_0; - int __dim_m_1 = __scalar_args.__dim_m_1; int __lb_m_1 = __scalar_args.__lb_m_1; int __flat_idx; int i; @@ -117,9 +113,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_4( long* k, __ScalarArgs___lfortran_gpu_kernel_4 __scalar_args) { - int __dim_d_0 = __scalar_args.__dim_d_0; int __lb_d_0 = __scalar_args.__lb_d_0; - int __dim_k_0 = __scalar_args.__dim_k_0; int __lb_k_0 = __scalar_args.__lb_k_0; int __flat_idx; int i; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.json b/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.json index d9875a7c607..b55ef16b7d4 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_265-880d0b8.stdout", - "stdout_hash": "399791c8b5c7b13ad1061de72b312fedfb8770d043c1c8e701f1274e", + "stdout_hash": "445eded1a28c11228bf208591ef24145cfdb52e6dc2aa106bc67e766", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.stdout index 30340bec84d..ce82884c624 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_265-880d0b8.stdout @@ -13,9 +13,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* b, __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) { - int __dim_a_0 = __scalar_args.__dim_a_0; int __lb_a_0 = __scalar_args.__lb_a_0; - int __dim_b_0 = __scalar_args.__dim_b_0; int __lb_b_0 = __scalar_args.__lb_b_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; @@ -57,18 +55,15 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __workspace_5, float* __workspace_6) { - int n = __scalar_args.n; int __dim_op_0 = __scalar_args.__dim_op_0; int __lb_op_0 = __scalar_args.__lb_op_0; int __dim_op_1 = __scalar_args.__dim_op_1; int __lb_op_1 = __scalar_args.__lb_op_1; int __dim_out_0 = __scalar_args.__dim_out_0; int __lb_out_0 = __scalar_args.__lb_out_0; - int __dim_out_1 = __scalar_args.__dim_out_1; int __lb_out_1 = __scalar_args.__lb_out_1; int __dim_v_0 = __scalar_args.__dim_v_0; int __lb_v_0 = __scalar_args.__lb_v_0; - int __dim_v_1 = __scalar_args.__dim_v_1; int __lb_v_1 = __scalar_args.__lb_v_1; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; @@ -159,9 +154,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( float* __workspace_3) { int n = __scalar_args.n; - int __dim_a_0 = __scalar_args.__dim_a_0; int __lb_a_0 = __scalar_args.__lb_a_0; - int __dim_b_0 = __scalar_args.__dim_b_0; int __lb_b_0 = __scalar_args.__lb_b_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.json b/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.json index 4ced0d199fe..c01c6b481da 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_277-2406dc4.stdout", - "stdout_hash": "50858481ee2b36fcb47f5198652fb5d43e5c4b5a0a3047336435fa95", + "stdout_hash": "96e2cc44060176eee134eb3c84c96f84d72a8f3c23a6a8973d765e19", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.stdout index 767ae7a34d9..1b070c37a83 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_277-2406dc4.stdout @@ -96,7 +96,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_sec_i; int __gpu_sec_i1; int j; - const int m = 3; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -221,7 +220,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __workspace_5, float* __workspace_6) { - int n = __scalar_args.n; int __dim_c_0 = __scalar_args.__dim_c_0; int __dim_out_0 = __scalar_args.__dim_out_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.json b/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.json index bf51d940129..df5874e4f8b 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_289-b8995a9.stdout", - "stdout_hash": "77fdfea13538e602247f2badad4a243fbf2b71f90e4899057c4c0944", + "stdout_hash": "4f8bd1dd154d280c5a8f0b653db61e69bb8791a10598904e7d90b3fb", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.stdout index 3de9c292483..dac0b61329a 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_289-b8995a9.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; @@ -63,7 +62,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.json b/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.json index e40acb27fca..b6f0280e306 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_290-febb906.stdout", - "stdout_hash": "03855f4a849a1b605d5c09f42c3545fa60543429074aff62f3a7bbc5", + "stdout_hash": "9df77c37b066e770e2d1cb7da349db7f701c07c655b88ac34df353f2", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.stdout index 96a633915c3..83003c4bc0e 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_290-febb906.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.json b/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.json index 9687e8244fe..91101fb5713 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_291-460362f.stdout", - "stdout_hash": "d15a32de92c63bdf19cee98429e3088049eb7d18faf5aed060f23bd2", + "stdout_hash": "d99de52818c45429d07edaf81c76bf4e7d9615cf37e42da07a967aad", "stderr": "gpu_cuda_kernel-gpu_metal_291-460362f.stderr", "stderr_hash": "64a8815f47348eb18517c2672487367a4ab1c69a822bd593c1a3703c", "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.stdout index e2fcc9b18b6..f87a577c7f4 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_291-460362f.stdout @@ -10,7 +10,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* r, __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) { - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.json b/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.json index 883b7f9aac7..7f62df9833f 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_292-0dd7a4a.stdout", - "stdout_hash": "77fdfea13538e602247f2badad4a243fbf2b71f90e4899057c4c0944", + "stdout_hash": "4f8bd1dd154d280c5a8f0b653db61e69bb8791a10598904e7d90b3fb", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.stdout index 3de9c292483..dac0b61329a 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_292-0dd7a4a.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; @@ -63,7 +62,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.json b/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.json index 8585a93604e..a81144248bb 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_296-10ab30d.stdout", - "stdout_hash": "9590916c11124c74e5a45476309affa7b42fa24ea35aa4b33301d9c2", + "stdout_hash": "bc078dafb5c77a598257dea162429bd671c64a50c427ce7231bb5f27", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.stdout index a263814c8a4..5b918224c86 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_296-10ab30d.stdout @@ -29,12 +29,9 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args, float* __workspace_9) { - int nn = __scalar_args.nn; int __dim_out_0 = __scalar_args.__dim_out_0; int __lb_out_0 = __scalar_args.__lb_out_0; - int __dim_out_1 = __scalar_args.__dim_out_1; int __lb_out_1 = __scalar_args.__lb_out_1; - int __dim_s_0 = __scalar_args.__dim_s_0; int __lb_s_0 = __scalar_args.__lb_s_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.json b/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.json index 8111814d5b5..c70a868f547 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_298-e543a30.stdout", - "stdout_hash": "3d091ebc71b8fffaee968524a52e1f0a06bf804a3224d2cbbe5ca045", + "stdout_hash": "4e28f430d3a3d4c6783ff1b8327024ed9a95b7d511d698149507a668", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.stdout index 029884ca5fb..0b29a533205 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_298-e543a30.stdout @@ -63,7 +63,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -91,7 +90,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( int __flat_idx; int __gpu_elem_i; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -135,7 +133,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_3( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -163,7 +160,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_4( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.json b/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.json index b8922526216..985695ee8f8 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_302-c945ed1.stdout", - "stdout_hash": "f1021900d0f8de07660fd5f42ca054903c56b6bf09ef7407e5b31fc0", + "stdout_hash": "b5b47d78f67794b80722bc5c24b3f707b84ad5b277a409b3e652268e", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.stdout index 7d913fd8a2c..e1f361c8b53 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_302-c945ed1.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; int __gpu_elem_i; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.json b/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.json index ed4fe92c8cb..52370cebffd 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_304-0ced324.stdout", - "stdout_hash": "560dcae0d6e6ccbdc74988b4012b3967927b02767e0dfcb0a1a73772", + "stdout_hash": "50e500c7965c29e469174d4828f2b1d1579a4f2e146138ce887f3001", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.stdout index b3c2dabcd12..0868cad7c9a 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_304-0ced324.stdout @@ -13,7 +13,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; int __gpu_elem_i; int i; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.json b/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.json index bd75aec7ea9..4fc68712290 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_307-eb7dd8e.stdout", - "stdout_hash": "dfb8a50d13ec328e56638d508ef190da5351b50bd4c7b5e708cb1bd9", + "stdout_hash": "50afe591e8ffa51f967d5cae1b4f7255a5fb01ef492ef63978e405d2", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.stdout index 2b9f949247b..1f68f1fdc08 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_307-eb7dd8e.stdout @@ -13,8 +13,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args, float* __workspace_2) { - int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.json b/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.json index e743450e414..69bdce2dbfb 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_309-c5214d3.stdout", - "stdout_hash": "027e6304b8a6fca4c3fc21b8a7cad2af5a3aed789baff2b508b3b7ee", + "stdout_hash": "d43f89c4f6ee0568f138089054a3ad9d5d8dbcf91216dae2f52e4d94", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.stdout index 2115baa01f8..0d5fd2227a8 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_309-c5214d3.stdout @@ -22,7 +22,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args, float* __workspace_3) { - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.json b/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.json index c06ba719fea..3f2cacbc8dc 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_310-c1a4744.stdout", - "stdout_hash": "21a7cbec50c12c8ce7240556934232577cf5802617516935aac7bfd7", + "stdout_hash": "f874ef7daa0c5975f3649f77b165494a8d34da1b81c4d144c34613d8", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.stdout index 87378b3b9e7..38253ca125f 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_310-c1a4744.stdout @@ -38,7 +38,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __workspace_2) { int nn = __scalar_args.nn; - int __dim_r_0 = __scalar_args.__dim_r_0; int __lb_r_0 = __scalar_args.__lb_r_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.json b/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.json index d8f1c304310..15cf2e540d8 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_316-6447449.stdout", - "stdout_hash": "5b5ec403ddf5698a82e8ef19195d4528a5d6452c499b203da47dcf82", + "stdout_hash": "466be5262268a5a8323b1a6efe8cd9c5d1fdd32365d525bc3e7298e0", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.stdout index fe959d3da40..074641d6ace 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_316-6447449.stdout @@ -25,7 +25,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __lb_p_0 = __scalar_args.__lb_p_0; int __dim_p_1 = __scalar_args.__dim_p_1; int __lb_p_1 = __scalar_args.__lb_p_1; - int __dim_p_2 = __scalar_args.__dim_p_2; int __lb_p_2 = __scalar_args.__lb_p_2; int __flat_idx; int i; @@ -57,7 +56,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __lb_p_0 = __scalar_args.__lb_p_0; int __dim_p_1 = __scalar_args.__dim_p_1; int __lb_p_1 = __scalar_args.__lb_p_1; - int __dim_p_2 = __scalar_args.__dim_p_2; int __lb_p_2 = __scalar_args.__lb_p_2; int __flat_idx; int i; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.json b/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.json index 7649a43c8a0..5adab5111ae 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_317-ecc259a.stdout", - "stdout_hash": "2701ce45a4b018b85871a25fabe3bd8cfbde12c0181d8782113eab92", + "stdout_hash": "d73cff5f043d91df1c7aa52bbb265920135fec7a807821ced2a50471", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.stdout index af3167e5245..f7bdc6ef007 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_317-ecc259a.stdout @@ -29,11 +29,9 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( { int __dim___gpu_gather_ops___upper__0 = __scalar_args.__dim___gpu_gather_ops___upper__0; int __lb___gpu_gather_ops___upper__0 = __scalar_args.__lb___gpu_gather_ops___upper__0; - int __dim___gpu_gather_ops___upper__1 = __scalar_args.__dim___gpu_gather_ops___upper__1; int __lb___gpu_gather_ops___upper__1 = __scalar_args.__lb___gpu_gather_ops___upper__1; int __dim___gpu_gather_ops_1__upper__0 = __scalar_args.__dim___gpu_gather_ops_1__upper__0; int __lb___gpu_gather_ops_1__upper__0 = __scalar_args.__lb___gpu_gather_ops_1__upper__0; - int __dim___gpu_gather_ops_1__upper__1 = __scalar_args.__dim___gpu_gather_ops_1__upper__1; int __lb___gpu_gather_ops_1__upper__1 = __scalar_args.__lb___gpu_gather_ops_1__upper__1; int __flat_idx; int i; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.json b/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.json index 3eeb3ed6645..f9ebc7fda83 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_318-5a5bfbd.stdout", - "stdout_hash": "2dc0d237dc610c45427e9faad7358169ae86dd231bd0a92c2d8d1485", + "stdout_hash": "dfb694c27af0b9cdbb92e9a0a034a4d9170582abfeb728b211d02b04", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.stdout index 9f8ba76eec1..d2ba1d27f92 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_318-5a5bfbd.stdout @@ -30,7 +30,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_sec_i; int __gpu_sec_i1; int k; - const int ny = 3; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.json b/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.json index 1af419a1fd7..b73dca38190 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_320-082cdda.stdout", - "stdout_hash": "98e5c57f4e8930db0f9fc20a523d1f3438272e074387663fc612b941", + "stdout_hash": "85446dcfd7e2585ffa1abd28333c49eff5809d5577b02600b6205bcf", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.stdout index 27efbe19f71..a016fa10d8d 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_320-082cdda.stdout @@ -22,9 +22,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* __data_self_op__a, __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) { - int __size_self_op__a = __scalar_args.__size_self_op__a; int __lb_self_op__a_dim1 = __scalar_args.__lb_self_op__a_dim1; - int __1__data_self_op__a = __scalar_args.__1__data_self_op__a; int __flat_idx; int i; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= 3)) { @@ -48,9 +46,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __data_self_op__a, __ScalarArgs___lfortran_gpu_kernel_1 __scalar_args) { - int __size_self_op__a = __scalar_args.__size_self_op__a; int __lb_self_op__a_dim1 = __scalar_args.__lb_self_op__a_dim1; - int __1__data_self_op__a = __scalar_args.__1__data_self_op__a; int __flat_idx; int i; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= 3)) { diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.json b/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.json index 598fb8ee636..351629d6f3a 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_328-cc3334c.stdout", - "stdout_hash": "e4a8ed57b1dcba844792e498965cf2b8d9a5f988856f0e45e0d618e1", + "stdout_hash": "5f767bffdddc77b9bcff702899849dd6aeac80d3a710d83cd55c8a26", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.stdout index a7a5ed98bc3..7ecaa4fca64 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_328-cc3334c.stdout @@ -1,7 +1,6 @@ #include __device__ inline void fixed_result_device_t_gpu_54(int n, float* r) { - const int width = 2; int __1__libasr_index_; int __do_loop_end; int __do_loop_end1; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.json b/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.json index 78b648c8aef..4f106e4e581 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_334-124b176.stdout", - "stdout_hash": "b5df98b3c3758c30ae957c191218af3bed4ac7a20623a9cd36e21c20", + "stdout_hash": "65442cd378dca77fe4fe2d2af90784876ddbfc61a0b95ec80fa5d9cd", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.stdout index fc1443c1340..cc60ae9dcfb 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_334-124b176.stdout @@ -12,7 +12,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -40,7 +39,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.json b/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.json index 2bf4a384a02..aab6fa12ba3 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_337-9610a4e.stdout", - "stdout_hash": "4f94aa76bc9d77726e9321a45553dc410d6297bdb332220311aab242", + "stdout_hash": "badc1044969e9952c82084f9953821be339cab1c12a90d084d83a301", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.stdout index 363c079a25a..22e4c4660f5 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_337-9610a4e.stdout @@ -12,7 +12,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int i; - const int n = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.json b/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.json index de2def84037..d88924fb599 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_391-0cf1271.stdout", - "stdout_hash": "0606cf07c177414a36c5b16ab0aa924217e6c642dbb5c68dce923694", + "stdout_hash": "43e240ed1ec81d67988ad74e469c301289ca1dd5e21fed69ad08ef9e", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.stdout index 0693d6205dc..3417b399e40 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_391-0cf1271.stdout @@ -29,7 +29,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; float* __gpu_heap_view___gpu_call_result; int i; - const int m = 8; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.json b/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.json index fd5628c0521..c249922998e 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_408-553c2f1.stdout", - "stdout_hash": "3d866b8fa3ccdc6c2f73ea09035cab63bfe70c09628d496f4d587ad3", + "stdout_hash": "9cd50c8979e271ac58a0fd8564ccc7bfefedc48d7fb3c0751a687ae1", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.stdout index ed8870165fb..8e8a1ee9b41 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_408-553c2f1.stdout @@ -88,7 +88,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_stop_code; int __gpu_stop_site; int i; - const int n = 64; __gpu_stop_site = 0; __gpu_stop_code = 0; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.json b/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.json index 68faff85b1f..17fad04e0a9 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_452-b86afe3.stdout", - "stdout_hash": "c694aed1c48d67e433eae05ea5ac4583035d7cbd9516045eef89cae5", + "stdout_hash": "be066782aeef4f94b52e93d890e4c22b798f86d1443326dc5533a410", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.stdout index f871a2d93c9..5e212877748 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_452-b86afe3.stdout @@ -47,7 +47,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_sum_k; float __gpu_sum_res; const int n = 3; - const int np = 2; int p; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.json b/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.json index e02996a5e9d..1eb9f5fc53a 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_453-087cbdb.stdout", - "stdout_hash": "f79985a43162ce12966801fca41ea38df935ce1ac14d13646f20cc78", + "stdout_hash": "f8df5221e2a836cd4e67bab97ee8b3ab21b90f4b9d3d20dddd43a697", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.stdout index 3635a02db08..31bbd97c508 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_453-087cbdb.stdout @@ -37,7 +37,6 @@ __device__ inline void twice_gpu_44(float* x, int __size_x_dim1, int __stride_x_ } __device__ inline void points_device_t_gpu_62(int p, int n, point_t* r) { - int __1_intent_out_dealloc_idx_; int __do_loop_end; int i; __do_loop_end = n; @@ -108,7 +107,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_sec_i1; int __gpu_sec_i2; const int n = 3; - const int np = 2; int p; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.json b/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.json index 6029c86cb24..f768ab7921d 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_455-ec807a4.stdout", - "stdout_hash": "edb134fd25365b4c6720108a2fd91aae8ba93f9b2e4de447ffec0254", + "stdout_hash": "1036588b5a1216a09d038fab83732527e026746382d0d070f9007c57", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.stdout index ce88c06747a..8f621c64706 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_455-ec807a4.stdout @@ -53,7 +53,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __gpu_mm_k5; const int m = 4; const int n = 3; - const int np = 2; int p; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json index 817bba7c597..3b328ac3152 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_474-0583450.stdout", - "stdout_hash": "f6f0f5651c82a9a53c4edd92d61d0080479570398c0f266be86eec64", + "stdout_hash": "38cc56d956d4d92cd39d7ec82a31895700742a32b04678ee18b0e728", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout index 39d38424a11..44a84176739 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.stdout @@ -15,7 +15,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int j; int k; const int m = 64; - const int n = 10000; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -57,7 +56,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __gpu_sec_i; int j; const int m = 64; - const int n = 10000; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -104,7 +102,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int j; - const int n = 10000; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.json b/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.json index 536141c59f9..5c7ab8f7673 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_476-6b797c7.stdout", - "stdout_hash": "b804252a7b704ff02e6913c35ee03b5fcbb598c0187358ad3455b0d7", + "stdout_hash": "b55d07215b7fa1a9e5514715ac487b991f0ce35621925b831d1cf3a3", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.stdout index 180a2d2b635..23afdbde242 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_476-6b797c7.stdout @@ -14,7 +14,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int j; int k; const int m = 150000; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } @@ -47,8 +46,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( float* __workspace_2) { int __gpu_private_shape = __scalar_args.__gpu_private_shape; - int n = __scalar_args.n; - int __dim_y_0 = __scalar_args.__dim_y_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; int __flat_idx; @@ -98,8 +95,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_2( { int __gpu_private_shape = __scalar_args.__gpu_private_shape; int m = __scalar_args.m; - int n = __scalar_args.n; - int __dim_y_0 = __scalar_args.__dim_y_0; int __loop_end_0 = __scalar_args.__loop_end_0; int __workspace_extent = __scalar_args.__workspace_extent; int __flat_idx; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.json b/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.json index c41ddcc2170..0f42eecfb69 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_477-3f086b7.stdout", - "stdout_hash": "8ae50e65a6e28677ee0bdb8ba33d46772b0a72c64e75d557d2be0e6f", + "stdout_hash": "5378fd95b1e4a2f26b4490e0188dfd21070a6b8395e1752cb1687ebd", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.stdout index 5519e43f6d6..0479fb87976 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_477-3f086b7.stdout @@ -41,7 +41,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float __gpu_scalar_argument; float* __libasr_created__subroutine_call_work; int j; - const int n = 4; float w[256]; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; @@ -92,7 +91,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_1( int __loop_end_0 = __scalar_args.__loop_end_0; int __flat_idx; int j; - const int n = 4; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.json b/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.json index af7d7f91d02..5136d07e033 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_478-5c1241e.stdout", - "stdout_hash": "8ca01d307d65f1d554cca745d04fd700a916110fe782b16fe19bc9bc", + "stdout_hash": "3cf14650618efe8b5a136d599dd1fb730040f08068900b88cba8b7ff", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.stdout index 8113065b28c..a87b7dfe64e 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_478-5c1241e.stdout @@ -11,9 +11,7 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( float* y, __ScalarArgs___lfortran_gpu_kernel_0 __scalar_args) { - int __lcompilers_t_extent_1 = __scalar_args.__lcompilers_t_extent_1; int m = __scalar_args.m; - int __dim_t_0 = __scalar_args.__dim_t_0; int __do_loop_end; int __flat_idx; int j; diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.json b/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.json index 39590267386..985769e2b46 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_479-7e99684.stdout", - "stdout_hash": "9dc278827717c80ec55d0e005ac1e950a700171dd5801c98602aeddb", + "stdout_hash": "1cbb05b39c023ec98c7646aa213ba8fee4bfe8956dc004ef75839cc1", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.stdout b/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.stdout index 8a6013d89c4..0d768c22bb2 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.stdout +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_479-7e99684.stdout @@ -18,7 +18,6 @@ extern "C" __global__ void __lfortran_gpu_kernel_0( int __flat_idx; int __gpu_bc_i; int j; - const int n = 32; if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; } diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.json b/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.json new file mode 100644 index 00000000000..48a2dbe4260 --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_metal_kernel-gpu_kernel_source_15-ddc1d80", + "cmd": "lfortran --no-color --gpu=metal --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_15.f90", + "infile_hash": "b548262f1790e25efae0005dfec351f092d5bd7ec7fc20b287feb76d", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.stdout", + "stdout_hash": "31ee2c378a32657d2df48da1e832b3656c97e20d89c74376ab93ad63", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.stdout b/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.stdout new file mode 100644 index 00000000000..fa609df2747 --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_15-ddc1d80.stdout @@ -0,0 +1,62 @@ +#include +using namespace metal; + +inline float twice_gpu_11(float v) { + float twice; + twice = (((float)2) * v); + return twice; +} + +struct __ScalarArgs___lfortran_gpu_kernel_0 { + float a; + int __dim_x_0; + int __lb_x_0; + int __dim_y_0; + int __lb_y_0; + int __dim_z_0; + int __lb_z_0; + int __dim_z_1; + int __lb_z_1; + int __loop_end_0; + int __gpu_lanes; +}; + +kernel void __lfortran_gpu_kernel_0( + device float* x [[buffer(0)]], + device float* y [[buffer(1)]], + device float* z [[buffer(2)]], + constant __ScalarArgs___lfortran_gpu_kernel_0& __scalar_args [[buffer(3)]], + uint __gpu_grid_thread [[thread_position_in_grid]], + uint __gpu_simd_lane [[thread_index_in_simdgroup]]) +{ + float a = __scalar_args.a; + int __lb_x_0 = __scalar_args.__lb_x_0; + int __lb_y_0 = __scalar_args.__lb_y_0; + int __dim_z_0 = __scalar_args.__dim_z_0; + int __lb_z_0 = __scalar_args.__lb_z_0; + int __lb_z_1 = __scalar_args.__lb_z_1; + int __loop_end_0 = __scalar_args.__loop_end_0; + int __gpu_lanes = __scalar_args.__gpu_lanes; + uint __thread_id = __gpu_grid_thread / (uint)__gpu_lanes; + int __gpu_lane = (int)(__gpu_grid_thread % (uint)__gpu_lanes); + int __flat_idx; + int i; + if ((((0 * 0) + __thread_id) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((0 * 0) + __thread_id); + i = (__flat_idx + 1); + { + float t; + t = (a * x[((int)(i) - (__lb_x_0))]); + if ((__gpu_lane == 0)) { + y[((int)(i) - (__lb_y_0))] = (t + y[((int)(i) - (__lb_y_0))]); + } + if (__gpu_lanes > 1) simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); + } + if ((__gpu_lane == 0)) { + z[((int)(i) - (__lb_z_0)) + (__dim_z_0 * ((int)(2) - (__lb_z_1)))] = twice_gpu_11(y[((int)(i) - (__lb_y_0))]); + } + if (__gpu_lanes > 1) simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); +} + diff --git a/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.json b/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.json index 14dfdc200e2..b8a300e1efa 100644 --- a/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.json +++ b/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_metal_kernel-gpu_metal_480-8fa07de.stdout", - "stdout_hash": "369906b53d6a2eb1cfd19f43b7c0b92fe5a6ad372a5023c4a9cf72f7", + "stdout_hash": "abb92a36e281fa01de65585e394c49e1252243bb43c6ab32bcb28004", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.stdout b/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.stdout index 734b11f29bc..ae2189bf37e 100644 --- a/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.stdout +++ b/tests/reference/gpu_metal_kernel-gpu_metal_480-8fa07de.stdout @@ -27,7 +27,6 @@ kernel void __lfortran_gpu_kernel_0( uint __thread_id = __gpu_grid_thread / (uint)__gpu_lanes; int __gpu_lane = (int)(__gpu_grid_thread % (uint)__gpu_lanes); int __flat_idx; - const int count = 65; int i; if ((((0 * 0) + __thread_id) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { return; diff --git a/tests/tests.toml b/tests/tests.toml index 6eaf43787bc..14ddd724418 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -4846,6 +4846,11 @@ filename = "../integration_tests/gpu_kernel_source_13.f90" gpu_metal_kernel = true gpu_cuda_kernel = true +[[test]] +filename = "../integration_tests/gpu_kernel_source_15.f90" +gpu_cuda_kernel = true +gpu_metal_kernel = true + [[test]] filename = "errors/array_bounds_check_01.f90" run = true From 0dadf0cb9bd98d9bf06a9c17722f52cca9218ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 03:36:27 +0000 Subject: [PATCH 14/19] fix: evaluate each operand of a defined operator once A type-bound defined operator such as `mk(3.) - mk(1.)` is represented as a call whose passed-object argument and dispatch expression (`m_dt`) are the same expression node. The array_struct_temporary and subroutine_from_function passes saved the argument in a temporary but then saved `m_dt` in a second temporary, so the left operand was evaluated twice (three function calls instead of two). This also affected operands returned as polymorphic allocatable results. When the passed-object argument has been replaced by a temporary, use that temporary as the dispatch expression too. Fixes #15572 --- integration_tests/CMakeLists.txt | 1 + integration_tests/operator_overloading_46.f90 | 204 ++++++++++++++++++ src/libasr/pass/array_struct_temporary.cpp | 24 +++ src/libasr/pass/array_struct_temporary.h | 6 + src/libasr/pass/subroutine_from_function.cpp | 20 +- 5 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 integration_tests/operator_overloading_46.f90 diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 5cf6e1bc431..382a98d975e 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -2644,6 +2644,7 @@ RUN(NAME operator_overloading_42 LABELS gfortran llvm) RUN(NAME operator_overloading_43 LABELS gfortran llvm) RUN(NAME operator_overloading_44 LABELS gfortran llvm) RUN(NAME operator_overloading_45 LABELS gfortran llvm) +RUN(NAME operator_overloading_46 LABELS gfortran llvm) RUN(NAME custom_unary_operator_01 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc) RUN(NAME custom_unary_operator_02 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc) diff --git a/integration_tests/operator_overloading_46.f90 b/integration_tests/operator_overloading_46.f90 new file mode 100644 index 00000000000..a3e9ca6a861 --- /dev/null +++ b/integration_tests/operator_overloading_46.f90 @@ -0,0 +1,204 @@ +module operator_overloading_46_mod + implicit none + integer :: ncalls = 0 + + type :: div_t + real, allocatable :: v(:) + contains + generic :: operator(-) => dminus + generic :: operator(.neg.) => dneg + procedure :: dminus + procedure :: dneg + end type + + type :: vec_t + real, allocatable :: v(:) + contains + generic :: operator(.div.) => vdiv + procedure :: vdiv + end type + + type :: sc_t + real, allocatable :: v(:) + contains + generic :: assignment(=) => assign_div + procedure :: assign_div + end type + + type :: pt_t + real :: x = 0 + contains + generic :: operator(+) => padd + procedure :: padd + end type + + type :: base_t + integer :: k = 0 + contains + generic :: operator(*) => bmul + generic :: operator(+) => badd + procedure :: bmul + procedure :: badd + end type + + type, extends(base_t) :: child_t + contains + procedure :: bmul => cmul + procedure :: badd => cadd + end type + + interface operator(+) + module procedure dplus + end interface + +contains + + function mk(x) result(d) + real, intent(in) :: x + type(div_t) :: d + ncalls = ncalls + 1 + d%v = [x, x] + end function + + function mkp(x) result(p) + real, intent(in) :: x + type(pt_t) :: p + ncalls = ncalls + 1 + p%x = x + end function + + function mkc(k) result(c) + integer, intent(in) :: k + class(base_t), allocatable :: c + ncalls = ncalls + 1 + allocate(child_t :: c) + c%k = k + end function + + function dminus(a, b) result(d) + class(div_t), intent(in) :: a, b + type(div_t) :: d + d%v = a%v - b%v + end function + + function dneg(a) result(d) + class(div_t), intent(in) :: a + type(div_t) :: d + d%v = -a%v + end function + + function dplus(a, b) result(d) + type(div_t), intent(in) :: a, b + type(div_t) :: d + d%v = a%v + b%v + end function + + function vdiv(self) result(d) + class(vec_t), intent(in) :: self + type(div_t) :: d + ncalls = ncalls + 1 + d%v = 2*self%v + end function + + subroutine assign_div(lhs, rhs) + class(sc_t), intent(inout) :: lhs + type(div_t), intent(in) :: rhs + if (allocated(lhs%v)) deallocate(lhs%v) + allocate(lhs%v, source=rhs%v) + end subroutine + + function padd(a, b) result(p) + class(pt_t), intent(in) :: a, b + type(pt_t) :: p + p%x = a%x + b%x + end function + + function bmul(a, b) result(r) + class(base_t), intent(in) :: a, b + integer :: r + r = a%k * b%k + end function + + function cmul(a, b) result(r) + class(child_t), intent(in) :: a + class(base_t), intent(in) :: b + integer :: r + r = 10 * a%k * b%k + end function + + function badd(a, b) result(r) + class(base_t), intent(in) :: a, b + type(base_t) :: r + r%k = a%k + b%k + end function + + function cadd(a, b) result(r) + class(child_t), intent(in) :: a + class(base_t), intent(in) :: b + type(base_t) :: r + r%k = 100 + a%k + b%k + end function + +end module + +program operator_overloading_46 + use operator_overloading_46_mod + implicit none + type(div_t) :: r + type(vec_t) :: a, b + type(sc_t) :: s + type(pt_t) :: p + type(base_t) :: q + integer :: k + + ncalls = 0 + r = mk(3.) - mk(1.) + print *, ncalls, r%v + if (ncalls /= 2) error stop + if (any(abs(r%v - 2.) > 1e-6)) error stop + + ncalls = 0 + r = .neg. mk(3.) + print *, ncalls, r%v + if (ncalls /= 1) error stop + if (any(abs(r%v + 3.) > 1e-6)) error stop + + ncalls = 0 + r = mk(3.) + mk(1.) + print *, ncalls, r%v + if (ncalls /= 2) error stop + if (any(abs(r%v - 4.) > 1e-6)) error stop + + ncalls = 0 + r = mk(5.) - mk(2.) - mk(1.) + print *, ncalls, r%v + if (ncalls /= 3) error stop + if (any(abs(r%v - 2.) > 1e-6)) error stop + + allocate(a%v(3), b%v(3)) + a%v = [1., 2., 3.] + b%v = [5., 5., 5.] + ncalls = 0 + s = .div. a - .div. b + print *, ncalls, s%v + if (ncalls /= 2) error stop + if (any(abs(s%v - [-8., -6., -4.]) > 1e-6)) error stop + + ncalls = 0 + p = mkp(3.) + mkp(1.) + print *, ncalls, p%x + if (ncalls /= 2) error stop + if (abs(p%x - 4.) > 1e-6) error stop + + ncalls = 0 + k = mkc(2) * mkc(3) + print *, ncalls, k + if (ncalls /= 2) error stop + if (k /= 60) error stop + + ncalls = 0 + q = mkc(2) + mkc(3) + print *, ncalls, q%k + if (ncalls /= 2) error stop + if (q%k /= 105) error stop +end program diff --git a/src/libasr/pass/array_struct_temporary.cpp b/src/libasr/pass/array_struct_temporary.cpp index c6188d9b432..f369ecf707a 100644 --- a/src/libasr/pass/array_struct_temporary.cpp +++ b/src/libasr/pass/array_struct_temporary.cpp @@ -1670,6 +1670,26 @@ ASR::Variable_t* designator_root_variable(ASR::expr_t* value) { return nullptr; } +// The passed-object actual of a type-bound call is the same expression as the +// dispatch expression `m_dt`, e.g. `mk(3.)` in `mk(3.) - mk(1.)` with a +// type-bound operator. Once the actual `original` has been replaced by +// `prepared`, the dispatch uses `prepared` too, so that the operand is +// evaluated only once. A designator has no side effects and is kept. +ASR::expr_t* passed_object_dispatch(ASR::expr_t* dt, ASR::expr_t* original, + ASR::expr_t* prepared) { + if( dt == nullptr || dt != original || prepared == original ) { + return dt; + } + ASR::expr_t* value = ASRUtils::get_past_array_physical_cast(dt); + if( ASR::is_a(*value) || + ASR::is_a(*value) || + ASR::is_a(*value) || + ASR::is_a(*value) ) { + return dt; + } + return prepared; +} + // A component of an array of derived type, such as `ps%x` or `ps(1::2)%y`, is // a strided section of `ps`: its elements are one struct apart, not one // element apart. It therefore has to be gathered into a contiguous temporary @@ -3541,6 +3561,10 @@ class ReplaceExprWithTemporary: public ASR::BaseExprReplacern_args; i++) { + x->m_dt = passed_object_dispatch(x->m_dt, original_args[i], + x->m_args[i].m_value); + } if (ASRUtils::is_elemental(x->m_name)) { for (size_t i = 0; i < x->n_args; i++) { if (x->m_args[i].m_value && ASRUtils::is_array( diff --git a/src/libasr/pass/array_struct_temporary.h b/src/libasr/pass/array_struct_temporary.h index 120b90b120e..34bc7706b55 100644 --- a/src/libasr/pass/array_struct_temporary.h +++ b/src/libasr/pass/array_struct_temporary.h @@ -20,6 +20,12 @@ namespace LCompilers { ASR::expr_t* value, Vec* current_body, ASR::expr_t* rank_source = nullptr); + // The dispatch expression of a type-bound call after its passed-object + // actual `original`, which is the same expression as `dt`, has been + // replaced by `prepared`, so that the operand is evaluated only once. + ASR::expr_t* passed_object_dispatch(ASR::expr_t* dt, ASR::expr_t* original, + ASR::expr_t* prepared); + void pass_array_struct_temporary(Allocator &al, ASR::TranslationUnit_t &unit, const PassOptions &pass_options); diff --git a/src/libasr/pass/subroutine_from_function.cpp b/src/libasr/pass/subroutine_from_function.cpp index 26a0bc5431b..6cf47cc8a18 100644 --- a/src/libasr/pass/subroutine_from_function.cpp +++ b/src/libasr/pass/subroutine_from_function.cpp @@ -683,8 +683,17 @@ public : } void replace_FunctionCall(ASR::FunctionCall_t* x){ + std::vector original_args; + for (size_t i = 0; i < x->n_args; i++) { + original_args.push_back(x->m_args[i].m_value); + } traverse_functionCall_args(x->m_args, x->n_args); - if (x->m_dt) { + ASR::expr_t* dt = x->m_dt; + for (size_t i = 0; i < x->n_args; i++) { + x->m_dt = passed_object_dispatch(x->m_dt, original_args[i], + x->m_args[i].m_value); + } + if (x->m_dt && x->m_dt == dt) { ASR::expr_t** current_expr_copy = current_expr; current_expr = &(x->m_dt); replace_expr(x->m_dt); @@ -1241,13 +1250,20 @@ class ReplaceFunctionCallWithSubroutineCallVisitor: // We skip the generic expression visitor on this statement, so // ensure nested calls inside the function call arguments are still replaced. + std::vector original_args; for (size_t i = 0; i < fc->n_args; i++) { + original_args.push_back(fc->m_args[i].m_value); ASR::expr_t** current_expr_copy = current_expr; current_expr = &fc->m_args[i].m_value; call_replacer(); current_expr = current_expr_copy; } - if (fc->m_dt) { + ASR::expr_t* dt = fc->m_dt; + for (size_t i = 0; i < fc->n_args; i++) { + fc->m_dt = passed_object_dispatch(fc->m_dt, original_args[i], + fc->m_args[i].m_value); + } + if (fc->m_dt && fc->m_dt == dt) { ASR::expr_t** current_expr_copy = current_expr; current_expr = &fc->m_dt; call_replacer(); From f13ef2469168a97fd72c1c3a3a12b5ff3cbcd657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 03:43:56 +0000 Subject: [PATCH 15/19] fix: forget tracked counters across calls in GPU array privatization Review follow-up to the per-iteration array privatization. The element tracking kept the known value of an integer local across an assignment like `y = f(k)`, where `f` may change `k` through an intent(inout) argument; `t(k) = ...` was then counted as the wrong element and `t` taken as fully defined. That analysis also runs on the statements after the loop, where impure calls are allowed, so a conforming program lost a value the loop left in `t(1)`. Now only `k = e` with `e` a known call-free value, and an element definition whose value calls nothing but pure functions, keep what is known; any other statement (assignment to anything else, including an associate name of a local, a call, a loop, input) forgets every counter. The diagnostic for an array of LOCAL locality that cannot be given a copy per thread now says why: its type (e.g. type(pair)), that it is a coarray, that an associate construct around the loop names it, or that the body has an associate construct the kernel cannot inline. Also factor the element-type check and the body-name collection into helpers, and document the contract of locality_spec_variables. New tests: gpu_kernel_source_16 (runs everywhere, with CUDA and Metal kernel references) keeps `t` a shared buffer when a call changes the counter after the loop and `u` shared when only part of it is defined before an untouched element is read; gpu_decline_18 and gpu_decline_19 cover the two associate diagnostics. --- integration_tests/CMakeLists.txt | 3 + integration_tests/gpu_decline_17.f90 | 2 +- integration_tests/gpu_decline_18.f90 | 26 +++ integration_tests/gpu_decline_19.f90 | 27 +++ integration_tests/gpu_kernel_source_16.f90 | 53 ++++++ src/libasr/pass/gpu_decline.cpp | 17 +- src/libasr/pass/gpu_decline.h | 12 +- src/libasr/pass/gpu_offload_privatize.cpp | 171 ++++++++++-------- src/libasr/pass/gpu_offload_visitor.h | 8 +- ...a_kernel-gpu_kernel_source_16-ce4a711.json | 13 ++ ...kernel-gpu_kernel_source_16-ce4a711.stdout | 49 +++++ ...l_kernel-gpu_kernel_source_16-6d4e811.json | 13 ++ ...kernel-gpu_kernel_source_16-6d4e811.stdout | 90 +++++++++ ...u_offload_cuda-gpu_decline_17-d2b52ed.json | 4 +- ...offload_cuda-gpu_decline_17-d2b52ed.stderr | 4 +- ...u_offload_cuda-gpu_decline_18-b238281.json | 13 ++ ...offload_cuda-gpu_decline_18-b238281.stderr | 9 + ...u_offload_cuda-gpu_decline_19-13fd5d9.json | 13 ++ ...offload_cuda-gpu_decline_19-13fd5d9.stderr | 9 + tests/tests.toml | 13 ++ 20 files changed, 463 insertions(+), 86 deletions(-) create mode 100644 integration_tests/gpu_decline_18.f90 create mode 100644 integration_tests/gpu_decline_19.f90 create mode 100644 integration_tests/gpu_kernel_source_16.f90 create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.json create mode 100644 tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.stdout create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.json create mode 100644 tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.stdout create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.json create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.stderr create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.json create mode 100644 tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.stderr diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index a79980d4d1f..cc1088a1bdc 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6425,6 +6425,8 @@ RUN(NAME gpu_decline_14 LABELS gfortran llvm) RUN(NAME gpu_decline_15 LABELS gfortran llvm) RUN(NAME gpu_decline_16 LABELS gfortran llvm) RUN(NAME gpu_decline_17 LABELS gfortran llvm) +RUN(NAME gpu_decline_18 LABELS gfortran llvm) +RUN(NAME gpu_decline_19 LABELS gfortran llvm) # One program per entry of the GPU unsupported list. Each runs on the CPU with # --gpu-allow-cpu-fallback where its loop is on the list, and the error @@ -6452,6 +6454,7 @@ RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_kernel_source_14 LABELS gfortran llvm metal cuda cuda_cpu) +RUN(NAME gpu_kernel_source_16 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME real128_arith_01 LABELS gfortran llvm) RUN(NAME real128_arith_02 LABELS gfortran llvm) diff --git a/integration_tests/gpu_decline_17.f90 b/integration_tests/gpu_decline_17.f90 index b8c959e1cb8..7c58208fa87 100644 --- a/integration_tests/gpu_decline_17.f90 +++ b/integration_tests/gpu_decline_17.f90 @@ -1,4 +1,4 @@ -! gpu decline reason: LocalityNotPrivate +! gpu decline reason: LocalityElementType ! An array of LOCAL locality is a new array in each iteration. Each thread ! needs a copy of its own, and an array of derived type is not one a thread ! can hold as a local yet: one buffer shared by every thread would be a diff --git a/integration_tests/gpu_decline_18.f90 b/integration_tests/gpu_decline_18.f90 new file mode 100644 index 00000000000..42628e550f3 --- /dev/null +++ b/integration_tests/gpu_decline_18.f90 @@ -0,0 +1,26 @@ +! gpu decline reason: LocalityNamedByAssociate +! An array of LOCAL locality is a new array in each iteration, but an +! associate name of the construct around the loop still names the array +! outside it. The kernel resolves that name to the array itself, so it +! cannot tell the two apart, and the loop is not offloaded. +program gpu_decline_18 +implicit none +integer, parameter :: n = 1000 +real :: x(n), g(n), t(2) +integer :: j +do j = 1, n + x(j) = real(j) +end do +t = [10.0, 20.0] +associate (a => t) + do concurrent (j = 1:n) local(t) + t(1) = x(j) + t(2) = a(2) + g(j) = t(1) + t(2) + end do +end associate +do j = 1, n + if (abs(g(j) - (x(j) + 20.0)) > 1.0e-3) error stop +end do +print *, "ok" +end program diff --git a/integration_tests/gpu_decline_19.f90 b/integration_tests/gpu_decline_19.f90 new file mode 100644 index 00000000000..1522da3e781 --- /dev/null +++ b/integration_tests/gpu_decline_19.f90 @@ -0,0 +1,27 @@ +! gpu decline reason: LocalityAssociateNotInlined +! An array of LOCAL locality is a new array in each iteration, which the +! kernel makes a local of a BLOCK around the loop body. An ASSOCIATE inside +! an IF of the body is not one the kernel inlines into that BLOCK, so the +! array cannot be given a copy per thread, and the loop is not offloaded. +program gpu_decline_19 +implicit none +integer, parameter :: n = 1000 +real :: x(n), g(n), t(2) +integer :: j +do j = 1, n + x(j) = real(j) +end do +do concurrent (j = 1:n) local(t) + if (j > 0) then + associate (e => 2.0 * x(j)) + t(1) = x(j) + t(2) = e + g(j) = t(1) + t(2) + end associate + end if +end do +do j = 1, n + if (abs(g(j) - 3.0 * x(j)) > 1.0e-3) error stop +end do +print *, "ok" +end program diff --git a/integration_tests/gpu_kernel_source_16.f90 b/integration_tests/gpu_kernel_source_16.f90 new file mode 100644 index 00000000000..f68b366dc32 --- /dev/null +++ b/integration_tests/gpu_kernel_source_16.f90 @@ -0,0 +1,53 @@ +module gpu_kernel_source_16_m +implicit none +contains + integer function bump(m) + integer, intent(inout) :: m + m = 2 + bump = 0 + end function +end module + +program gpu_kernel_source_16 + ! Arrays that must stay buffers every thread shares, which the + ! reference kernel source checks: making either a local of the thread + ! would change what the program computes. + use gpu_kernel_source_16_m + implicit none + integer, parameter :: n = 8 + real :: t(2), u(2), x(n), g(n) + integer :: j, k, y + + do j = 1, n + x(j) = real(j) + end do + + ! Each iteration defines `t` whole, but after the loop `t(1)` is read + ! before it is defined again: the call changes `k`, so `t(k) = 5.0` + ! defines `t(2)`, not `t(1)`, and `t(1)` keeps the value the loop + ! left there. + do concurrent (j = 1:1) + t = x(j) + 41.0 + g(j) = t(1) + end do + k = 1 + y = bump(k) + t(k) = 5.0 + t(2) = 5.0 + if (y /= 0 .or. k /= 2) error stop 1 + if (abs(t(1) - 42.0) > 1.0e-5) error stop 2 + + ! Each iteration defines only `u(1)`, the same element twice, and + ! then reads `u(2)`, which keeps the value it had before the loop. + u(2) = 9.0 + do concurrent (j = 1:n) + k = 1 + u(k) = 1.0 + u(k + 1 - 1) = 1.0 + g(j) = u(1) + u(2) + x(j) + end do + do j = 1, n + if (abs(g(j) - (10.0 + x(j))) > 1.0e-5) error stop 3 + end do + print *, "ok" +end program diff --git a/src/libasr/pass/gpu_decline.cpp b/src/libasr/pass/gpu_decline.cpp index b45996283e6..800d653224b 100644 --- a/src/libasr/pass/gpu_decline.cpp +++ b/src/libasr/pass/gpu_decline.cpp @@ -167,9 +167,20 @@ std::string gpu_decline_message(const GpuDecline &decline) { case GpuDeclineReason::UnsizedLocalArray: return "local array '" + decline.name + "' has no extent the gpu can use"; - case GpuDeclineReason::LocalityNotPrivate: - return "array '" + decline.name + "' of local locality " - "cannot be given a copy per gpu thread"; + case GpuDeclineReason::LocalityElementType: + return "array '" + decline.name + "' of local locality is of " + "type " + decline.type_name + ", which a gpu thread cannot " + "hold a copy of"; + case GpuDeclineReason::LocalityCoarray: + return "array '" + decline.name + "' of local locality is a " + "coarray, which a gpu thread cannot hold a copy of"; + case GpuDeclineReason::LocalityNamedByAssociate: + return "array '" + decline.name + "' of local locality is " + "named by an associate construct around the loop"; + case GpuDeclineReason::LocalityAssociateNotInlined: + return "array '" + decline.name + "' of local locality cannot " + "be given a copy per gpu thread: the loop body has an " + "associate construct the gpu kernel cannot inline"; case GpuDeclineReason::AliasTemporaryRuntimeSized: return "an aliased assignment needs a run-time sized temporary"; case GpuDeclineReason::UngatherableStridedSection: diff --git a/src/libasr/pass/gpu_decline.h b/src/libasr/pass/gpu_decline.h index 26226fa0889..f7e3c3951dd 100644 --- a/src/libasr/pass/gpu_decline.h +++ b/src/libasr/pass/gpu_decline.h @@ -132,8 +132,13 @@ enum class GpuDeclineReason { StructElementGather, UnsizedLocalArray, // An array of LOCAL locality that a thread cannot hold a copy of its - // own of. - LocalityNotPrivate, + // own of: its type is not one a thread holds as a local, it is a + // coarray, an ASSOCIATE around the loop names it, or the body has an + // ASSOCIATE the kernel cannot inline. + LocalityElementType, + LocalityCoarray, + LocalityNamedByAssociate, + LocalityAssociateNotInlined, AliasTemporaryRuntimeSized, UngatherableStridedSection, // A section passed to a procedure has to be copied into a contiguous @@ -265,6 +270,9 @@ struct GpuDecline { // The element type the decline is about, when the reason is about a // type, which the message names. ASR::ttype_t *type = nullptr; + // The declared type of the variable as the source spells it, for a + // type `type` cannot name by itself (a derived type). + std::string type_name; // Where the section is evaluated, when the reason is about a section, // and why no copy placed before the statement serves it. GpuSectionSite site = GpuSectionSite::Statement; diff --git a/src/libasr/pass/gpu_offload_privatize.cpp b/src/libasr/pass/gpu_offload_privatize.cpp index 2ee56e3dcbd..75e8c253fb5 100644 --- a/src/libasr/pass/gpu_offload_privatize.cpp +++ b/src/libasr/pass/gpu_offload_privatize.cpp @@ -70,11 +70,6 @@ class GpuArrayAccess { return conflicts(acc, path, routine); } - // The same question asked about another variable of the procedure. - GpuArrayAccess of(ASR::symbol_t *other) { - return GpuArrayAccess(other, routine, pointers, outside); - } - SymbolTable *procedure() const { return routine; } private: @@ -188,6 +183,22 @@ class GpuScopedConstructs } }; +// Whether a thread can hold a copy of its own of a variable whose +// elements are of type `elem`. +bool gpu_private_element_type(ASR::ttype_t *elem) { + return ASR::is_a(*elem) || ASR::is_a(*elem) + || ASR::is_a(*elem) + || ASR::is_a(*elem); +} + +// The variables the statements of a loop body name. +std::set gpu_body_names(const ParallelLoopNest &work) { + std::set named; + VarSymbolCollector c(named); + for (size_t i = 0; i < work.n_body; i++) c.visit_stmt(*work.body[i]); + return named; +} + // What a run of statements does with the value an array held when the // run was entered. // Untouched -- never reads it: the array is not accessed, or it is first @@ -305,9 +316,14 @@ class GpuArrayFlowReader { } // Follows the integer locals a statement the run went on past - // assigns. Any statement other than such an assignment, or the - // definition of an element, may change them in ways not followed - // here, and forgets them all. + // assigns. Only two kinds of statement keep what is known: `k = e` + // where `k` is such a local and `e` a value `evaluate` knows, which + // calls nothing; and the definition of an element (`element`), which + // calls no procedure that is not pure, and so changes no local but + // its target. Every other statement -- an assignment to anything + // else (an associate name of a local among them), a call, a loop, + // an input statement -- may change one in ways not followed here, + // and forgets them all. void count(ASR::stmt_t *s) { if (ASR::is_a(*s)) { ASR::Assignment_t *a = ASR::down_cast(s); @@ -316,20 +332,39 @@ class GpuArrayFlowReader { ASR::symbol_t *t = ASR::down_cast( a->m_target)->m_v; int64_t v = 0; - bool known = trackable(t) && evaluate(a->m_value, v); - counters.erase(t); - if (known) { + if (trackable(t) && evaluate(a->m_value, v)) { counters[t] = v; - } else if (access.of(t).expr(a->m_value)) { - counters.clear(); + return; } + } else if (element(s, nullptr)) { return; } - if (element(s, nullptr)) return; } counters.clear(); } + // Whether `e` may call a procedure that is not pure, which may change + // a local passed to it or reached through a pointer. A pure function + // changes neither its arguments nor anything outside it (F2018 + // 15.7, C1583, C1594). + static bool calls_impure(ASR::expr_t *e) { + struct Calls : public ASR::BaseWalkVisitor { + bool found = false; + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + ASR::symbol_t *f = ASRUtils::symbol_get_past_external( + x.m_name); + if (!ASR::is_a(*f) || + !ASRUtils::get_FunctionType( + ASR::down_cast(f))->m_pure) { + found = true; + } + ASR::BaseWalkVisitor::visit_FunctionCall(x); + } + } calls; + calls.visit_expr(*e); + return calls.found; + } + // Whether an element of the array, its subscripts values known here, // is one the run has defined; `offset` is set to its position in // array element order. @@ -385,7 +420,7 @@ class GpuArrayFlowReader { // `t(i1, ..., ir) = v`, each subscript a value known here within the // declared bounds of its dimension, where `v` reads `t` only through - // elements defined before and names no integer local followed here. + // elements defined before and calls no procedure that is not pure. // `offset` is set to the element's position in array element order. bool element(ASR::stmt_t *s, int64_t *offset) { if (!ASR::is_a(*s)) return false; @@ -395,9 +430,7 @@ class GpuArrayFlowReader { !reads_defined(a->m_value)) { return false; } - for (auto &c : counters) { - if (access.of(c.first).expr(a->m_value)) return false; - } + if (calls_impure(a->m_value)) return false; int64_t position = 0; if (!known_element(*ASR::down_cast(a->m_target), position, false)) { @@ -832,8 +865,9 @@ bool read_after_region(GpuArrayFlowReader &reader, // path through the body that accesses it first defines all of it -- by // an assignment to the whole array, by a nest of DO loops over its full // declared extent, or by assignments to each of its elements in turn, as -// the lowering of an array constructor fills its temporary -- and no statement that can run after the loop, however -// a jump gets there, may read it before it is defined again. So no +// the lowering of an array constructor fills its temporary -- and no +// statement that can run after the loop, however a jump gets there, may +// read it before it is defined again. So no // iteration reads a value it did not define, whether every iteration, // some or none define the array, and nothing after the loop reads what // they defined. It is a local, non-saved variable that no pointer and no @@ -900,13 +934,7 @@ GpuOffloadVisitor::iteration_array_candidates( if (s == proc_scope) break; } - std::set named; - { - VarSymbolCollector c(named); - for (size_t i = 0; i < work.n_body; i++) { - c.visit_stmt(*work.body[i]); - } - } + std::set named = gpu_body_names(work); // What the procedures contained in this one name, which they reach by // host association. @@ -955,13 +983,7 @@ GpuOffloadVisitor::iteration_array_candidates( continue; } ASR::Array_t *arr = ASR::down_cast(v->m_type); - ASR::ttype_t *elem = arr->m_type; - if (!ASR::is_a(*elem) && - !ASR::is_a(*elem) && - !ASR::is_a(*elem) && - !ASR::is_a(*elem)) { - continue; - } + if (!gpu_private_element_type(arr->m_type)) continue; GpuArrayAccess access(sym, proc_scope, pointers, outside); bool named_outside_body = false; for (size_t d = 0; d < work.n_heads(); d++) { @@ -994,25 +1016,16 @@ GpuOffloadVisitor::iteration_array_candidates( return candidates; } -// A variable of LOCAL locality (the OMPPrivate clause of the canonical -// region, from `local(t)` or an OpenMP `private(t)`) is a construct -// entity: each iteration has its own, undefined on entry, and the -// variable outside the loop is not affected by it (Fortran 2018, -// 11.1.7.5). It becomes a local of the BLOCK around the body, with no -// analysis of the body. False, when an array the body names is not one -// the kernel can hold as a local of a thread: its one buffer would be -// shared by every thread. +// A variable of LOCAL locality (`local(t)`, the OMPPrivate clause of the +// canonical region) is a construct entity: each iteration has its own, +// undefined on entry, and the variable outside the loop is not affected +// by it (Fortran 2018, 11.1.7.5). It becomes a local of the BLOCK around +// the body, with no analysis of the body. bool GpuOffloadVisitor::locality_spec_variables( const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, const std::map &enclosing_assoc_map, - std::vector &local, std::string &rejected) { - std::set named; - { - VarSymbolCollector c(named); - for (size_t i = 0; i < work.n_body; i++) { - c.visit_stmt(*work.body[i]); - } - } + std::vector &local, GpuDecline &rejected) { + std::set named = gpu_body_names(work); std::set indices; for (size_t d = 0; d < work.n_heads(); d++) { if (work.head(d).m_v && ASR::is_a(*work.head(d).m_v)) { @@ -1037,33 +1050,44 @@ bool GpuOffloadVisitor::locality_spec_variables( if (!ASR::is_a(*clause->m_vars[k])) continue; ASR::symbol_t *sym = ASR::down_cast( clause->m_vars[k])->m_v; - if (!named.count(sym) || indices.count(sym) || + if (!ASR::is_a(*sym) || !named.count(sym) || + indices.count(sym) || std::find(local.begin(), local.end(), sym) != local.end()) { continue; } - bool array = ASR::is_a(*sym) && - ASRUtils::is_array(ASRUtils::symbol_type(sym)); - ASR::ttype_t *elem = ASR::is_a(*sym) - ? ASRUtils::type_get_past_array(ASRUtils::symbol_type(sym)) - : nullptr; - bool holdable = elem != nullptr && inlined && - !in_associates.count(sym) && - ASR::down_cast(sym)->n_codims == 0 && - (ASR::is_a(*elem) || - ASR::is_a(*elem) || - ASR::is_a(*elem) || - ASR::is_a(*elem)); - if (!holdable) { - // A scalar is still a local of each thread when the body - // assigns it (see visit_OMPRegion); an array is a buffer. - if (array) { - rejected = ASRUtils::symbol_name(sym); - return false; - } + ASR::Variable_t *v = ASR::down_cast(sym); + ASR::ttype_t *elem = ASRUtils::type_get_past_array(v->m_type); + GpuDeclineReason why = GpuDeclineReason::None; + if (!gpu_private_element_type(elem)) { + why = GpuDeclineReason::LocalityElementType; + } else if (v->n_codims > 0) { + why = GpuDeclineReason::LocalityCoarray; + } else if (in_associates.count(sym)) { + why = GpuDeclineReason::LocalityNamedByAssociate; + } else if (!inlined) { + why = GpuDeclineReason::LocalityAssociateNotInlined; + } + if (why == GpuDeclineReason::None) { + local.push_back(sym); continue; } - local.push_back(sym); + // A scalar the body assigns is still a local of each thread + // (see visit_OMPRegion); an array would be one buffer that + // every thread shares. + if (ASRUtils::is_array(v->m_type)) { + rejected = GpuDecline(why, v->m_name); + rejected.type_name = ASRUtils::type_to_str_fortran_symbol( + elem, v->m_type_declaration, true); + if (ASR::is_a(*elem) && + !ASR::down_cast(elem) + ->m_is_unlimited_polymorphic) { + rejected.type_name = (ASR::down_cast( + elem)->m_is_cstruct ? "type(" : "class(") + + rejected.type_name + ")"; + } + return false; + } } } return true; @@ -1076,11 +1100,10 @@ bool GpuOffloadVisitor::privatize_iteration_arrays( const std::map &enclosing_assoc_map, Vec &private_shapes) { std::vector privatized; - std::string rejected; + GpuDecline rejected; if (!locality_spec_variables(region, work, enclosing_assoc_map, privatized, rejected)) { - report_not_offloaded(region.base.base.loc, - GpuDecline(GpuDeclineReason::LocalityNotPrivate, rejected)); + report_not_offloaded(region.base.base.loc, rejected); return false; } for (ASR::symbol_t *sym : iteration_array_candidates(region, work, diff --git a/src/libasr/pass/gpu_offload_visitor.h b/src/libasr/pass/gpu_offload_visitor.h index 4a8a3bd5585..a2105d4e4dc 100644 --- a/src/libasr/pass/gpu_offload_visitor.h +++ b/src/libasr/pass/gpu_offload_visitor.h @@ -558,11 +558,15 @@ class GpuOffloadVisitor : public ASR::StatementWalkVisitor const std::map &enclosing_assoc_map, Vec &private_shapes); - // The variables of LOCAL locality the body names. + // Appends to `local` the variables of LOCAL locality that the body + // names and a thread can hold a copy of its own of. A scalar it + // cannot is left alone. An array it cannot makes it return false, + // with `rejected` set to the decline that names the array and why; + // the caller reports it, and the loop is not offloaded. bool locality_spec_variables(const ASR::OMPRegion_t ®ion, ParallelLoopNest &work, const std::map &enclosing_assoc_map, - std::vector &local, std::string &rejected); + std::vector &local, GpuDecline &rejected); // The arrays privatize_iteration_arrays may make local. std::vector iteration_array_candidates( diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.json b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.json new file mode 100644 index 00000000000..f1e22ea1efc --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_cuda_kernel-gpu_kernel_source_16-ce4a711", + "cmd": "lfortran --no-color --gpu=cuda --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_16.f90", + "infile_hash": "aede8dcc14c79ba45cbbb2144a62c69e47d34bb8e86f294a824b2a02", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.stdout", + "stdout_hash": "cc2f846efe1474b0f0ffadf3ae0cf2796d79d6026c0dbc9d570faa89", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.stdout b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.stdout new file mode 100644 index 00000000000..bd7edd77c93 --- /dev/null +++ b/tests/reference/gpu_cuda_kernel-gpu_kernel_source_16-ce4a711.stdout @@ -0,0 +1,49 @@ +#include + +extern "C" __global__ void __lfortran_gpu_kernel_0( + float* g, + float* t, + float* x) +{ + int __flat_idx; + int __gpu_bc_i; + int j; + if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= 1)) { + return; + } + __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); + j = (__flat_idx + 1); + __gpu_bc_i = (1 - 1); + while (((__gpu_bc_i + 1) <= 2)) { + __gpu_bc_i = (__gpu_bc_i + 1); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01f); + } + g[((int)(j) - (1))] = t[((int)(1) - (1))]; +} + +struct __ScalarArgs___lfortran_gpu_kernel_1 { + int __loop_end_0; +}; + +extern "C" __global__ void __lfortran_gpu_kernel_1( + float* g, + float* u, + float* x, + __ScalarArgs___lfortran_gpu_kernel_1 __scalar_args) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __flat_idx; + int j; + int k; + const int n = 8; + if ((((blockIdx.x * blockDim.x) + threadIdx.x) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((blockIdx.x * blockDim.x) + threadIdx.x); + j = (__flat_idx + 1); + k = 1; + u[((int)(k) - (1))] = 1.00000000000000000e+00f; + u[((int)(((k + 1) - 1)) - (1))] = 1.00000000000000000e+00f; + g[((int)(j) - (1))] = ((u[((int)(1) - (1))] + u[((int)(2) - (1))]) + x[((int)(j) - (1))]); +} + diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.json b/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.json new file mode 100644 index 00000000000..c3c53eb6960 --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_metal_kernel-gpu_kernel_source_16-6d4e811", + "cmd": "lfortran --no-color --gpu=metal --show-gpu-kernel-source {infile}", + "infile": "tests/../integration_tests/gpu_kernel_source_16.f90", + "infile_hash": "aede8dcc14c79ba45cbbb2144a62c69e47d34bb8e86f294a824b2a02", + "outfile": null, + "outfile_hash": null, + "stdout": "gpu_metal_kernel-gpu_kernel_source_16-6d4e811.stdout", + "stdout_hash": "5eeae32c2dd86af1b752133a768e7dcab2a3ad4bc6ef65b42cfd088a", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.stdout b/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.stdout new file mode 100644 index 00000000000..5440b68039f --- /dev/null +++ b/tests/reference/gpu_metal_kernel-gpu_kernel_source_16-6d4e811.stdout @@ -0,0 +1,90 @@ +#include +using namespace metal; + +kernel void __lfortran_gpu_kernel_0( + device float* g [[buffer(0)]], + device float* t [[buffer(1)]], + device float* x [[buffer(2)]], + uint __thread_id [[thread_position_in_grid]]) +{ + int __flat_idx; + int __gpu_bc_i; + int __gpu_loop_end; + int __gpu_loop_group; + int j; + if ((((0 * 0) + __thread_id) >= 1)) { + return; + } + __flat_idx = ((0 * 0) + __thread_id); + j = (__flat_idx + 1); + __gpu_loop_end = 2; + __gpu_bc_i = 1; + if ((__gpu_loop_end >= 1)) { + for (__gpu_loop_group = 1; __gpu_loop_group <= (__gpu_loop_end - 15); __gpu_loop_group += 16) { + __gpu_bc_i = __gpu_loop_group; + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 1); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 2); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 3); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 4); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 5); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 6); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 7); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 8); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 9); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 10); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 11); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 12); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 13); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 14); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + __gpu_bc_i = (__gpu_loop_group + 15); + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + } + for (__gpu_bc_i = __gpu_loop_group; __gpu_bc_i <= __gpu_loop_end; __gpu_bc_i++) { + t[((int)(__gpu_bc_i) - (1))] = (x[((int)(j) - (1))] + 4.10000000000000000e+01); + } + } + g[((int)(j) - (1))] = t[((int)(1) - (1))]; +} + +struct __ScalarArgs___lfortran_gpu_kernel_1 { + int __loop_end_0; +}; + +kernel void __lfortran_gpu_kernel_1( + device float* g [[buffer(0)]], + device float* u [[buffer(1)]], + device float* x [[buffer(2)]], + constant __ScalarArgs___lfortran_gpu_kernel_1& __scalar_args [[buffer(3)]], + uint __thread_id [[thread_position_in_grid]]) +{ + int __loop_end_0 = __scalar_args.__loop_end_0; + int __flat_idx; + int j; + int k; + const int n = 8; + if ((((0 * 0) + __thread_id) >= (((__loop_end_0 >= 1)) ? (((__loop_end_0 - 1) + 1)) : (0)))) { + return; + } + __flat_idx = ((0 * 0) + __thread_id); + j = (__flat_idx + 1); + k = 1; + u[((int)(k) - (1))] = 1.00000000000000000e+00; + u[((int)(((k + 1) - 1)) - (1))] = 1.00000000000000000e+00; + g[((int)(j) - (1))] = ((u[((int)(1) - (1))] + u[((int)(2) - (1))]) + x[((int)(j) - (1))]); +} + diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json index bd9c1eacaae..662a9bc916b 100644 --- a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json +++ b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.json @@ -2,12 +2,12 @@ "basename": "gpu_offload_cuda-gpu_decline_17-d2b52ed", "cmd": "lfortran --no-color --gpu=cuda -c {infile} -o {outfile}", "infile": "tests/../integration_tests/gpu_decline_17.f90", - "infile_hash": "24c5fc3990e838a979e7d6750fa390aa01898aaf71d8ad681c202ae2", + "infile_hash": "449f6e105a148238e88806e7bc3dfadf55cf008fd2851126c60bf278", "outfile": null, "outfile_hash": null, "stdout": null, "stdout_hash": null, "stderr": "gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr", - "stderr_hash": "a6f51824604cdb4339b0982f40bc3c880ab84a90fc6944307fa28c40", + "stderr_hash": "b5d19fc7271b5940c4c49bf848944d0942e1be6951f7cdcfe4d97752", "returncode": 5 } \ No newline at end of file diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr index da443cf2835..0d55abec36e 100644 --- a/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr +++ b/tests/reference/gpu_offload_cuda-gpu_decline_17-d2b52ed.stderr @@ -1,4 +1,4 @@ -ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of local locality cannot be given a copy per gpu thread +ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of local locality is of type type(pair), which a gpu thread cannot hold a copy of --> tests/../integration_tests/gpu_decline_17.f90:18:1 - 22:6 | 18 | do concurrent (j = 1:n) local(t) @@ -6,4 +6,4 @@ ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of l ... | 22 | end do - | ...^^^^^^ array 't' of local locality cannot be given a copy per gpu thread + | ...^^^^^^ array 't' of local locality is of type type(pair), which a gpu thread cannot hold a copy of diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.json b/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.json new file mode 100644 index 00000000000..9b47e45b747 --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_offload_cuda-gpu_decline_18-b238281", + "cmd": "lfortran --no-color --gpu=cuda -c {infile} -o {outfile}", + "infile": "tests/../integration_tests/gpu_decline_18.f90", + "infile_hash": "79322cd6dd050a54f47f3e272a4a42af10071a8b6f0e4ba769d6f670", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "gpu_offload_cuda-gpu_decline_18-b238281.stderr", + "stderr_hash": "ada0cae395ad3a0f5fd1125c318cda785a982bb5deffccb9a649cfd4", + "returncode": 5 +} \ No newline at end of file diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.stderr b/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.stderr new file mode 100644 index 00000000000..882f615f09a --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_18-b238281.stderr @@ -0,0 +1,9 @@ +ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of local locality is named by an associate construct around the loop + --> tests/../integration_tests/gpu_decline_18.f90:16:5 - 20:10 + | +16 | do concurrent (j = 1:n) local(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... +... + | +20 | end do + | ...^^^^^^^^^^ array 't' of local locality is named by an associate construct around the loop diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.json b/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.json new file mode 100644 index 00000000000..cfe0d463435 --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.json @@ -0,0 +1,13 @@ +{ + "basename": "gpu_offload_cuda-gpu_decline_19-13fd5d9", + "cmd": "lfortran --no-color --gpu=cuda -c {infile} -o {outfile}", + "infile": "tests/../integration_tests/gpu_decline_19.f90", + "infile_hash": "76dbad05e8a1315e8b8a736838be156a1e4ca8887313529a3702d77b", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "gpu_offload_cuda-gpu_decline_19-13fd5d9.stderr", + "stderr_hash": "c94e7dd2270200de708e79072c4654292d4356b1e7fcf664ef0d09a9", + "returncode": 5 +} \ No newline at end of file diff --git a/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.stderr b/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.stderr new file mode 100644 index 00000000000..3abb8597a53 --- /dev/null +++ b/tests/reference/gpu_offload_cuda-gpu_decline_19-13fd5d9.stderr @@ -0,0 +1,9 @@ +ASR pass error: parallel loop cannot be offloaded to the GPU yet: array 't' of local locality cannot be given a copy per gpu thread: the loop body has an associate construct the gpu kernel cannot inline + --> tests/../integration_tests/gpu_decline_19.f90:14:1 - 22:6 + | +14 | do concurrent (j = 1:n) local(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... +... + | +22 | end do + | ...^^^^^^ array 't' of local locality cannot be given a copy per gpu thread: the loop body has an associate construct the gpu kernel cannot inline diff --git a/tests/tests.toml b/tests/tests.toml index b23f01f0c90..0d5edeec030 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -4600,6 +4600,14 @@ gpu_offload_cuda = true filename = "../integration_tests/gpu_decline_17.f90" gpu_offload_cuda = true +[[test]] +filename = "../integration_tests/gpu_decline_18.f90" +gpu_offload_cuda = true + +[[test]] +filename = "../integration_tests/gpu_decline_19.f90" +gpu_offload_cuda = true + [[test]] filename = "gpu_decline_impure_condition.f90" gpu_offload_cuda = true @@ -4855,6 +4863,11 @@ filename = "../integration_tests/gpu_kernel_source_14.f90" gpu_metal_kernel = true gpu_cuda_kernel = true +[[test]] +filename = "../integration_tests/gpu_kernel_source_16.f90" +gpu_metal_kernel = true +gpu_cuda_kernel = true + [[test]] filename = "errors/array_bounds_check_01.f90" run = true From 9021c8b159afd5c248d379165ea9c97b4b96805a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 03:31:13 +0000 Subject: [PATCH 16/19] perf(gpu): reuse CUDA scratch buffers across launches lfortran_gpu_set_scratch_arg did a cudaMalloc for every scratch buffer (each per-thread workspace) on every launch, freed at the next sync. A kernel with several workspaces launched in a loop spent most of its runtime API time in cudaMalloc/cudaFree. Take the scratch buffer at launch from the memory the kernel's argument slot keeps, as read-only buffers already do and as the Metal runtime does for scratch. It grows when a launch needs more, the old memory being freed at the next sync. What a launch leaves in a scratch buffer is dead once it ends (a part the host reads back is read before the next launch), and the default stream runs launches in order, so pending launches can share it. The new test runs two kernels with workspaces many times between syncs, with workspace sizes that grow, shrink and are zero, and checks the results against the same loops run on the host. --- integration_tests/CMakeLists.txt | 1 + integration_tests/gpu_metal_484.f90 | 82 +++++++++++++++++++++++ src/libasr/runtime/lfortran_gpu_cuda.cu | 19 ++++-- src/libasr/runtime/lfortran_gpu_runtime.h | 3 +- 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 integration_tests/gpu_metal_484.f90 diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 5cf6e1bc431..904c9922a73 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6384,6 +6384,7 @@ RUN(NAME gpu_metal_478 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_479 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_480 LABELS gfortran llvm metal cuda_cpu) RUN(NAME gpu_metal_481 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_metal_484 LABELS gfortran llvm metal cuda cuda_cpu) # gfortran evaluates a `do concurrent` limit twice, so gpu_metal_369 has no # gfortran label. The llvm backend and gfortran evaluate the limits of an # inner index again for every value of the outer one, so gpu_metal_370 is for diff --git a/integration_tests/gpu_metal_484.f90 b/integration_tests/gpu_metal_484.f90 new file mode 100644 index 00000000000..17f8deabd21 --- /dev/null +++ b/integration_tests/gpu_metal_484.f90 @@ -0,0 +1,82 @@ +module gpu_metal_484_m + implicit none +contains + pure function smooth(v) result(r) + real, intent(in) :: v(:) + real, allocatable :: r(:) + integer :: i + allocate(r(size(v))) + do i = 1, size(v) + r(i) = 0.5*v(i) + if (i > 1) r(i) = r(i) + 0.25*v(i-1) + if (i < size(v)) r(i) = r(i) + 0.25*v(i+1) + end do + end function + + pure function scaled(v, c) result(r) + real, intent(in) :: v(:), c + real, allocatable :: r(:) + allocate(r(size(v))) + r = c*v + 1.0 + end function + + ! Launches the same kernels, with per-thread workspaces sized by `m`, + ! `steps` times each, with no host access between the launches. + subroutine run(m, ncol, steps, a, b) + integer, intent(in) :: m, ncol, steps + real, intent(inout) :: a(m, ncol), b(m, ncol) + integer :: s, j + do s = 1, steps + do concurrent (j = 1:ncol) + b(:, j) = smooth(a(:, j)) + end do + do concurrent (j = 1:ncol) + a(:, j) = scaled(b(:, j), 0.5) + end do + end do + end subroutine + + subroutine run_ref(m, ncol, steps, a, b) + integer, intent(in) :: m, ncol, steps + real, intent(inout) :: a(m, ncol), b(m, ncol) + integer :: s, j + do s = 1, steps + do j = 1, ncol + b(:, j) = smooth(a(:, j)) + end do + do j = 1, ncol + a(:, j) = scaled(b(:, j), 0.5) + end do + end do + end subroutine +end module + +program gpu_metal_484 + use gpu_metal_484_m + implicit none + integer, parameter :: nsizes = 7 + integer, parameter :: sizes(nsizes) = [8, 40, 3, 72, 0, 16, 72] + integer, parameter :: ncols(nsizes) = [5, 33, 64, 9, 4, 1, 17] + real, allocatable :: a(:, :), b(:, :), ra(:, :), rb(:, :) + integer :: k, i, j, m, ncol + + do k = 1, nsizes + m = sizes(k) + ncol = ncols(k) + allocate(a(m, ncol), b(m, ncol), ra(m, ncol), rb(m, ncol)) + do j = 1, ncol + do i = 1, m + a(i, j) = real(mod(i + 3*j + k, 11)) + end do + end do + b = 0 + ra = a + rb = b + call run(m, ncol, 25, a, b) + call run_ref(m, ncol, 25, ra, rb) + if (any(abs(a - ra) > 1e-5)) error stop + if (any(abs(b - rb) > 1e-5)) error stop + deallocate(a, b, ra, rb) + end do + print *, "ok" +end program diff --git a/src/libasr/runtime/lfortran_gpu_cuda.cu b/src/libasr/runtime/lfortran_gpu_cuda.cu index 62125199ed5..e793b99d7a4 100644 --- a/src/libasr/runtime/lfortran_gpu_cuda.cu +++ b/src/libasr/runtime/lfortran_gpu_cuda.cu @@ -33,6 +33,11 @@ default stream ordering every copy and launch: is a dirty range, the kernel reads the resident memory instead. * A range that overlaps a dirty one without being the same range makes the runtime sync first. +* A scratch buffer, which only the device holds, is the memory its argument + slot keeps as well. What a launch leaves there is dead once it ends (a part + the host reads back is read before the next launch is made), and the + stream runs the launches one after another, so every launch of the kernel + uses the same memory, however many of them are still pending. * Memory a launch may still use is freed only at the next sync. */ @@ -202,7 +207,8 @@ static void* dirty_resident(void *host, size_t size) { return entries[i].device; } -// The memory argument `idx` of a kernel keeps for what it only reads. +// The memory argument `idx` of a kernel keeps for what it only reads, or +// for its scratch buffer. static void* slot_buffer(slot_cache *cache, int idx, size_t size) { if (cache->buffers[idx] && cache->capacities[idx] >= size) { return cache->buffers[idx]; @@ -280,7 +286,6 @@ lfortran_gpu_kernel* lfortran_gpu_load_kernel( void lfortran_gpu_release_kernel(lfortran_gpu_kernel* k) { if (!k) return; for (int i = 0; i < k->n_args; i++) { - if (k->kind[i] == ARG_SCRATCH) free_later(k->buffer_device_ptrs[i]); if (k->kind[i] == ARG_SCALAR && k->scalar_args[i].data) { free(k->scalar_args[i].data); } @@ -305,16 +310,17 @@ void lfortran_gpu_set_scratch_arg(lfortran_gpu_kernel* k, int idx, if (!k || idx >= MAX_ARGS) return; k->buffer_host_ptrs[idx] = NULL; k->buffer_sizes[idx] = size; + k->buffer_device_ptrs[idx] = NULL; k->kind[idx] = ARG_SCRATCH; if (idx >= k->n_args) k->n_args = idx + 1; - k->buffer_device_ptrs[idx] = size > 0 ? device_alloc(size) : NULL; } void lfortran_gpu_read_scratch_arg(lfortran_gpu_kernel* k, int idx, void* dst, size_t size) { if (!k || idx >= MAX_ARGS || size == 0) return; - if (k->kind[idx] != ARG_SCRATCH || size > k->buffer_sizes[idx]) { + if (k->kind[idx] != ARG_SCRATCH || !k->buffer_device_ptrs[idx] + || size > k->buffer_sizes[idx]) { fprintf(stderr, "lfortran_gpu_read_scratch_arg: no scratch buffer " "%d of %zu bytes\n", idx, size); exit(1); @@ -375,6 +381,11 @@ void lfortran_gpu_launch(lfortran_gpu_ctx* ctx, lfortran_gpu_kernel* k, } k->buffer_device_ptrs[i] = d_ptr; } + for (int i = 0; i < k->n_args; i++) { + if (k->kind[i] != ARG_SCRATCH) continue; + k->buffer_device_ptrs[i] = k->buffer_sizes[i] == 0 ? NULL + : slot_buffer(k->cache, i, k->buffer_sizes[i]); + } // Build the kernel argument array for cudaLaunchKernel: a device // pointer for a buffer, the value for a scalar. diff --git a/src/libasr/runtime/lfortran_gpu_runtime.h b/src/libasr/runtime/lfortran_gpu_runtime.h index b91e8c60a3f..36c26ba604c 100644 --- a/src/libasr/runtime/lfortran_gpu_runtime.h +++ b/src/libasr/runtime/lfortran_gpu_runtime.h @@ -122,7 +122,8 @@ void lfortran_gpu_set_buffer_arg(lfortran_gpu_kernel* k, int idx, void lfortran_gpu_set_scalar_arg(lfortran_gpu_kernel* k, int idx, const void* val, size_t size); // A buffer of `size` bytes only the device holds: nothing is copied in or -// back, and the kernel object owns it until it is released. +// back. What the launch leaves in it lasts until the next launch of the +// kernel; the runtime may keep the memory for later launches. void lfortran_gpu_set_scratch_arg(lfortran_gpu_kernel* k, int idx, size_t size); // Copies the leading `size` bytes of the scratch buffer `idx` into `dst`, From 97301a01b7d704561efc5c5f76b259be820dc6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 04:24:34 +0000 Subject: [PATCH 17/19] test: regenerate gpu_metal_474 CUDA reference for the combined stack #15569 makes the array-constant temporary thread-local and #15570 drops the unused named constant; the merged output has both changes. Also run gpu_kernel_source_15 on the cuda backend. --- integration_tests/CMakeLists.txt | 2 +- tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 8ef988e26a4..0ee7ddc54e0 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -6485,7 +6485,7 @@ RUN(NAME gpu_kernel_source_10 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_11 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_12 LABELS gfortran llvm metal cuda_cpu cuda) RUN(NAME gpu_kernel_source_13 LABELS gfortran llvm metal cuda cuda_cpu) -RUN(NAME gpu_kernel_source_15 LABELS gfortran llvm metal cuda_cpu) +RUN(NAME gpu_kernel_source_15 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_14 LABELS gfortran llvm metal cuda cuda_cpu) RUN(NAME gpu_kernel_source_16 LABELS gfortran llvm metal cuda cuda_cpu) diff --git a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json index f453029bbfc..2db4696deeb 100644 --- a/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json +++ b/tests/reference/gpu_cuda_kernel-gpu_metal_474-0583450.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "gpu_cuda_kernel-gpu_metal_474-0583450.stdout", - "stdout_hash": "aeec474ccd4bb100eeaed7b040e2a86d2bb5e5f0522626859924f59d", + "stdout_hash": "9aeae5a07d29532a2543236859e7a997c1a98675868d1dfa45bad359", "stderr": null, "stderr_hash": null, "returncode": 0 From 3ba8e18d3cfc827fa4cff07e09037f84458418cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 04:35:00 +0000 Subject: [PATCH 18/19] ci: document and script validating --gpu=cuda on NVIDIA hardware with Formal ci/cuda_nvidia/README.md gives the exact steps to build LFortran, check the backend, run the GPU integration tests on a real GPU, and validate BerkeleyLab Formal (tests, both solvers, full-field comparisons against host LLVM and GFortran 16, cuobjdump, nsys and compute-sanitizer). run_formal_cuda.sh performs all of it and prints a summary; fpm/ and gfortran16/ are the Linux Pixi environments it uses. --- ci/cuda_nvidia/README.md | 153 +++++++++++++++++++++ ci/cuda_nvidia/fpm/pixi.toml | 8 ++ ci/cuda_nvidia/gfortran16/pixi.toml | 9 ++ ci/cuda_nvidia/make_boundary_input.py | 21 +++ ci/cuda_nvidia/run_formal_cuda.sh | 185 ++++++++++++++++++++++++++ 5 files changed, 376 insertions(+) create mode 100644 ci/cuda_nvidia/README.md create mode 100644 ci/cuda_nvidia/fpm/pixi.toml create mode 100644 ci/cuda_nvidia/gfortran16/pixi.toml create mode 100644 ci/cuda_nvidia/make_boundary_input.py create mode 100755 ci/cuda_nvidia/run_formal_cuda.sh diff --git a/ci/cuda_nvidia/README.md b/ci/cuda_nvidia/README.md new file mode 100644 index 00000000000..68b351fd850 --- /dev/null +++ b/ci/cuda_nvidia/README.md @@ -0,0 +1,153 @@ +# Running LFortran's CUDA backend on NVIDIA hardware + +This directory holds the recipe used to validate `--gpu=cuda` on a real NVIDIA +GPU: LFortran's own GPU integration tests, and the BerkeleyLab +[Formal](https://github.com/BerkeleyLab/formal) library and its 2D +advection-diffusion example. `run_formal_cuda.sh` performs every step below and +prints a summary; the sections explain what it does and how to run the pieces +by hand. + +Validated on: NVIDIA RTX PRO 6000 Blackwell Server Edition (compute capability +12.0, `sm_120`), driver 610.43.02, CUDA 13.3 (`/usr/local/cuda`), Ubuntu 24.04, +Pixi `llvm11` environment (LLVM 11.1.0, conda-forge GCC 15.3 as nvcc's host +compiler). + +## Prerequisites + +- An NVIDIA driver and a CUDA toolkit with `nvcc` on `PATH` + (`export PATH=/usr/local/cuda/bin:$PATH`). `cuobjdump`, `nsys` and + `compute-sanitizer` from the same toolkit are used for evidence when present. +- Git and [Pixi](https://pixi.sh). Everything else (LLVM 11, the host C/C++ + compilers, FPM, GFortran 16) comes from Pixi environments. +- If `pixi shell` does not work in your shell, prefix commands with + `eval "$(pixi shell-hook -e llvm11)"` or use `pixi run -e llvm11 ...`. + +## 1. Build LFortran + +From the root of this checkout: + +```bash +CMAKE_BUILD_PARALLEL_LEVEL=16 pixi run -e llvm11 build \ + '-DCMAKE_CXX_FLAGS_DEBUG=-g -O2' '-DCMAKE_C_FLAGS_DEBUG=-g -O2' > build.log 2>&1 +pixi run -e llvm11 bash -c 'command -v lfortran; lfortran --version; command -v nvcc' +``` + +`lfortran` must resolve to `build/llvm11/src/bin/lfortran` of this checkout. + +## 2. Quick check + +```bash +cat > saxpy.f90 <<'EOF' +program saxpy +implicit none +integer, parameter :: n = 10000000 +real, allocatable :: x(:), y(:) +real :: a +integer :: i +allocate(x(n), y(n)) +a = 2.0; x = 1.0; y = 3.0 +do concurrent (i = 1:n) + y(i) = a*x(i) + y(i) +end do +if (abs(y(1) - 5.0) > 1e-6 .or. abs(y(n) - 5.0) > 1e-6) error stop "wrong result" +print *, "OK" +end program +EOF +pixi run -e llvm11 lfortran --gpu=cuda saxpy.f90 -o saxpy_gpu +CUDA_DISABLE_PTX_JIT=1 ./saxpy_gpu # prints OK +cuobjdump --list-elf --list-ptx saxpy_gpu # sm_120 cubins on this GPU +``` + +GPU options: + +- `--gpu=cuda` compiles the device code with nvcc and runs it on the GPU. + `--gpu=cuda_cpu` compiles the same device code as host C++ and runs it on + the CPU (no GPU needed; this is what CI runs). +- `--gpu-arch=` selects the GPU architecture, e.g. `sm_120`. The default + is `native`, the GPUs of the compiling machine. On a machine without a GPU + nvcc then falls back to its oldest default architecture with a warning, so + pass an explicit architecture when cross-compiling. +- `--device-compiler=` selects nvcc (or, for `cuda_cpu`, the host C++ + compiler). +- `--show-gpu-kernel-source` prints the generated `.cu` source. +- `CUDA_DISABLE_PTX_JIT=1` at run time makes a binary built for the wrong + architecture fail instead of being JIT compiled by the driver. + +## 3. LFortran GPU integration tests on the GPU + +```bash +CUDA_DISABLE_PTX_JIT=1 pixi run -e llvm11 integration_tests -b cuda -j16 > cuda.log 2>&1 +grep 'tests passed' cuda.log +``` + +Every test labeled `cuda_cpu` that passes on a real GPU also carries the `cuda` +label (485 tests on this branch). CI has no NVIDIA GPU and runs only +`-b cuda_cpu`, so run this on GPU machines after changing GPU code. + +## 4. Formal + +```bash +ci/cuda_nvidia/run_formal_cuda.sh /path/to/work-dir > formal.log 2>&1 +tail -40 formal.log +``` + +The script clones Formal at the validated revision (`FORMAL_REF`, the head of +BerkeleyLab/formal#71, which contains #70), then, with logs in +`/logs` and data in `/validation`: + +1. Builds and runs Formal's FPM test suite and both solvers with + `--gpu=cuda_cpu` (expect 32/32 tests, 0 skipped). +2. The same with native `--gpu=cuda --gpu-arch=native` and + `CUDA_DISABLE_PTX_JIT=1`, in a separate build directory. +3. Builds three executables of the example: native GPU, ordinary host LLVM, + and GFortran 16 as an independent oracle. +4. Compares full fields from a shared raw input: + - a 17x13, 9-step Gaussian case, native against host LLVM, with Formal's + `validate_2d_advection_workspace.py`; + - a nonsquare 13x11, 3-step case with nonzero, non-smooth boundaries + (`make_boundary_input.py`), native against GFortran and host LLVM, with + Formal's strict `compare_2d_raw_fields.py` (finite fields, evolution, + unchanged boundaries, default tolerances). +5. Records evidence of native execution: `cuobjdump` of the executable, `nsys` + kernel/transfer summaries, and `compute-sanitizer` memcheck, racecheck, + synccheck and initcheck on both solvers. +6. Runs `integration_tests -b cuda` (step 3 above). + +Environment overrides: `GPU_ARCH` (e.g. `sm_120`), `JOBS`, `FORMAL_REF`, +`SKIP_PROFILE=1`, `SKIP_LFORTRAN_TESTS=1`. + +Notes on the recipe: + +- Keep all Fortran flags in a single FPM `--flag` argument. +- `--input` supplies the grid, step count and time step, so Formal rejects it + together with `--cells`, `--steps` or `--dt`; and only the workspace solver + accepts `--input`. +- `formal/benchmarks/pixi.toml` only lists `osx-arm64`; `fpm/pixi.toml` here + pins the same FPM (0.13.0) for Linux. +- Formal needs GFortran 16 (its README asks for 16.3+); conda-forge's 16.2 + builds it with `-fcoarray=single`. `gfortran16/pixi.toml` provides it. +- `nsys` and `compute-sanitizer` need a writable `TMPDIR`; the script uses + `/tmp` (a shared `/tmp/nvidia` can belong to another user). +- The operators solver cannot read a raw input, so its initial field is + computed by each build. GPU `sinf`/`expf` and the host math libraries round + differently (host LLVM and GFortran differ as well), at the 1e-7 level, so + that path is compared against its own initial state rather than bitwise + across builds. + +## Results on the validation machine + +| Check | Result | +|---|---| +| Formal tests, `cuda_cpu` | 32/32, 0 skipped | +| Formal tests, native CUDA, PTX JIT disabled | 32/32, 0 skipped | +| Embedded device code | `sm_120` cubins only | +| Gaussian 17x13/9, native vs host LLVM | max abs 1.2e-10, relative L2 7.9e-11 | +| Boundary 13x11/3, native vs GFortran 16 vs host LLVM | bitwise identical; boundaries fixed; field evolves | +| compute-sanitizer (4 tools x 2 solvers) | 0 errors | +| nsys, workspace solver | all arithmetic in kernels; transfers constant in the step count | +| `integration_tests -b cuda` | all pass | + +Known limitation: the operators solver runs every kernel on the GPU, but +LFortran synchronizes at each procedure exit and re-uploads data per launch, +and part of its arithmetic is host array expressions, so most of its time is +host work and transfers. The workspace solver is fully device resident. diff --git a/ci/cuda_nvidia/fpm/pixi.toml b/ci/cuda_nvidia/fpm/pixi.toml new file mode 100644 index 00000000000..b34100eee6d --- /dev/null +++ b/ci/cuda_nvidia/fpm/pixi.toml @@ -0,0 +1,8 @@ +[workspace] +name = "formal-fpm-linux" +description = "Linux counterpart of formal/benchmarks/pixi.toml (which only lists osx-arm64): the same pinned FPM" +channels = ["conda-forge"] +platforms = ["linux-64"] + +[dependencies] +fpm = "==0.13.0" diff --git a/ci/cuda_nvidia/gfortran16/pixi.toml b/ci/cuda_nvidia/gfortran16/pixi.toml new file mode 100644 index 00000000000..2ee6bb11409 --- /dev/null +++ b/ci/cuda_nvidia/gfortran16/pixi.toml @@ -0,0 +1,9 @@ +[workspace] +name = "formal-gfortran16" +description = "Independent GFortran oracle for Formal (README asks for GCC >= 16.3; newest on conda-forge is 16.2)" +channels = ["conda-forge"] +platforms = ["linux-64"] + +[dependencies] +gfortran = "16.2.*" +fpm = "==0.13.0" diff --git a/ci/cuda_nvidia/make_boundary_input.py b/ci/cuda_nvidia/make_boundary_input.py new file mode 100644 index 00000000000..221ba043fcb --- /dev/null +++ b/ci/cuda_nvidia/make_boundary_input.py @@ -0,0 +1,21 @@ +"""Write a FADV2D1 raw input with nonzero, non-smooth boundaries on a nonsquare grid.""" +import sys +import numpy as np +out, nx, ny, steps, dt = sys.argv[1], int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]), float(sys.argv[5]) +rng = np.random.default_rng(20261019) +X, Y = np.meshgrid(np.linspace(0, 1, nx + 2), np.linspace(0, 1, ny + 2), indexing="ij") +s = (0.5 + 0.3 * np.sin(3.1 * X) * np.cos(2.3 * Y) + 0.05 * rng.standard_normal(X.shape)).astype(np.float32) +s[0, :] = 1.0 + 0.1 * np.arange(ny + 2) # distinct nonzero values on each boundary +s[-1, :] = -0.75 + 0.05 * np.arange(ny + 2) +s[:, 0] = 2.0 - 0.07 * np.arange(nx + 2) +s[:, -1] = 0.3 + 0.11 * np.arange(nx + 2) +u = (0.4 + 0.2 * rng.standard_normal((nx + 1, ny + 2))).astype(np.float32) +v = (-0.3 + 0.2 * rng.standard_normal((nx + 2, ny + 1))).astype(np.float32) +dt32 = np.float32(dt) +with open(out, "wb") as f: + f.write(b"FADV2D1\n") + f.write(f"{nx} {ny} {steps} {float(dt32):.16E}\n".encode()) + f.write(b"mode raw\n") + for a in (s, u, v): + f.write(np.asfortranarray(a).astype(" $name (log: $log)" + "$@" > "$log" 2>&1 + local rc=$? + if [ $rc -eq 0 ]; then SUMMARY+=("PASS $name"); else SUMMARY+=("FAIL $name (exit $rc, $log)"); FAILED=1; fi + return $rc +} +lf() { pixi run --manifest-path "$LFORTRAN_ROOT/pixi.toml" -e llvm11 "$@"; } +formal_fpm() { + lf pixi run --manifest-path "$FPM_MANIFEST" \ + /bin/bash -c 'cd "$FORMAL_ROOT" && exec fpm "$@"' _ "$@" +} + +# 0. Toolchain and revisions. +{ + echo "date: $(date -Is)"; echo "host: $(hostname)" + echo "lfortran_root: $LFORTRAN_ROOT" + echo "lfortran_head: $(git -C "$LFORTRAN_ROOT" rev-parse HEAD)" + nvidia-smi --query-gpu=name,compute_cap,driver_version --format=csv,noheader + nvidia-smi -q | grep -i 'Addressing Mode' + lf bash -c 'command -v lfortran; lfortran --version | head -1; llvm-config --version; + command -v nvcc; nvcc --version | tail -2; command -v c++; c++ --version | head -1' +} > "$LOGS/00-environment.log" 2>&1 +cat "$LOGS/00-environment.log" +test -x "$LFORTRAN_COMPILER" || { echo "Build LFortran first: pixi run -e llvm11 build (see README.md)"; exit 1; } +NVCC="$(lf bash -c 'command -v nvcc' 2>/dev/null)" +CUDA_CPU_CXX="$(lf bash -c 'command -v "${CXX:-c++}"' 2>/dev/null)" +test -x "$NVCC" || { echo "nvcc not found on PATH"; exit 1; } +CUDA_BIN="$(dirname "$NVCC")" + +# 1. Formal at the validated revision. +if [ ! -d "$FORMAL_ROOT/.git" ]; then + git clone -q "$FORMAL_REPO" "$FORMAL_ROOT" +fi +git -C "$FORMAL_ROOT" fetch -q origin "$FORMAL_REF" 2>/dev/null || git -C "$FORMAL_ROOT" fetch -q origin pull/71/head +git -C "$FORMAL_ROOT" checkout -q --detach "$FORMAL_REF" +echo "formal_head: $(git -C "$FORMAL_ROOT" rev-parse HEAD)" | tee -a "$LOGS/00-environment.log" + +# Keep all flags in one --flag argument. +COMMON_FLAGS="--cpp --realloc-lhs-arrays --separate-compilation" +CPU_FLAGS="$COMMON_FLAGS --gpu=cuda_cpu --device-compiler=$CUDA_CPU_CXX" +NATIVE_FLAGS="$COMMON_FLAGS --gpu=cuda --gpu-arch=$GPU_ARCH --device-compiler=$NVCC" +CPU_BUILD="$FORMAL_ROOT/build/cuda-cpu" +NATIVE_BUILD="$FORMAL_ROOT/build/cuda-nvidia" +HOST_BUILD="$FORMAL_ROOT/build/llvm-cpu-reference" +GF_BUILD="$FORMAL_ROOT/build/gfortran16-reference" +EXAMPLE="--example 2D-advection-diffusion" +GAUSS_ARGS="--solver workspace --order 4 --cells 17,13 --steps 9 --dt 1e-4 --no-csv" +OPS_ARGS="--solver operators --order 4 --cells 9,11 --steps 2 --dt 1e-4 --no-csv" + +# 2. CUDA CPU emulation. +step "formal tests, cuda_cpu" "$LOGS/10-fpm-test-cuda-cpu.log" \ + formal_fpm test --compiler "$LFORTRAN_COMPILER" --build-dir "$CPU_BUILD" --flag "$CPU_FLAGS" +step "operators solver, cuda_cpu" "$LOGS/11-operators-cuda-cpu.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$CPU_BUILD" --flag "$CPU_FLAGS" $EXAMPLE -- $OPS_ARGS +step "workspace solver, cuda_cpu (dumps shared input)" "$LOGS/12-workspace-cuda-cpu.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$CPU_BUILD" --flag "$CPU_FLAGS" $EXAMPLE -- $GAUSS_ARGS \ + --dump-input "$V/gaussian-input.fadv2d" --dump-final-raw "$V/gaussian-cuda-cpu-final.fadv2d" + +# 3. Native CUDA. With PTX JIT disabled a binary built for the wrong +# architecture fails instead of silently JIT compiling. +export CUDA_DISABLE_PTX_JIT=1 +step "formal tests, native cuda" "$LOGS/20-fpm-test-cuda-native.log" \ + formal_fpm test --compiler "$LFORTRAN_COMPILER" --build-dir "$NATIVE_BUILD" --flag "$NATIVE_FLAGS" +step "operators solver, native cuda" "$LOGS/21-operators-cuda-native.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$NATIVE_BUILD" --flag "$NATIVE_FLAGS" $EXAMPLE -- $OPS_ARGS +# --input supplies cells, steps and dt; Formal rejects them together. +step "workspace solver, native cuda (shared input)" "$LOGS/22-workspace-cuda-native.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$NATIVE_BUILD" --flag "$NATIVE_FLAGS" $EXAMPLE -- \ + --solver workspace --order 4 --no-csv --input "$V/gaussian-input.fadv2d" \ + --dump-final-raw "$V/gaussian-cuda-native-final.fadv2d" + +# 4. Executables: native GPU, host LLVM, independent GFortran 16 oracle. +step "capture native executable" "$LOGS/30-capture-native.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$NATIVE_BUILD" --flag "$NATIVE_FLAGS" $EXAMPLE --runner cp -- "$V/formal-native" +step "capture host LLVM executable" "$LOGS/31-capture-host.log" \ + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$HOST_BUILD" --flag "$COMMON_FLAGS" $EXAMPLE --runner cp -- "$V/formal-host-llvm" +step "capture GFortran 16 executable" "$LOGS/32-capture-gfortran.log" \ + pixi run --manifest-path "$GF16_MANIFEST" /bin/bash -c 'cd "$FORMAL_ROOT" && exec fpm "$@"' _ \ + run --compiler gfortran --build-dir "$GF_BUILD" --flag "-cpp -O2 -ffree-line-length-none -fcoarray=single" \ + $EXAMPLE --runner cp -- "$V/formal-gfortran" +GF_LIB="$(pixi run --manifest-path "$GF16_MANIFEST" bash -c 'echo $CONDA_PREFIX/lib' 2>/dev/null)" + +# 5. Full-field comparisons. +step "gaussian 17x13/9: host LLVM reference" "$LOGS/40-gaussian-host.log" \ + "$V/formal-host-llvm" --solver workspace --order 4 --no-csv --input "$V/gaussian-input.fadv2d" \ + --dump-final-raw "$V/gaussian-host-final.fadv2d" +step "gaussian 17x13/9: native vs host (validate_2d_advection_workspace.py)" "$LOGS/41-gaussian-validate.log" \ + lf python "$FORMAL_ROOT/example/scripts/validate_2d_advection_workspace.py" \ + --executable "$V/formal-native" --workdir "$V/compare-native" \ + --raw-input "$V/gaussian-input.fadv2d" --reference-raw "$V/gaussian-host-final.fadv2d" \ + --cells 17,13 --steps 9 --dt 1e-4 --evolution --gpu-runner env + +lf python "$HERE/make_boundary_input.py" "$V/boundary-input.fadv2d" 13 11 3 1e-4 > "$LOGS/50-boundary-input.log" 2>&1 +for exe in native host-llvm gfortran; do + step "boundary 13x11/3: $exe" "$LOGS/51-boundary-$exe.log" \ + env LD_LIBRARY_PATH="$GF_LIB${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" "$V/formal-$exe" \ + --solver workspace --order 4 --no-csv --input "$V/boundary-input.fadv2d" \ + --dump-final-raw "$V/boundary-$exe-final.fadv2d" + # The comparator takes the oracle payloads without the FADV2D1 header. + python3 -c 'import sys; b=open(sys.argv[1],"rb").read().split(b"\n",3); assert b[2]==b"mode raw-final"; open(sys.argv[2],"wb").write(b[3])' \ + "$V/boundary-$exe-final.fadv2d" "$V/boundary-$exe-final.bin" 2>/dev/null +done +step "boundary 13x11/3: native vs GFortran vs host (compare_2d_raw_fields.py)" "$LOGS/52-boundary-compare.log" \ + lf python "$FORMAL_ROOT/example/scripts/compare_2d_raw_fields.py" \ + "$V/boundary-input.fadv2d" "$V/boundary-native-final.fadv2d" "$V/boundary-gfortran-final.bin" \ + --cells 13,11 --steps 3 --evolution --cpu-final "$V/boundary-host-llvm-final.bin" + +# 6. Evidence of native execution. +step "embedded GPU code (cuobjdump)" "$LOGS/60-cuobjdump.log" \ + "$CUDA_BIN/cuobjdump" --list-elf --list-ptx "$V/formal-native" +if [ "${SKIP_PROFILE:-0}" != 1 ]; then + if [ -x "$CUDA_BIN/nsys" ]; then + step "nsys: workspace kernel launches" "$LOGS/61-nsys-workspace.log" bash -c " + cd '$V' && '$CUDA_BIN/nsys' profile -o nsys-workspace --force-overwrite true \ + ./formal-native --solver workspace --order 4 --no-csv --input gaussian-input.fadv2d && + '$CUDA_BIN/nsys' stats --report cuda_gpu_kern_sum,cuda_gpu_mem_time_sum,cuda_api_sum nsys-workspace.nsys-rep" + step "nsys: operators kernel launches" "$LOGS/62-nsys-operators.log" bash -c " + cd '$V' && '$CUDA_BIN/nsys' profile -o nsys-operators --force-overwrite true \ + ./formal-native $OPS_ARGS && + '$CUDA_BIN/nsys' stats --report cuda_gpu_kern_sum,cuda_gpu_mem_time_sum,cuda_api_sum nsys-operators.nsys-rep" + fi + if [ -x "$CUDA_BIN/compute-sanitizer" ]; then + for tool in memcheck racecheck synccheck initcheck; do + step "compute-sanitizer $tool: workspace" "$LOGS/63-sanitizer-$tool-workspace.log" \ + "$CUDA_BIN/compute-sanitizer" --tool $tool --error-exitcode 99 "$V/formal-native" \ + --solver workspace --order 4 --no-csv --input "$V/gaussian-input.fadv2d" + step "compute-sanitizer $tool: operators" "$LOGS/63-sanitizer-$tool-operators.log" \ + "$CUDA_BIN/compute-sanitizer" --tool $tool --error-exitcode 99 "$V/formal-native" $OPS_ARGS + done + fi +fi + +# 7. LFortran's GPU integration tests on the real GPU. +if [ "${SKIP_LFORTRAN_TESTS:-0}" != 1 ]; then + step "lfortran integration_tests -b cuda" "$LOGS/70-lfortran-cuda-tests.log" \ + bash -c "cd '$LFORTRAN_ROOT' && pixi run -e llvm11 integration_tests -b cuda -j$JOBS" +fi +unset CUDA_DISABLE_PTX_JIT + +echo +echo "Summary ($WORK):" +for line in "${SUMMARY[@]}"; do echo " $line"; done +grep -h 'tests passed' "$LOGS"/10-*.log "$LOGS"/20-*.log "$LOGS"/70-*.log 2>/dev/null | sed 's/^/ /' +grep -h 'sm_' "$LOGS/60-cuobjdump.log" | sed -E 's/.*\.(sm_[0-9a-z]+)\.(cubin|ptx)/\1 \2/' | sort | uniq -c | sed 's/^/ /' +exit $FAILED From 93826d8f1bfb180c9d316945b299f17328174b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C4=8Cert=C3=ADk?= Date: Mon, 19 Oct 2026 05:15:59 +0000 Subject: [PATCH 19/19] ci: check that every do concurrent in Formal is offloaded Build all of Formal (library, tests, every example) with --gpu-allow-cpu-fallback, which reports each loop LFortran would run on the CPU instead of failing, and require that no loop is reported. --- ci/cuda_nvidia/run_formal_cuda.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ci/cuda_nvidia/run_formal_cuda.sh b/ci/cuda_nvidia/run_formal_cuda.sh index 57866482122..2fcb6e0b685 100755 --- a/ci/cuda_nvidia/run_formal_cuda.sh +++ b/ci/cuda_nvidia/run_formal_cuda.sh @@ -96,6 +96,28 @@ step "workspace solver, cuda_cpu (dumps shared input)" "$LOGS/12-workspace-cuda- formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$CPU_BUILD" --flag "$CPU_FLAGS" $EXAMPLE -- $GAUSS_ARGS \ --dump-input "$V/gaussian-input.fadv2d" --dump-final-raw "$V/gaussian-cuda-cpu-final.fadv2d" +# Every `do concurrent` is offloaded. Without --gpu-allow-cpu-fallback a loop +# LFortran cannot offload is a compile error; with it, such a loop is +# reported as "parallel loop runs on the CPU" instead. Building all of +# Formal (library, tests, every example) with the fallback allowed and +# finding no such report shows that none would run on the host. +all_do_concurrent_offloaded() { + local b="$FORMAL_ROOT/build/fallback-check" log="$LOGS/19-fallback-build.log" + local f="$NATIVE_FLAGS --gpu-allow-cpu-fallback" + formal_fpm build --compiler "$LFORTRAN_COMPILER" --build-dir "$b" --flag "$f" --tests > "$log" 2>&1 || return 1 + for ex in $(cd "$FORMAL_ROOT/example" && ls *.F90 *.f90 2>/dev/null | sed 's/\.[Ff]90$//'); do + grep -qE "^\s*program\b" "$FORMAL_ROOT/example/$ex".[Ff]90 2>/dev/null || continue + formal_fpm run --compiler "$LFORTRAN_COMPILER" --build-dir "$b" --flag "$f" \ + --example "$ex" --runner true >> "$log" 2>&1 || return 1 + done + echo "do concurrent constructs in Formal: $(grep -rciE '^\s*([a-z_0-9]+\s*:\s*)?do\s+concurrent' \ + "$FORMAL_ROOT/src" "$FORMAL_ROOT/test" "$FORMAL_ROOT/example" | awk -F: '{s+=$2} END {print s}')" + echo "loops reported as running on the CPU: $(grep -c 'runs on the CPU' "$log")" + ! grep -q 'runs on the CPU' "$log" +} +step "every do concurrent offloaded (no CPU fallback)" "$LOGS/19-all-do-concurrent-offloaded.log" \ + all_do_concurrent_offloaded + # 3. Native CUDA. With PTX JIT disabled a binary built for the wrong # architecture fails instead of silently JIT compiling. export CUDA_DISABLE_PTX_JIT=1