Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions numba/cuda/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
from numba.core.compiler import (CompilerBase, DefaultPassBuilder,
compile_result, Flags, Option)
from numba.core.compiler_lock import global_compiler_lock
from numba.core.compiler_machinery import (LoweringPass, PassManager,
register_pass)
from numba.core.compiler_machinery import (LoweringPass, AnalysisPass,
PassManager, register_pass)
from numba.core.dispatcher import CompilingCounter, OmittedArg
from numba.core.errors import NumbaInvalidConfigWarning
from numba.core.errors import (NumbaPerformanceWarning,
NumbaInvalidConfigWarning, TypingError)
from numba.core.typed_passes import IRLegalization, NativeLowering
from numba.core.typing.typeof import Purpose, typeof
from warnings import warn
Expand All @@ -29,7 +30,6 @@
from .errors import missing_launch_config_msg, normalize_kernel_dimensions
from .api import get_current_device
from .args import wrap_arg
from numba.core.errors import NumbaPerformanceWarning
from .descriptor import cuda_target
from . import types as cuda_types

Expand Down Expand Up @@ -103,6 +103,33 @@ def run_pass(self, state):
return True


@register_pass(mutates_CFG=False, analysis_only=True)
class CUDALegalization(AnalysisPass):

_name = "cuda_legalization"

def __init__(self):
AnalysisPass.__init__(self)

def run_pass(self, state):
# Early return if NVVM 7
from numba.cuda.cudadrv.nvvm import NVVM
if NVVM().is_nvvm70:
return False
# NVVM < 7, need to check for charseq
typmap = state.typemap
for k, v in typmap.items():
if isinstance(v, types.Array):
Comment thread
stuartarchibald marked this conversation as resolved.
Resolved
if isinstance(v.dtype, (types.UnicodeCharSeq, types.CharSeq)):
msg = (f"{k} is a char sequence type. This type is not "
"supported with CUDA toolkit versions < 11.2. To "
"use this type, you need to update your CUDA "
"toolkit - try 'conda install cudatoolkit=11' if "
"you are using conda to manage your environment.")
raise TypingError(msg)
return False


class CUDACompiler(CompilerBase):
def define_pipelines(self):
dpb = DefaultPassBuilder
Expand All @@ -113,6 +140,7 @@ def define_pipelines(self):

typed_passes = dpb.define_typed_pipeline(self.state)
pm.passes.extend(typed_passes.passes)
pm.add_pass(CUDALegalization, "CUDA legalization")

lowering_passes = self.define_cuda_lowering_pipeline(self.state)
pm.passes.extend(lowering_passes.passes)
Expand Down
3 changes: 2 additions & 1 deletion numba/cuda/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def load_additional_registries(self):
# side effect of import needed for numba.cpython.*, the builtins
# registry is updated at import time.
from numba.cpython import numbers, tupleobj, slicing # noqa: F401
from numba.cpython import rangeobj, iterators, unicode # noqa: F401
from numba.cpython import rangeobj, iterators # noqa: F401
from numba.cpython import unicode, charseq # noqa: F401
from numba.cpython import cmathimpl
from numba.np import arrayobj # noqa: F401
from numba.np import npdatetime # noqa: F401
Expand Down
47 changes: 45 additions & 2 deletions numba/cuda/tests/cudapy/test_const_string.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import re
from numba.cuda.testing import unittest, skip_on_cudasim
import numpy as np
from numba import config, cuda
from numba.core.errors import TypingError
from numba.cuda.cudadrv.nvvm import NVVM
from numba.cuda.testing import unittest, skip_on_cudasim, CUDATestCase
from llvmlite import ir


@skip_on_cudasim("This is testing CUDA backend code generation")
class TestCudaConstString(unittest.TestCase):
class TestConstStringCodegen(unittest.TestCase):
def test_const_string(self):
# These imports are incompatible with CUDASIM
from numba.cuda.descriptor import cuda_target
Expand Down Expand Up @@ -52,5 +56,44 @@ def test_const_string(self):
self.assertEqual(len(matches), 1)


class TestConstString(CUDATestCase):
def test_assign_const_string(self):
# There is no NVVM on cudasim, but we might as well run this test.
if not config.ENABLE_CUDASIM and not NVVM().is_nvvm70:
self.skipTest('Character sequences unsupported on NVVM 3.4')

# Inspired by the reproducer from Issue #7041.

@cuda.jit
def str_assign(arr):
i = cuda.grid(1)
if i < len(arr):
arr[i] = "XYZ"

n_strings = 8
arr = np.zeros(n_strings + 1, dtype="<U12")
str_assign[1, n_strings](arr)

# Expected result, e.g.:
# ['XYZ' 'XYZ' 'XYZ' 'XYZ' 'XYZ' 'XYZ' 'XYZ' 'XYZ' '']
expected = np.zeros_like(arr)
expected[:-1] = 'XYZ'
expected[-1] = ''
np.testing.assert_equal(arr, expected)

@skip_on_cudasim('Const strings not disallowed on cudasim')
Comment thread
stuartarchibald marked this conversation as resolved.
Resolved
def test_const_string_disallowed_nvvm34(self):
if NVVM().is_nvvm70:
self.skipTest('Character sequences are permitted with NVVM 7.0')

@cuda.jit
def str_assign(arr):
arr[0] = "XYZ"

arr = np.zeros(1, dtype="<U12")
with self.assertRaisesRegex(TypingError, '.*is a char sequence.*'):
str_assign[1, 1](arr)
Comment thread
stuartarchibald marked this conversation as resolved.
Resolved


if __name__ == '__main__':
unittest.main()