From 65fb5876809659269608155295a4ee65ab8b84ce Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Tue, 31 Mar 2026 13:06:11 +0000 Subject: [PATCH 01/16] refactor cuda bindings utils for nvvm --- cuda_bindings/cuda/bindings/utils/__init__.py | 4 +- .../cuda/bindings/utils/_nvvm_utils.py | 94 +++++++++++++++++++ cuda_core/tests/test_program.py | 91 +++--------------- 3 files changed, 108 insertions(+), 81 deletions(-) create mode 100644 cuda_bindings/cuda/bindings/utils/_nvvm_utils.py diff --git a/cuda_bindings/cuda/bindings/utils/__init__.py b/cuda_bindings/cuda/bindings/utils/__init__.py index e4fcb15e8fd..fd5018ed1ec 100644 --- a/cuda_bindings/cuda/bindings/utils/__init__.py +++ b/cuda_bindings/cuda/bindings/utils/__init__.py @@ -1,9 +1,10 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE from typing import Any, Callable from ._ptx_utils import get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver from ._version_check import warn_if_cuda_major_version_mismatch +from ._nvvm_utils import check_nvvm_options _handle_getters: dict[type, Callable[[Any], int]] = {} @@ -11,7 +12,6 @@ def _add_cuda_native_handle_getter(t: type, getter: Callable[[Any], int]) -> None: _handle_getters[t] = getter - def get_cuda_native_handle(obj: Any) -> int: """Returns the address of the provided CUDA Python object as a Python int. diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py new file mode 100644 index 00000000000..e8f7dbbf433 --- /dev/null +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -0,0 +1,94 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026-2027 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +from typing import Sequence + +_PRECHECK_NVVM_IR = """target triple = "nvptx64-unknown-cuda" +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + +define void @dummy_kernel() {{ +entry: + ret void +}} + +!nvvm.annotations = !{{!0}} +!0 = !{{void ()* @dummy_kernel, !"kernel", i32 1}} + +!nvvmir.version = !{{!1}} +!1 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}} +""" + + +def check_nvvm_options(options: Sequence[bytes]) -> bool: + """ + Abstracted from https://github.com/NVIDIA/numba-cuda/pull/681 + + Check if the specified options are supported by the current libNVVM version. + + The options are a list of bytes, each representing a compiler option. + + If the test program fails to compile, the options are not supported and False + is returned. + + If the test program compiles successfully, True is returned. + + cuda.bindings.nvvm returns exceptions instead of return codes. + + Parameters + ---------- + options : Sequence[bytes] + List of compiler options as bytes (e.g., [b"-arch=compute_90", b"-g"]). + + Returns + ------- + bool + True if the options are supported, False otherwise. + + Examples + -------- + >>> from cuda.bindings.utils import check_nvvm_options + >>> check_nvvm_options([b"-arch=compute_90", b"-g"]) + True + >>> check_nvvm_options([b"-arch=compute_90", b"-numba-debug"]) + True # if -numba-debug is supported by the installed libNVVM + """ + try: + from cuda.bindings import nvvm + from cuda.bindings._internal.nvvm import _inspect_function_pointer + + if _inspect_function_pointer("__nvvmCreateProgram") == 0: + return False + except Exception: + return False + + program = None + try: + program = nvvm.create_program() + + major, minor, debug_major, debug_minor = nvvm.ir_version() + precheck_ir = _PRECHECK_NVVM_IR.format( + major=major, + minor=minor, + debug_major=debug_major, + debug_minor=debug_minor, + ) + precheck_ir_bytes = precheck_ir.encode("utf-8") + nvvm.add_module_to_program( + program, + precheck_ir_bytes, + len(precheck_ir_bytes), + "precheck.ll", + ) + + options_list = [opt.decode("utf-8") if isinstance(opt, bytes) else opt for opt in options] + nvvm.verify_program(program, len(options_list), options_list) + nvvm.compile_program(program, len(options_list), options_list) + except Exception: + return False + finally: + if program is not None: + try: + nvvm.destroy_program(program) + except Exception: + pass + return True diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index ac40fb735dc..028d1e22d3f 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -70,81 +70,14 @@ def _has_nvrtc_pch_apis_for_tests(): ) -_libnvvm_version = None -_libnvvm_version_attempted = False - -precheck_nvvm_ir = """target triple = "nvptx64-unknown-cuda" -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" - -define void @dummy_kernel() {{ - entry: - ret void -}} - -!nvvm.annotations = !{{!0}} -!0 = !{{void ()* @dummy_kernel, !"kernel", i32 1}} - -!nvvmir.version = !{{!1}} -!1 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}} -""" - - -def _get_libnvvm_version_for_tests(): - """ - Detect libNVVM version by compiling dummy IR and analyzing the PTX output. - - Workaround for the lack of direct libNVVM version API (nvbugs 5312315). - The approach: - - Compile a small dummy NVVM IR to PTX - - Use PTX version analysis APIs if available to infer libNVVM version - - Cache the result for future use - """ - global _libnvvm_version, _libnvvm_version_attempted - - if _libnvvm_version_attempted: - return _libnvvm_version - - _libnvvm_version_attempted = True - +def _check_nvvm_arch(arch: str) -> bool: + """Check if the given NVVM arch is supported by the installed libNVVM.""" try: - from cuda.core._program import _get_nvvm_module - - nvvm = _get_nvvm_module() - - try: - from cuda.bindings.utils import get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver - except ImportError: - _libnvvm_version = None - return _libnvvm_version - - program = nvvm.create_program() - try: - major, minor, debug_major, debug_minor = nvvm.ir_version() - global precheck_nvvm_ir - precheck_nvvm_ir = precheck_nvvm_ir.format( - major=major, minor=minor, debug_major=debug_major, debug_minor=debug_minor - ) - precheck_ir_bytes = precheck_nvvm_ir.encode("utf-8") - nvvm.add_module_to_program(program, precheck_ir_bytes, len(precheck_ir_bytes), "precheck.ll") - - options = ["-arch=compute_90"] - nvvm.verify_program(program, len(options), options) - nvvm.compile_program(program, len(options), options) - - ptx_size = nvvm.get_compiled_result_size(program) - ptx_data = bytearray(ptx_size) - nvvm.get_compiled_result(program, ptx_data) - ptx_str = ptx_data.decode("utf-8") - ptx_version = get_ptx_ver(ptx_str) - cuda_version = get_minimal_required_cuda_ver_from_ptx_ver(ptx_version) - _libnvvm_version = cuda_version - return _libnvvm_version - finally: - nvvm.destroy_program(program) + from cuda.bindings.utils import check_nvvm_options + return check_nvvm_options([f"-arch={arch}".encode()]) except Exception: - _libnvvm_version = None - return _libnvvm_version + return False @pytest.fixture(scope="session") @@ -525,8 +458,8 @@ def test_nvvm_compile_invalid_ir(): pytest.param( ProgramOptions(name="test_sm110_1", arch="sm_110", device_code_optimize=False), marks=pytest.mark.skipif( - (_get_libnvvm_version_for_tests() or 0) < 13000, - reason="Compute capability 110 requires libNVVM >= 13.0", + not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", ), ), pytest.param( @@ -540,15 +473,15 @@ def test_nvvm_compile_invalid_ir(): device_code_optimize=True, ), marks=pytest.mark.skipif( - (_get_libnvvm_version_for_tests() or 0) < 13000, - reason="Compute capability 110 requires libNVVM >= 13.0", + not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", ), ), pytest.param( ProgramOptions(name="test_sm110_3", arch="sm_110", link_time_optimization=True), marks=pytest.mark.skipif( - (_get_libnvvm_version_for_tests() or 0) < 13000, - reason="Compute capability 110 requires libNVVM >= 13.0", + not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", ), ), ], @@ -772,4 +705,4 @@ def test_program_options_as_bytes_nvvm_unsupported_option(): """Test that unsupported options raise CUDAError for NVVM backend""" options = ProgramOptions(arch="sm_80", lineinfo=True) with pytest.raises(CUDAError, match="not supported by NVVM backend"): - options.as_bytes("nvvm") + options.as_bytes("nvvm") \ No newline at end of file From 10943c825e43e63c4d8d2d9320d77d9bea707aea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 13:11:13 +0000 Subject: [PATCH 02/16] [pre-commit.ci] auto code formatting --- cuda_bindings/cuda/bindings/utils/__init__.py | 3 ++- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 6 +++--- cuda_core/tests/test_program.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/__init__.py b/cuda_bindings/cuda/bindings/utils/__init__.py index fd5018ed1ec..c646d59221c 100644 --- a/cuda_bindings/cuda/bindings/utils/__init__.py +++ b/cuda_bindings/cuda/bindings/utils/__init__.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE from typing import Any, Callable +from ._nvvm_utils import check_nvvm_options from ._ptx_utils import get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver from ._version_check import warn_if_cuda_major_version_mismatch -from ._nvvm_utils import check_nvvm_options _handle_getters: dict[type, Callable[[Any], int]] = {} @@ -12,6 +12,7 @@ def _add_cuda_native_handle_getter(t: type, getter: Callable[[Any], int]) -> None: _handle_getters[t] = getter + def get_cuda_native_handle(obj: Any) -> int: """Returns the address of the provided CUDA Python object as a Python int. diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index e8f7dbbf433..0c17c316e44 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -22,7 +22,7 @@ def check_nvvm_options(options: Sequence[bytes]) -> bool: """ Abstracted from https://github.com/NVIDIA/numba-cuda/pull/681 - + Check if the specified options are supported by the current libNVVM version. The options are a list of bytes, each representing a compiler option. @@ -31,8 +31,8 @@ def check_nvvm_options(options: Sequence[bytes]) -> bool: is returned. If the test program compiles successfully, True is returned. - - cuda.bindings.nvvm returns exceptions instead of return codes. + + cuda.bindings.nvvm returns exceptions instead of return codes. Parameters ---------- diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index 028d1e22d3f..be0ac066c35 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -705,4 +705,4 @@ def test_program_options_as_bytes_nvvm_unsupported_option(): """Test that unsupported options raise CUDAError for NVVM backend""" options = ProgramOptions(arch="sm_80", lineinfo=True) with pytest.raises(CUDAError, match="not supported by NVVM backend"): - options.as_bytes("nvvm") \ No newline at end of file + options.as_bytes("nvvm") From a7ef55221b7dc9ed3f7d2b9d1359c4f0e559e578 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Tue, 31 Mar 2026 13:15:14 +0000 Subject: [PATCH 03/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 0c17c316e44..1eeebdd5525 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2026-2027 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +import contextlib from typing import Sequence _PRECHECK_NVVM_IR = """target triple = "nvptx64-unknown-cuda" @@ -87,8 +88,6 @@ def check_nvvm_options(options: Sequence[bytes]) -> bool: return False finally: if program is not None: - try: + with contextlib.suppress(Exception): nvvm.destroy_program(program) - except Exception: - pass return True From 4f3b44236d3b477b78b97657c6001fa04d2c8fbc Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Mon, 6 Apr 2026 09:29:36 +0000 Subject: [PATCH 04/16] renaming --- cuda_bindings/cuda/bindings/utils/__init__.py | 2 +- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 7 +++---- cuda_core/tests/test_program.py | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/__init__.py b/cuda_bindings/cuda/bindings/utils/__init__.py index c646d59221c..79d62d53233 100644 --- a/cuda_bindings/cuda/bindings/utils/__init__.py +++ b/cuda_bindings/cuda/bindings/utils/__init__.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE from typing import Any, Callable -from ._nvvm_utils import check_nvvm_options +from ._nvvm_utils import check_nvvm_compiler_options from ._ptx_utils import get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver from ._version_check import warn_if_cuda_major_version_mismatch diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 1eeebdd5525..42fcd1819c9 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -20,7 +20,7 @@ """ -def check_nvvm_options(options: Sequence[bytes]) -> bool: +def check_nvvm_compiler_options(options: Sequence[str]) -> bool: """ Abstracted from https://github.com/NVIDIA/numba-cuda/pull/681 @@ -81,9 +81,8 @@ def check_nvvm_options(options: Sequence[bytes]) -> bool: "precheck.ll", ) - options_list = [opt.decode("utf-8") if isinstance(opt, bytes) else opt for opt in options] - nvvm.verify_program(program, len(options_list), options_list) - nvvm.compile_program(program, len(options_list), options_list) + nvvm.verify_program(program, len(options), options) + nvvm.compile_program(program, len(options), options) except Exception: return False finally: diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index be0ac066c35..db518a886b7 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -73,9 +73,9 @@ def _has_nvrtc_pch_apis_for_tests(): def _check_nvvm_arch(arch: str) -> bool: """Check if the given NVVM arch is supported by the installed libNVVM.""" try: - from cuda.bindings.utils import check_nvvm_options + from cuda.bindings.utils import check_nvvm_compiler_options - return check_nvvm_options([f"-arch={arch}".encode()]) + return check_nvvm_compiler_options([f"-arch={arch}".encode()]) except Exception: return False From 686c62aa83ac7ac6ab47db153fe629afdba52b27 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Mon, 6 Apr 2026 11:53:40 +0000 Subject: [PATCH 05/16] exceptions --- .../cuda/bindings/utils/_nvvm_utils.py | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 42fcd1819c9..3b8bcf91f34 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -55,38 +55,39 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: """ try: from cuda.bindings import nvvm - from cuda.bindings._internal.nvvm import _inspect_function_pointer - - if _inspect_function_pointer("__nvvmCreateProgram") == 0: + except ModuleNotFoundError as exc: + if exc.name == "nvvm": return False - except Exception: + raise + + from cuda.bindings._internal.nvvm import _inspect_function_pointer + + if _inspect_function_pointer("__nvvmCreateProgram") == 0: return False + + program = nvvm.create_program() + + major, minor, debug_major, debug_minor = nvvm.ir_version() + precheck_ir = _PRECHECK_NVVM_IR.format( + major=major, + minor=minor, + debug_major=debug_major, + debug_minor=debug_minor, + ) + precheck_ir_bytes = precheck_ir.encode("utf-8") + nvvm.add_module_to_program( + program, + precheck_ir_bytes, + len(precheck_ir_bytes), + "precheck.ll", + ) - program = None try: - program = nvvm.create_program() - - major, minor, debug_major, debug_minor = nvvm.ir_version() - precheck_ir = _PRECHECK_NVVM_IR.format( - major=major, - minor=minor, - debug_major=debug_major, - debug_minor=debug_minor, - ) - precheck_ir_bytes = precheck_ir.encode("utf-8") - nvvm.add_module_to_program( - program, - precheck_ir_bytes, - len(precheck_ir_bytes), - "precheck.ll", - ) - - nvvm.verify_program(program, len(options), options) nvvm.compile_program(program, len(options), options) - except Exception: - return False + except nvvm.nvvmError as e: + if e.status == nvvm.Result.ERROR_INVALID_OPTION: + return False + raise finally: - if program is not None: - with contextlib.suppress(Exception): - nvvm.destroy_program(program) + nvvm.destroy_program(program) return True From 3c5043c01e2fa5b05e5ef3dd1cc0b78224dafb6c Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Mon, 6 Apr 2026 12:41:31 +0000 Subject: [PATCH 06/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 2 +- cuda_core/tests/test_program.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 3b8bcf91f34..071c6e5ea64 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026-2027 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE import contextlib diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index db518a886b7..9d92d3ed92d 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -74,11 +74,11 @@ def _check_nvvm_arch(arch: str) -> bool: """Check if the given NVVM arch is supported by the installed libNVVM.""" try: from cuda.bindings.utils import check_nvvm_compiler_options - - return check_nvvm_compiler_options([f"-arch={arch}".encode()]) - except Exception: - return False - + except ModuleNotFoundError as exc: + if exc.name == "cuda": + return False + raise + return check_nvvm_compiler_options([f"-arch={arch}"]) @pytest.fixture(scope="session") def nvvm_ir(): From b1747af02fa7b08cb55a75ca571a5bfca7eb3b98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:44:02 +0000 Subject: [PATCH 07/16] [pre-commit.ci] auto code formatting --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 5 ++--- cuda_core/tests/test_program.py | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 071c6e5ea64..0f15ae68147 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -1,7 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -import contextlib from typing import Sequence _PRECHECK_NVVM_IR = """target triple = "nvptx64-unknown-cuda" @@ -59,12 +58,12 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: if exc.name == "nvvm": return False raise - + from cuda.bindings._internal.nvvm import _inspect_function_pointer if _inspect_function_pointer("__nvvmCreateProgram") == 0: return False - + program = nvvm.create_program() major, minor, debug_major, debug_minor = nvvm.ir_version() diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index 9d92d3ed92d..64307f152e7 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -80,6 +80,7 @@ def _check_nvvm_arch(arch: str) -> bool: raise return check_nvvm_compiler_options([f"-arch={arch}"]) + @pytest.fixture(scope="session") def nvvm_ir(): """Generate working NVVM IR with proper version metadata. From d19960e986715cabe150acb4813db66a8b37adf3 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Tue, 7 Apr 2026 06:59:59 +0000 Subject: [PATCH 08/16] refresh --- cuda_bindings/cuda/bindings/utils/__init__.py | 2 +- .../cuda/bindings/utils/_nvvm_utils.py | 33 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/__init__.py b/cuda_bindings/cuda/bindings/utils/__init__.py index 79d62d53233..3fe75ca13f0 100644 --- a/cuda_bindings/cuda/bindings/utils/__init__.py +++ b/cuda_bindings/cuda/bindings/utils/__init__.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE from typing import Any, Callable diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 0f15ae68147..396c5c90487 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -49,8 +49,6 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: >>> from cuda.bindings.utils import check_nvvm_options >>> check_nvvm_options([b"-arch=compute_90", b"-g"]) True - >>> check_nvvm_options([b"-arch=compute_90", b"-numba-debug"]) - True # if -numba-debug is supported by the installed libNVVM """ try: from cuda.bindings import nvvm @@ -65,23 +63,22 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: return False program = nvvm.create_program() - - major, minor, debug_major, debug_minor = nvvm.ir_version() - precheck_ir = _PRECHECK_NVVM_IR.format( - major=major, - minor=minor, - debug_major=debug_major, - debug_minor=debug_minor, - ) - precheck_ir_bytes = precheck_ir.encode("utf-8") - nvvm.add_module_to_program( - program, - precheck_ir_bytes, - len(precheck_ir_bytes), - "precheck.ll", - ) - try: + major, minor, debug_major, debug_minor = nvvm.ir_version() + precheck_ir = _PRECHECK_NVVM_IR.format( + major=major, + minor=minor, + debug_major=debug_major, + debug_minor=debug_minor, + ) + precheck_ir_bytes = precheck_ir.encode("utf-8") + nvvm.add_module_to_program( + program, + precheck_ir_bytes, + len(precheck_ir_bytes), + "precheck.ll", + ) + nvvm.compile_program(program, len(options), options) except nvvm.nvvmError as e: if e.status == nvvm.Result.ERROR_INVALID_OPTION: From 4a7c3e906cf8118ded34a81c77d99adc42be8de0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 07:01:50 +0000 Subject: [PATCH 09/16] [pre-commit.ci] auto code formatting --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 396c5c90487..bae8cdeac3e 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -78,7 +78,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: len(precheck_ir_bytes), "precheck.ll", ) - + nvvm.compile_program(program, len(options), options) except nvvm.nvvmError as e: if e.status == nvvm.Result.ERROR_INVALID_OPTION: From c13c8607e08fd65c972c52765b73141fd1cb805d Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Tue, 7 Apr 2026 15:18:08 +0000 Subject: [PATCH 10/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index bae8cdeac3e..92f5930b94e 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -78,12 +78,12 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: len(precheck_ir_bytes), "precheck.ll", ) - - nvvm.compile_program(program, len(options), options) - except nvvm.nvvmError as e: - if e.status == nvvm.Result.ERROR_INVALID_OPTION: - return False - raise + try: + nvvm.compile_program(program, len(options), options) + except nvvm.nvvmError as e: + if e.status == nvvm.Result.ERROR_INVALID_OPTION: + return False + raise finally: nvvm.destroy_program(program) return True From e2afa85bc627b021d298acb07a31aebed1aa9658 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Tue, 7 Apr 2026 15:37:16 +0000 Subject: [PATCH 11/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 92f5930b94e..831b0ba3bec 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -25,7 +25,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Check if the specified options are supported by the current libNVVM version. - The options are a list of bytes, each representing a compiler option. + The options are a list of strings, each representing a compiler option. If the test program fails to compile, the options are not supported and False is returned. @@ -37,7 +37,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Parameters ---------- options : Sequence[bytes] - List of compiler options as bytes (e.g., [b"-arch=compute_90", b"-g"]). + List of compiler options as strings (e.g., ["-arch=compute_90", "-g"]). Returns ------- @@ -47,7 +47,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Examples -------- >>> from cuda.bindings.utils import check_nvvm_options - >>> check_nvvm_options([b"-arch=compute_90", b"-g"]) + >>> check_nvvm_options(["-arch=compute_90", "-g"]) True """ try: From 8239ee657c7fe1efd846452f7f0cabfa638b3f2b Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Thu, 16 Apr 2026 10:34:40 +0000 Subject: [PATCH 12/16] refresh --- cuda_bindings/tests/test_utils.py | 49 +++++++++++++++++++++++ cuda_core/tests/test_program.py | 64 ++++++++++++++++++------------- 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/cuda_bindings/tests/test_utils.py b/cuda_bindings/tests/test_utils.py index fd89cd00bde..0fcc706f313 100644 --- a/cuda_bindings/tests/test_utils.py +++ b/cuda_bindings/tests/test_utils.py @@ -11,10 +11,28 @@ from cuda.bindings import driver, runtime from cuda.bindings._internal.utils import get_c_compiler +from cuda.bindings.utils import ( + check_nvvm_compiler_options, + get_cuda_native_handle, + get_minimal_required_cuda_ver_from_ptx_ver, + get_ptx_ver, +) from cuda.bindings.utils import get_cuda_native_handle, get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver have_cufile = importlib.util.find_spec("cuda.bindings.cufile") is not None +def _is_libnvvm_available() -> bool: + try: + from cuda.bindings._internal.nvvm import _inspect_function_pointer + + return _inspect_function_pointer("__nvvmCreateProgram") != 0 + except Exception: + return False + + +_libnvvm_available = _is_libnvvm_available() +_skip_no_libnvvm = pytest.mark.skipif(not _libnvvm_available, reason="libNVVM not available") + ptx_88_kernel = r""" .version 8.8 .target sm_75 @@ -118,3 +136,34 @@ def test_get_c_compiler(): c_compiler = get_c_compiler() prefix = ("GCC", "Clang", "MSVC", "Unknown") assert sum(c_compiler.startswith(p) for p in prefix) == 1 + +@_skip_no_libnvvm +def test_check_nvvm_compiler_options_valid(): + assert check_nvvm_compiler_options(["-arch=compute_90"]) is True + + +@_skip_no_libnvvm +def test_check_nvvm_compiler_options_invalid(): + assert check_nvvm_compiler_options(["--this-is-not-a-valid-option"]) is False + + +@_skip_no_libnvvm +def test_check_nvvm_compiler_options_empty(): + assert check_nvvm_compiler_options([]) is True + + +@_skip_no_libnvvm +def test_check_nvvm_compiler_options_multiple_valid(): + assert check_nvvm_compiler_options(["-arch=compute_90", "-opt=3", "-g"]) is True + + +@_skip_no_libnvvm +def test_check_nvvm_compiler_options_arch_detection(): + assert check_nvvm_compiler_options(["-arch=compute_90"]) is True + assert check_nvvm_compiler_options(["-arch=compute_99999"]) is False + + +def test_check_nvvm_compiler_options_no_libnvvm(): + if _libnvvm_available: + pytest.skip("libNVVM is available; this test targets the fallback path") + assert check_nvvm_compiler_options(["-arch=compute_90"]) is False diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index 64307f152e7..5f1f25eb5fc 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -70,14 +70,25 @@ def _has_nvrtc_pch_apis_for_tests(): ) +def _has_check_nvvm_compiler_options(): + try: + from cuda.bindings.utils import check_nvvm_compiler_options # noqa: F401 + + return True + except ImportError: + return False + + +has_nvvm_option_checker = pytest.mark.skipif( + not _has_check_nvvm_compiler_options(), + reason="cuda.bindings.utils.check_nvvm_compiler_options not available (cuda-bindings too old?)", +) + + def _check_nvvm_arch(arch: str) -> bool: """Check if the given NVVM arch is supported by the installed libNVVM.""" - try: - from cuda.bindings.utils import check_nvvm_compiler_options - except ModuleNotFoundError as exc: - if exc.name == "cuda": - return False - raise + from cuda.bindings.utils import check_nvvm_compiler_options + return check_nvvm_compiler_options([f"-arch={arch}"]) @@ -458,10 +469,13 @@ def test_nvvm_compile_invalid_ir(): ), pytest.param( ProgramOptions(name="test_sm110_1", arch="sm_110", device_code_optimize=False), - marks=pytest.mark.skipif( - not _check_nvvm_arch("compute_110"), - reason="Compute capability 110 not supported by installed libNVVM", - ), + marks=[ + has_nvvm_option_checker, + pytest.mark.skipif( + _has_check_nvvm_compiler_options() and not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", + ), + ], ), pytest.param( ProgramOptions( @@ -473,17 +487,23 @@ def test_nvvm_compile_invalid_ir(): fma=True, device_code_optimize=True, ), - marks=pytest.mark.skipif( - not _check_nvvm_arch("compute_110"), - reason="Compute capability 110 not supported by installed libNVVM", - ), + marks=[ + has_nvvm_option_checker, + pytest.mark.skipif( + _has_check_nvvm_compiler_options() and not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", + ), + ], ), pytest.param( ProgramOptions(name="test_sm110_3", arch="sm_110", link_time_optimization=True), - marks=pytest.mark.skipif( - not _check_nvvm_arch("compute_110"), - reason="Compute capability 110 not supported by installed libNVVM", - ), + marks=[ + has_nvvm_option_checker, + pytest.mark.skipif( + _has_check_nvvm_compiler_options() and not _check_nvvm_arch("compute_110"), + reason="Compute capability 110 not supported by installed libNVVM", + ), + ], ), ], ) @@ -663,12 +683,8 @@ def test_program_options_as_bytes_nvrtc(): """Test ProgramOptions.as_bytes() for NVRTC backend""" options = ProgramOptions(arch="sm_80", debug=True, lineinfo=True, ftz=True) nvrtc_options = options.as_bytes("nvrtc") - - # Should return list of bytes assert isinstance(nvrtc_options, list) assert all(isinstance(opt, bytes) for opt in nvrtc_options) - - # Decode to check content options_str = [opt.decode() for opt in nvrtc_options] assert "-arch=sm_80" in options_str assert "--device-debug" in options_str @@ -681,12 +697,8 @@ def test_program_options_as_bytes_nvvm(): """Test ProgramOptions.as_bytes() for NVVM backend""" options = ProgramOptions(arch="sm_80", debug=True, ftz=True, device_code_optimize=True) nvvm_options = options.as_bytes("nvvm") - - # Should return list of bytes (same as other backends) assert isinstance(nvvm_options, list) assert all(isinstance(opt, bytes) for opt in nvvm_options) - - # Decode to check content options_str = [opt.decode() for opt in nvvm_options] assert "-arch=compute_80" in options_str assert "-g" in options_str From 5c5024c17475c168893c3821b77ba2c748176eab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 10:36:22 +0000 Subject: [PATCH 13/16] [pre-commit.ci] auto code formatting --- cuda_bindings/tests/test_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cuda_bindings/tests/test_utils.py b/cuda_bindings/tests/test_utils.py index 0fcc706f313..645d0ebcca3 100644 --- a/cuda_bindings/tests/test_utils.py +++ b/cuda_bindings/tests/test_utils.py @@ -17,10 +17,10 @@ get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver, ) -from cuda.bindings.utils import get_cuda_native_handle, get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver have_cufile = importlib.util.find_spec("cuda.bindings.cufile") is not None + def _is_libnvvm_available() -> bool: try: from cuda.bindings._internal.nvvm import _inspect_function_pointer @@ -137,6 +137,7 @@ def test_get_c_compiler(): prefix = ("GCC", "Clang", "MSVC", "Unknown") assert sum(c_compiler.startswith(p) for p in prefix) == 1 + @_skip_no_libnvvm def test_check_nvvm_compiler_options_valid(): assert check_nvvm_compiler_options(["-arch=compute_90"]) is True From 9003ff19401b5ada66edf06d98a74683c7736b30 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Fri, 17 Apr 2026 06:47:30 +0000 Subject: [PATCH 14/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 4 ++-- cuda_bindings/tests/test_utils.py | 6 +++--- cuda_core/tests/test_program.py | 7 +++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index 831b0ba3bec..fca4256aa54 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -36,7 +36,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Parameters ---------- - options : Sequence[bytes] + options : Sequence[str] List of compiler options as strings (e.g., ["-arch=compute_90", "-g"]). Returns @@ -46,7 +46,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Examples -------- - >>> from cuda.bindings.utils import check_nvvm_options + >>> from cuda.bindings.utils import check_nvvm_compiler_options >>> check_nvvm_options(["-arch=compute_90", "-g"]) True """ diff --git a/cuda_bindings/tests/test_utils.py b/cuda_bindings/tests/test_utils.py index 645d0ebcca3..4b410dd6f14 100644 --- a/cuda_bindings/tests/test_utils.py +++ b/cuda_bindings/tests/test_utils.py @@ -22,11 +22,11 @@ def _is_libnvvm_available() -> bool: + from cuda.bindings._internal.nvvm import _inspect_function_pointer + from cuda.pathfinder import DynamicLibNotFoundError try: - from cuda.bindings._internal.nvvm import _inspect_function_pointer - return _inspect_function_pointer("__nvvmCreateProgram") != 0 - except Exception: + except DynamicLibNotFoundError: return False diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index 5f1f25eb5fc..f446d6457e3 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -72,11 +72,10 @@ def _has_nvrtc_pch_apis_for_tests(): def _has_check_nvvm_compiler_options(): try: - from cuda.bindings.utils import check_nvvm_compiler_options # noqa: F401 - - return True - except ImportError: + import cuda.bindings.utils as utils + except ModuleNotFoundError: return False + return hasattr(utils, "check_nvvm_compiler_options") has_nvvm_option_checker = pytest.mark.skipif( From 39633c2859420d628d375dfcdb3f507667e8bb82 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 06:55:33 +0000 Subject: [PATCH 15/16] [pre-commit.ci] auto code formatting --- cuda_bindings/tests/test_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cuda_bindings/tests/test_utils.py b/cuda_bindings/tests/test_utils.py index 4b410dd6f14..01e30269291 100644 --- a/cuda_bindings/tests/test_utils.py +++ b/cuda_bindings/tests/test_utils.py @@ -24,6 +24,7 @@ def _is_libnvvm_available() -> bool: from cuda.bindings._internal.nvvm import _inspect_function_pointer from cuda.pathfinder import DynamicLibNotFoundError + try: return _inspect_function_pointer("__nvvmCreateProgram") != 0 except DynamicLibNotFoundError: From 9ad12b1e9c84c2d2c2c6c0012193871e19a967c1 Mon Sep 17 00:00:00 2001 From: abhilash1910 Date: Fri, 17 Apr 2026 06:56:23 +0000 Subject: [PATCH 16/16] refresh --- cuda_bindings/cuda/bindings/utils/_nvvm_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py index fca4256aa54..de7b111e7bf 100644 --- a/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py +++ b/cuda_bindings/cuda/bindings/utils/_nvvm_utils.py @@ -47,7 +47,7 @@ def check_nvvm_compiler_options(options: Sequence[str]) -> bool: Examples -------- >>> from cuda.bindings.utils import check_nvvm_compiler_options - >>> check_nvvm_options(["-arch=compute_90", "-g"]) + >>> check_nvvm_compiler_options(["-arch=compute_90", "-g"]) True """ try: