numba-cuda 0.0.1__py3-none-any.whl → 0.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. _numba_cuda_redirector.pth +1 -0
  2. _numba_cuda_redirector.py +74 -0
  3. numba_cuda/VERSION +1 -0
  4. numba_cuda/__init__.py +5 -0
  5. numba_cuda/_version.py +19 -0
  6. numba_cuda/numba/cuda/__init__.py +22 -0
  7. numba_cuda/numba/cuda/api.py +526 -0
  8. numba_cuda/numba/cuda/api_util.py +30 -0
  9. numba_cuda/numba/cuda/args.py +77 -0
  10. numba_cuda/numba/cuda/cg.py +62 -0
  11. numba_cuda/numba/cuda/codegen.py +378 -0
  12. numba_cuda/numba/cuda/compiler.py +422 -0
  13. numba_cuda/numba/cuda/cpp_function_wrappers.cu +47 -0
  14. numba_cuda/numba/cuda/cuda_fp16.h +3631 -0
  15. numba_cuda/numba/cuda/cuda_fp16.hpp +2465 -0
  16. numba_cuda/numba/cuda/cuda_paths.py +258 -0
  17. numba_cuda/numba/cuda/cudadecl.py +806 -0
  18. numba_cuda/numba/cuda/cudadrv/__init__.py +9 -0
  19. numba_cuda/numba/cuda/cudadrv/devicearray.py +904 -0
  20. numba_cuda/numba/cuda/cudadrv/devices.py +248 -0
  21. numba_cuda/numba/cuda/cudadrv/driver.py +3201 -0
  22. numba_cuda/numba/cuda/cudadrv/drvapi.py +398 -0
  23. numba_cuda/numba/cuda/cudadrv/dummyarray.py +452 -0
  24. numba_cuda/numba/cuda/cudadrv/enums.py +607 -0
  25. numba_cuda/numba/cuda/cudadrv/error.py +36 -0
  26. numba_cuda/numba/cuda/cudadrv/libs.py +176 -0
  27. numba_cuda/numba/cuda/cudadrv/ndarray.py +20 -0
  28. numba_cuda/numba/cuda/cudadrv/nvrtc.py +260 -0
  29. numba_cuda/numba/cuda/cudadrv/nvvm.py +707 -0
  30. numba_cuda/numba/cuda/cudadrv/rtapi.py +10 -0
  31. numba_cuda/numba/cuda/cudadrv/runtime.py +142 -0
  32. numba_cuda/numba/cuda/cudaimpl.py +1055 -0
  33. numba_cuda/numba/cuda/cudamath.py +140 -0
  34. numba_cuda/numba/cuda/decorators.py +189 -0
  35. numba_cuda/numba/cuda/descriptor.py +33 -0
  36. numba_cuda/numba/cuda/device_init.py +89 -0
  37. numba_cuda/numba/cuda/deviceufunc.py +908 -0
  38. numba_cuda/numba/cuda/dispatcher.py +1057 -0
  39. numba_cuda/numba/cuda/errors.py +59 -0
  40. numba_cuda/numba/cuda/extending.py +7 -0
  41. numba_cuda/numba/cuda/initialize.py +13 -0
  42. numba_cuda/numba/cuda/intrinsic_wrapper.py +77 -0
  43. numba_cuda/numba/cuda/intrinsics.py +198 -0
  44. numba_cuda/numba/cuda/kernels/__init__.py +0 -0
  45. numba_cuda/numba/cuda/kernels/reduction.py +262 -0
  46. numba_cuda/numba/cuda/kernels/transpose.py +65 -0
  47. numba_cuda/numba/cuda/libdevice.py +3382 -0
  48. numba_cuda/numba/cuda/libdevicedecl.py +17 -0
  49. numba_cuda/numba/cuda/libdevicefuncs.py +1057 -0
  50. numba_cuda/numba/cuda/libdeviceimpl.py +83 -0
  51. numba_cuda/numba/cuda/mathimpl.py +448 -0
  52. numba_cuda/numba/cuda/models.py +48 -0
  53. numba_cuda/numba/cuda/nvvmutils.py +235 -0
  54. numba_cuda/numba/cuda/printimpl.py +86 -0
  55. numba_cuda/numba/cuda/random.py +292 -0
  56. numba_cuda/numba/cuda/simulator/__init__.py +38 -0
  57. numba_cuda/numba/cuda/simulator/api.py +110 -0
  58. numba_cuda/numba/cuda/simulator/compiler.py +9 -0
  59. numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +2 -0
  60. numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +432 -0
  61. numba_cuda/numba/cuda/simulator/cudadrv/devices.py +117 -0
  62. numba_cuda/numba/cuda/simulator/cudadrv/driver.py +62 -0
  63. numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +4 -0
  64. numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +4 -0
  65. numba_cuda/numba/cuda/simulator/cudadrv/error.py +6 -0
  66. numba_cuda/numba/cuda/simulator/cudadrv/libs.py +2 -0
  67. numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +29 -0
  68. numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +19 -0
  69. numba_cuda/numba/cuda/simulator/kernel.py +308 -0
  70. numba_cuda/numba/cuda/simulator/kernelapi.py +495 -0
  71. numba_cuda/numba/cuda/simulator/reduction.py +15 -0
  72. numba_cuda/numba/cuda/simulator/vector_types.py +58 -0
  73. numba_cuda/numba/cuda/simulator_init.py +17 -0
  74. numba_cuda/numba/cuda/stubs.py +902 -0
  75. numba_cuda/numba/cuda/target.py +440 -0
  76. numba_cuda/numba/cuda/testing.py +202 -0
  77. numba_cuda/numba/cuda/tests/__init__.py +58 -0
  78. numba_cuda/numba/cuda/tests/cudadrv/__init__.py +8 -0
  79. numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +145 -0
  80. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +145 -0
  81. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +375 -0
  82. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +21 -0
  83. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +179 -0
  84. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +235 -0
  85. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_libraries.py +22 -0
  86. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +193 -0
  87. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +547 -0
  88. numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +249 -0
  89. numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +81 -0
  90. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +192 -0
  91. numba_cuda/numba/cuda/tests/cudadrv/test_events.py +38 -0
  92. numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +65 -0
  93. numba_cuda/numba/cuda/tests/cudadrv/test_init.py +139 -0
  94. numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +37 -0
  95. numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +12 -0
  96. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +317 -0
  97. numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +127 -0
  98. numba_cuda/numba/cuda/tests/cudadrv/test_mvc.py +54 -0
  99. numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +199 -0
  100. numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +37 -0
  101. numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +20 -0
  102. numba_cuda/numba/cuda/tests/cudadrv/test_ptds.py +149 -0
  103. numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +36 -0
  104. numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +85 -0
  105. numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +41 -0
  106. numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +122 -0
  107. numba_cuda/numba/cuda/tests/cudapy/__init__.py +8 -0
  108. numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +234 -0
  109. numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +41 -0
  110. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +58 -0
  111. numba_cuda/numba/cuda/tests/cudapy/jitlink.ptx +30 -0
  112. numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +100 -0
  113. numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +42 -0
  114. numba_cuda/numba/cuda/tests/cudapy/test_array.py +260 -0
  115. numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +201 -0
  116. numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +35 -0
  117. numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1620 -0
  118. numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +120 -0
  119. numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +24 -0
  120. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +545 -0
  121. numba_cuda/numba/cuda/tests/cudapy/test_casting.py +257 -0
  122. numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +33 -0
  123. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +276 -0
  124. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +296 -0
  125. numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +20 -0
  126. numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +129 -0
  127. numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +176 -0
  128. numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +147 -0
  129. numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +435 -0
  130. numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +90 -0
  131. numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +94 -0
  132. numba_cuda/numba/cuda/tests/cudapy/test_debug.py +101 -0
  133. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +221 -0
  134. numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +222 -0
  135. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +700 -0
  136. numba_cuda/numba/cuda/tests/cudapy/test_enums.py +121 -0
  137. numba_cuda/numba/cuda/tests/cudapy/test_errors.py +79 -0
  138. numba_cuda/numba/cuda/tests/cudapy/test_exception.py +174 -0
  139. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +155 -0
  140. numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +244 -0
  141. numba_cuda/numba/cuda/tests/cudapy/test_forall.py +52 -0
  142. numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +29 -0
  143. numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +66 -0
  144. numba_cuda/numba/cuda/tests/cudapy/test_globals.py +60 -0
  145. numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +456 -0
  146. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +159 -0
  147. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +95 -0
  148. numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +37 -0
  149. numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +165 -0
  150. numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +1106 -0
  151. numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +318 -0
  152. numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +99 -0
  153. numba_cuda/numba/cuda/tests/cudapy/test_lang.py +64 -0
  154. numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +119 -0
  155. numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +187 -0
  156. numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +199 -0
  157. numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +164 -0
  158. numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +37 -0
  159. numba_cuda/numba/cuda/tests/cudapy/test_math.py +786 -0
  160. numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +74 -0
  161. numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +113 -0
  162. numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +22 -0
  163. numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +140 -0
  164. numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +46 -0
  165. numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +101 -0
  166. numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +49 -0
  167. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +401 -0
  168. numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +86 -0
  169. numba_cuda/numba/cuda/tests/cudapy/test_overload.py +335 -0
  170. numba_cuda/numba/cuda/tests/cudapy/test_powi.py +124 -0
  171. numba_cuda/numba/cuda/tests/cudapy/test_print.py +128 -0
  172. numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +33 -0
  173. numba_cuda/numba/cuda/tests/cudapy/test_random.py +104 -0
  174. numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +610 -0
  175. numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +125 -0
  176. numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +76 -0
  177. numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +83 -0
  178. numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +85 -0
  179. numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +37 -0
  180. numba_cuda/numba/cuda/tests/cudapy/test_sm.py +444 -0
  181. numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +205 -0
  182. numba_cuda/numba/cuda/tests/cudapy/test_sync.py +271 -0
  183. numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +80 -0
  184. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +277 -0
  185. numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +47 -0
  186. numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +307 -0
  187. numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +283 -0
  188. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +20 -0
  189. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +69 -0
  190. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +36 -0
  191. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +37 -0
  192. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +139 -0
  193. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +276 -0
  194. numba_cuda/numba/cuda/tests/cudasim/__init__.py +6 -0
  195. numba_cuda/numba/cuda/tests/cudasim/support.py +6 -0
  196. numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +102 -0
  197. numba_cuda/numba/cuda/tests/data/__init__.py +0 -0
  198. numba_cuda/numba/cuda/tests/data/cuda_include.cu +5 -0
  199. numba_cuda/numba/cuda/tests/data/error.cu +7 -0
  200. numba_cuda/numba/cuda/tests/data/jitlink.cu +23 -0
  201. numba_cuda/numba/cuda/tests/data/jitlink.ptx +51 -0
  202. numba_cuda/numba/cuda/tests/data/warn.cu +7 -0
  203. numba_cuda/numba/cuda/tests/doc_examples/__init__.py +6 -0
  204. numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +0 -0
  205. numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +49 -0
  206. numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +77 -0
  207. numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +76 -0
  208. numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +82 -0
  209. numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +155 -0
  210. numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +173 -0
  211. numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +109 -0
  212. numba_cuda/numba/cuda/tests/doc_examples/test_random.py +59 -0
  213. numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +76 -0
  214. numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +130 -0
  215. numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +50 -0
  216. numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +73 -0
  217. numba_cuda/numba/cuda/tests/nocuda/__init__.py +8 -0
  218. numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +359 -0
  219. numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +36 -0
  220. numba_cuda/numba/cuda/tests/nocuda/test_import.py +49 -0
  221. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +238 -0
  222. numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +54 -0
  223. numba_cuda/numba/cuda/types.py +37 -0
  224. numba_cuda/numba/cuda/ufuncs.py +662 -0
  225. numba_cuda/numba/cuda/vector_types.py +209 -0
  226. numba_cuda/numba/cuda/vectorizers.py +252 -0
  227. numba_cuda-0.0.13.dist-info/LICENSE +25 -0
  228. numba_cuda-0.0.13.dist-info/METADATA +69 -0
  229. numba_cuda-0.0.13.dist-info/RECORD +231 -0
  230. {numba_cuda-0.0.1.dist-info → numba_cuda-0.0.13.dist-info}/WHEEL +1 -1
  231. numba_cuda-0.0.1.dist-info/METADATA +0 -10
  232. numba_cuda-0.0.1.dist-info/RECORD +0 -5
  233. {numba_cuda-0.0.1.dist-info → numba_cuda-0.0.13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1055 @@
1
+ from functools import reduce
2
+ import operator
3
+ import math
4
+
5
+ from llvmlite import ir
6
+ import llvmlite.binding as ll
7
+
8
+ from numba.core.imputils import Registry, lower_cast
9
+ from numba.core.typing.npydecl import parse_dtype
10
+ from numba.core.datamodel import models
11
+ from numba.core import types, cgutils
12
+ from numba.np import ufunc_db
13
+ from numba.np.npyimpl import register_ufuncs
14
+ from .cudadrv import nvvm
15
+ from numba import cuda
16
+ from numba.cuda import nvvmutils, stubs, errors
17
+ from numba.cuda.types import dim3, CUDADispatcher
18
+
19
+ registry = Registry()
20
+ lower = registry.lower
21
+ lower_attr = registry.lower_getattr
22
+ lower_constant = registry.lower_constant
23
+
24
+
25
+ def initialize_dim3(builder, prefix):
26
+ x = nvvmutils.call_sreg(builder, "%s.x" % prefix)
27
+ y = nvvmutils.call_sreg(builder, "%s.y" % prefix)
28
+ z = nvvmutils.call_sreg(builder, "%s.z" % prefix)
29
+ return cgutils.pack_struct(builder, (x, y, z))
30
+
31
+
32
+ @lower_attr(types.Module(cuda), 'threadIdx')
33
+ def cuda_threadIdx(context, builder, sig, args):
34
+ return initialize_dim3(builder, 'tid')
35
+
36
+
37
+ @lower_attr(types.Module(cuda), 'blockDim')
38
+ def cuda_blockDim(context, builder, sig, args):
39
+ return initialize_dim3(builder, 'ntid')
40
+
41
+
42
+ @lower_attr(types.Module(cuda), 'blockIdx')
43
+ def cuda_blockIdx(context, builder, sig, args):
44
+ return initialize_dim3(builder, 'ctaid')
45
+
46
+
47
+ @lower_attr(types.Module(cuda), 'gridDim')
48
+ def cuda_gridDim(context, builder, sig, args):
49
+ return initialize_dim3(builder, 'nctaid')
50
+
51
+
52
+ @lower_attr(types.Module(cuda), 'laneid')
53
+ def cuda_laneid(context, builder, sig, args):
54
+ return nvvmutils.call_sreg(builder, 'laneid')
55
+
56
+
57
+ @lower_attr(dim3, 'x')
58
+ def dim3_x(context, builder, sig, args):
59
+ return builder.extract_value(args, 0)
60
+
61
+
62
+ @lower_attr(dim3, 'y')
63
+ def dim3_y(context, builder, sig, args):
64
+ return builder.extract_value(args, 1)
65
+
66
+
67
+ @lower_attr(dim3, 'z')
68
+ def dim3_z(context, builder, sig, args):
69
+ return builder.extract_value(args, 2)
70
+
71
+
72
+ # -----------------------------------------------------------------------------
73
+
74
+ @lower(cuda.const.array_like, types.Array)
75
+ def cuda_const_array_like(context, builder, sig, args):
76
+ # This is a no-op because CUDATargetContext.make_constant_array already
77
+ # created the constant array.
78
+ return args[0]
79
+
80
+
81
+ _unique_smem_id = 0
82
+
83
+
84
+ def _get_unique_smem_id(name):
85
+ """Due to bug with NVVM invalid internalizing of shared memory in the
86
+ PTX output. We can't mark shared memory to be internal. We have to
87
+ ensure unique name is generated for shared memory symbol.
88
+ """
89
+ global _unique_smem_id
90
+ _unique_smem_id += 1
91
+ return "{0}_{1}".format(name, _unique_smem_id)
92
+
93
+
94
+ @lower(cuda.shared.array, types.IntegerLiteral, types.Any)
95
+ def cuda_shared_array_integer(context, builder, sig, args):
96
+ length = sig.args[0].literal_value
97
+ dtype = parse_dtype(sig.args[1])
98
+ return _generic_array(context, builder, shape=(length,), dtype=dtype,
99
+ symbol_name=_get_unique_smem_id('_cudapy_smem'),
100
+ addrspace=nvvm.ADDRSPACE_SHARED,
101
+ can_dynsized=True)
102
+
103
+
104
+ @lower(cuda.shared.array, types.Tuple, types.Any)
105
+ @lower(cuda.shared.array, types.UniTuple, types.Any)
106
+ def cuda_shared_array_tuple(context, builder, sig, args):
107
+ shape = [ s.literal_value for s in sig.args[0] ]
108
+ dtype = parse_dtype(sig.args[1])
109
+ return _generic_array(context, builder, shape=shape, dtype=dtype,
110
+ symbol_name=_get_unique_smem_id('_cudapy_smem'),
111
+ addrspace=nvvm.ADDRSPACE_SHARED,
112
+ can_dynsized=True)
113
+
114
+
115
+ @lower(cuda.local.array, types.IntegerLiteral, types.Any)
116
+ def cuda_local_array_integer(context, builder, sig, args):
117
+ length = sig.args[0].literal_value
118
+ dtype = parse_dtype(sig.args[1])
119
+ return _generic_array(context, builder, shape=(length,), dtype=dtype,
120
+ symbol_name='_cudapy_lmem',
121
+ addrspace=nvvm.ADDRSPACE_LOCAL,
122
+ can_dynsized=False)
123
+
124
+
125
+ @lower(cuda.local.array, types.Tuple, types.Any)
126
+ @lower(cuda.local.array, types.UniTuple, types.Any)
127
+ def ptx_lmem_alloc_array(context, builder, sig, args):
128
+ shape = [ s.literal_value for s in sig.args[0] ]
129
+ dtype = parse_dtype(sig.args[1])
130
+ return _generic_array(context, builder, shape=shape, dtype=dtype,
131
+ symbol_name='_cudapy_lmem',
132
+ addrspace=nvvm.ADDRSPACE_LOCAL,
133
+ can_dynsized=False)
134
+
135
+
136
+ @lower(stubs.threadfence_block)
137
+ def ptx_threadfence_block(context, builder, sig, args):
138
+ assert not args
139
+ fname = 'llvm.nvvm.membar.cta'
140
+ lmod = builder.module
141
+ fnty = ir.FunctionType(ir.VoidType(), ())
142
+ sync = cgutils.get_or_insert_function(lmod, fnty, fname)
143
+ builder.call(sync, ())
144
+ return context.get_dummy_value()
145
+
146
+
147
+ @lower(stubs.threadfence_system)
148
+ def ptx_threadfence_system(context, builder, sig, args):
149
+ assert not args
150
+ fname = 'llvm.nvvm.membar.sys'
151
+ lmod = builder.module
152
+ fnty = ir.FunctionType(ir.VoidType(), ())
153
+ sync = cgutils.get_or_insert_function(lmod, fnty, fname)
154
+ builder.call(sync, ())
155
+ return context.get_dummy_value()
156
+
157
+
158
+ @lower(stubs.threadfence)
159
+ def ptx_threadfence_device(context, builder, sig, args):
160
+ assert not args
161
+ fname = 'llvm.nvvm.membar.gl'
162
+ lmod = builder.module
163
+ fnty = ir.FunctionType(ir.VoidType(), ())
164
+ sync = cgutils.get_or_insert_function(lmod, fnty, fname)
165
+ builder.call(sync, ())
166
+ return context.get_dummy_value()
167
+
168
+
169
+ @lower(stubs.syncwarp)
170
+ def ptx_syncwarp(context, builder, sig, args):
171
+ mask = context.get_constant(types.int32, 0xFFFFFFFF)
172
+ mask_sig = types.none(types.int32)
173
+ return ptx_syncwarp_mask(context, builder, mask_sig, [mask])
174
+
175
+
176
+ @lower(stubs.syncwarp, types.i4)
177
+ def ptx_syncwarp_mask(context, builder, sig, args):
178
+ fname = 'llvm.nvvm.bar.warp.sync'
179
+ lmod = builder.module
180
+ fnty = ir.FunctionType(ir.VoidType(), (ir.IntType(32),))
181
+ sync = cgutils.get_or_insert_function(lmod, fnty, fname)
182
+ builder.call(sync, args)
183
+ return context.get_dummy_value()
184
+
185
+
186
+ @lower(stubs.shfl_sync_intrinsic, types.i4, types.i4, types.i4, types.i4,
187
+ types.i4)
188
+ @lower(stubs.shfl_sync_intrinsic, types.i4, types.i4, types.i8, types.i4,
189
+ types.i4)
190
+ @lower(stubs.shfl_sync_intrinsic, types.i4, types.i4, types.f4, types.i4,
191
+ types.i4)
192
+ @lower(stubs.shfl_sync_intrinsic, types.i4, types.i4, types.f8, types.i4,
193
+ types.i4)
194
+ def ptx_shfl_sync_i32(context, builder, sig, args):
195
+ """
196
+ The NVVM intrinsic for shfl only supports i32, but the cuda intrinsic
197
+ function supports both 32 and 64 bit ints and floats, so for feature parity,
198
+ i64, f32, and f64 are implemented. Floats by way of bitcasting the float to
199
+ an int, then shuffling, then bitcasting back. And 64-bit values by packing
200
+ them into 2 32bit values, shuffling thoose, and then packing back together.
201
+ """
202
+ mask, mode, value, index, clamp = args
203
+ value_type = sig.args[2]
204
+ if value_type in types.real_domain:
205
+ value = builder.bitcast(value, ir.IntType(value_type.bitwidth))
206
+ fname = 'llvm.nvvm.shfl.sync.i32'
207
+ lmod = builder.module
208
+ fnty = ir.FunctionType(
209
+ ir.LiteralStructType((ir.IntType(32), ir.IntType(1))),
210
+ (ir.IntType(32), ir.IntType(32), ir.IntType(32),
211
+ ir.IntType(32), ir.IntType(32))
212
+ )
213
+ func = cgutils.get_or_insert_function(lmod, fnty, fname)
214
+ if value_type.bitwidth == 32:
215
+ ret = builder.call(func, (mask, mode, value, index, clamp))
216
+ if value_type == types.float32:
217
+ rv = builder.extract_value(ret, 0)
218
+ pred = builder.extract_value(ret, 1)
219
+ fv = builder.bitcast(rv, ir.FloatType())
220
+ ret = cgutils.make_anonymous_struct(builder, (fv, pred))
221
+ else:
222
+ value1 = builder.trunc(value, ir.IntType(32))
223
+ value_lshr = builder.lshr(value, context.get_constant(types.i8, 32))
224
+ value2 = builder.trunc(value_lshr, ir.IntType(32))
225
+ ret1 = builder.call(func, (mask, mode, value1, index, clamp))
226
+ ret2 = builder.call(func, (mask, mode, value2, index, clamp))
227
+ rv1 = builder.extract_value(ret1, 0)
228
+ rv2 = builder.extract_value(ret2, 0)
229
+ pred = builder.extract_value(ret1, 1)
230
+ rv1_64 = builder.zext(rv1, ir.IntType(64))
231
+ rv2_64 = builder.zext(rv2, ir.IntType(64))
232
+ rv_shl = builder.shl(rv2_64, context.get_constant(types.i8, 32))
233
+ rv = builder.or_(rv_shl, rv1_64)
234
+ if value_type == types.float64:
235
+ rv = builder.bitcast(rv, ir.DoubleType())
236
+ ret = cgutils.make_anonymous_struct(builder, (rv, pred))
237
+ return ret
238
+
239
+
240
+ @lower(stubs.vote_sync_intrinsic, types.i4, types.i4, types.boolean)
241
+ def ptx_vote_sync(context, builder, sig, args):
242
+ fname = 'llvm.nvvm.vote.sync'
243
+ lmod = builder.module
244
+ fnty = ir.FunctionType(ir.LiteralStructType((ir.IntType(32),
245
+ ir.IntType(1))),
246
+ (ir.IntType(32), ir.IntType(32), ir.IntType(1)))
247
+ func = cgutils.get_or_insert_function(lmod, fnty, fname)
248
+ return builder.call(func, args)
249
+
250
+
251
+ @lower(stubs.match_any_sync, types.i4, types.i4)
252
+ @lower(stubs.match_any_sync, types.i4, types.i8)
253
+ @lower(stubs.match_any_sync, types.i4, types.f4)
254
+ @lower(stubs.match_any_sync, types.i4, types.f8)
255
+ def ptx_match_any_sync(context, builder, sig, args):
256
+ mask, value = args
257
+ width = sig.args[1].bitwidth
258
+ if sig.args[1] in types.real_domain:
259
+ value = builder.bitcast(value, ir.IntType(width))
260
+ fname = 'llvm.nvvm.match.any.sync.i{}'.format(width)
261
+ lmod = builder.module
262
+ fnty = ir.FunctionType(ir.IntType(32), (ir.IntType(32), ir.IntType(width)))
263
+ func = cgutils.get_or_insert_function(lmod, fnty, fname)
264
+ return builder.call(func, (mask, value))
265
+
266
+
267
+ @lower(stubs.match_all_sync, types.i4, types.i4)
268
+ @lower(stubs.match_all_sync, types.i4, types.i8)
269
+ @lower(stubs.match_all_sync, types.i4, types.f4)
270
+ @lower(stubs.match_all_sync, types.i4, types.f8)
271
+ def ptx_match_all_sync(context, builder, sig, args):
272
+ mask, value = args
273
+ width = sig.args[1].bitwidth
274
+ if sig.args[1] in types.real_domain:
275
+ value = builder.bitcast(value, ir.IntType(width))
276
+ fname = 'llvm.nvvm.match.all.sync.i{}'.format(width)
277
+ lmod = builder.module
278
+ fnty = ir.FunctionType(ir.LiteralStructType((ir.IntType(32),
279
+ ir.IntType(1))),
280
+ (ir.IntType(32), ir.IntType(width)))
281
+ func = cgutils.get_or_insert_function(lmod, fnty, fname)
282
+ return builder.call(func, (mask, value))
283
+
284
+
285
+ @lower(stubs.activemask)
286
+ def ptx_activemask(context, builder, sig, args):
287
+ activemask = ir.InlineAsm(ir.FunctionType(ir.IntType(32), []),
288
+ "activemask.b32 $0;", '=r', side_effect=True)
289
+ return builder.call(activemask, [])
290
+
291
+
292
+ @lower(stubs.lanemask_lt)
293
+ def ptx_lanemask_lt(context, builder, sig, args):
294
+ activemask = ir.InlineAsm(ir.FunctionType(ir.IntType(32), []),
295
+ "mov.u32 $0, %lanemask_lt;", '=r',
296
+ side_effect=True)
297
+ return builder.call(activemask, [])
298
+
299
+
300
+ @lower(stubs.popc, types.Any)
301
+ def ptx_popc(context, builder, sig, args):
302
+ return builder.ctpop(args[0])
303
+
304
+
305
+ @lower(stubs.fma, types.Any, types.Any, types.Any)
306
+ def ptx_fma(context, builder, sig, args):
307
+ return builder.fma(*args)
308
+
309
+
310
+ def float16_float_ty_constraint(bitwidth):
311
+ typemap = {32: ('f32', 'f'), 64: ('f64', 'd')}
312
+
313
+ try:
314
+ return typemap[bitwidth]
315
+ except KeyError:
316
+ msg = f"Conversion between float16 and float{bitwidth} unsupported"
317
+ raise errors.CudaLoweringError(msg)
318
+
319
+
320
+ @lower_cast(types.float16, types.Float)
321
+ def float16_to_float_cast(context, builder, fromty, toty, val):
322
+ if fromty.bitwidth == toty.bitwidth:
323
+ return val
324
+
325
+ ty, constraint = float16_float_ty_constraint(toty.bitwidth)
326
+
327
+ fnty = ir.FunctionType(context.get_value_type(toty), [ir.IntType(16)])
328
+ asm = ir.InlineAsm(fnty, f"cvt.{ty}.f16 $0, $1;", f"={constraint},h")
329
+ return builder.call(asm, [val])
330
+
331
+
332
+ @lower_cast(types.Float, types.float16)
333
+ def float_to_float16_cast(context, builder, fromty, toty, val):
334
+ if fromty.bitwidth == toty.bitwidth:
335
+ return val
336
+
337
+ ty, constraint = float16_float_ty_constraint(fromty.bitwidth)
338
+
339
+ fnty = ir.FunctionType(ir.IntType(16), [context.get_value_type(fromty)])
340
+ asm = ir.InlineAsm(fnty, f"cvt.rn.f16.{ty} $0, $1;", f"=h,{constraint}")
341
+ return builder.call(asm, [val])
342
+
343
+
344
+ def float16_int_constraint(bitwidth):
345
+ typemap = { 8: 'c', 16: 'h', 32: 'r', 64: 'l' }
346
+
347
+ try:
348
+ return typemap[bitwidth]
349
+ except KeyError:
350
+ msg = f"Conversion between float16 and int{bitwidth} unsupported"
351
+ raise errors.CudaLoweringError(msg)
352
+
353
+
354
+ @lower_cast(types.float16, types.Integer)
355
+ def float16_to_integer_cast(context, builder, fromty, toty, val):
356
+ bitwidth = toty.bitwidth
357
+ constraint = float16_int_constraint(bitwidth)
358
+ signedness = 's' if toty.signed else 'u'
359
+
360
+ fnty = ir.FunctionType(context.get_value_type(toty), [ir.IntType(16)])
361
+ asm = ir.InlineAsm(fnty,
362
+ f"cvt.rni.{signedness}{bitwidth}.f16 $0, $1;",
363
+ f"={constraint},h")
364
+ return builder.call(asm, [val])
365
+
366
+
367
+ @lower_cast(types.Integer, types.float16)
368
+ @lower_cast(types.IntegerLiteral, types.float16)
369
+ def integer_to_float16_cast(context, builder, fromty, toty, val):
370
+ bitwidth = fromty.bitwidth
371
+ constraint = float16_int_constraint(bitwidth)
372
+ signedness = 's' if fromty.signed else 'u'
373
+
374
+ fnty = ir.FunctionType(ir.IntType(16),
375
+ [context.get_value_type(fromty)])
376
+ asm = ir.InlineAsm(fnty,
377
+ f"cvt.rn.f16.{signedness}{bitwidth} $0, $1;",
378
+ f"=h,{constraint}")
379
+ return builder.call(asm, [val])
380
+
381
+
382
+ def lower_fp16_binary(fn, op):
383
+ @lower(fn, types.float16, types.float16)
384
+ def ptx_fp16_binary(context, builder, sig, args):
385
+ fnty = ir.FunctionType(ir.IntType(16),
386
+ [ir.IntType(16), ir.IntType(16)])
387
+ asm = ir.InlineAsm(fnty, f'{op}.f16 $0,$1,$2;', '=h,h,h')
388
+ return builder.call(asm, args)
389
+
390
+
391
+ lower_fp16_binary(stubs.fp16.hadd, 'add')
392
+ lower_fp16_binary(operator.add, 'add')
393
+ lower_fp16_binary(operator.iadd, 'add')
394
+ lower_fp16_binary(stubs.fp16.hsub, 'sub')
395
+ lower_fp16_binary(operator.sub, 'sub')
396
+ lower_fp16_binary(operator.isub, 'sub')
397
+ lower_fp16_binary(stubs.fp16.hmul, 'mul')
398
+ lower_fp16_binary(operator.mul, 'mul')
399
+ lower_fp16_binary(operator.imul, 'mul')
400
+
401
+
402
+ @lower(stubs.fp16.hneg, types.float16)
403
+ def ptx_fp16_hneg(context, builder, sig, args):
404
+ fnty = ir.FunctionType(ir.IntType(16), [ir.IntType(16)])
405
+ asm = ir.InlineAsm(fnty, 'neg.f16 $0, $1;', '=h,h')
406
+ return builder.call(asm, args)
407
+
408
+
409
+ @lower(operator.neg, types.float16)
410
+ def operator_hneg(context, builder, sig, args):
411
+ return ptx_fp16_hneg(context, builder, sig, args)
412
+
413
+
414
+ @lower(stubs.fp16.habs, types.float16)
415
+ def ptx_fp16_habs(context, builder, sig, args):
416
+ fnty = ir.FunctionType(ir.IntType(16), [ir.IntType(16)])
417
+ asm = ir.InlineAsm(fnty, 'abs.f16 $0, $1;', '=h,h')
418
+ return builder.call(asm, args)
419
+
420
+
421
+ @lower(abs, types.float16)
422
+ def operator_habs(context, builder, sig, args):
423
+ return ptx_fp16_habs(context, builder, sig, args)
424
+
425
+
426
+ @lower(stubs.fp16.hfma, types.float16, types.float16, types.float16)
427
+ def ptx_hfma(context, builder, sig, args):
428
+ argtys = [ir.IntType(16), ir.IntType(16), ir.IntType(16)]
429
+ fnty = ir.FunctionType(ir.IntType(16), argtys)
430
+ asm = ir.InlineAsm(fnty, "fma.rn.f16 $0,$1,$2,$3;", "=h,h,h,h")
431
+ return builder.call(asm, args)
432
+
433
+
434
+ @lower(operator.truediv, types.float16, types.float16)
435
+ @lower(operator.itruediv, types.float16, types.float16)
436
+ def fp16_div_impl(context, builder, sig, args):
437
+ def fp16_div(x, y):
438
+ return cuda.fp16.hdiv(x, y)
439
+
440
+ return context.compile_internal(builder, fp16_div, sig, args)
441
+
442
+
443
+ _fp16_cmp = """{{
444
+ .reg .pred __$$f16_cmp_tmp;
445
+ setp.{op}.f16 __$$f16_cmp_tmp, $1, $2;
446
+ selp.u16 $0, 1, 0, __$$f16_cmp_tmp;
447
+ }}"""
448
+
449
+
450
+ def _gen_fp16_cmp(op):
451
+ def ptx_fp16_comparison(context, builder, sig, args):
452
+ fnty = ir.FunctionType(ir.IntType(16), [ir.IntType(16), ir.IntType(16)])
453
+ asm = ir.InlineAsm(fnty, _fp16_cmp.format(op=op), '=h,h,h')
454
+ result = builder.call(asm, args)
455
+
456
+ zero = context.get_constant(types.int16, 0)
457
+ int_result = builder.bitcast(result, ir.IntType(16))
458
+ return builder.icmp_unsigned("!=", int_result, zero)
459
+ return ptx_fp16_comparison
460
+
461
+
462
+ lower(stubs.fp16.heq, types.float16, types.float16)(_gen_fp16_cmp('eq'))
463
+ lower(operator.eq, types.float16, types.float16)(_gen_fp16_cmp('eq'))
464
+ lower(stubs.fp16.hne, types.float16, types.float16)(_gen_fp16_cmp('ne'))
465
+ lower(operator.ne, types.float16, types.float16)(_gen_fp16_cmp('ne'))
466
+ lower(stubs.fp16.hge, types.float16, types.float16)(_gen_fp16_cmp('ge'))
467
+ lower(operator.ge, types.float16, types.float16)(_gen_fp16_cmp('ge'))
468
+ lower(stubs.fp16.hgt, types.float16, types.float16)(_gen_fp16_cmp('gt'))
469
+ lower(operator.gt, types.float16, types.float16)(_gen_fp16_cmp('gt'))
470
+ lower(stubs.fp16.hle, types.float16, types.float16)(_gen_fp16_cmp('le'))
471
+ lower(operator.le, types.float16, types.float16)(_gen_fp16_cmp('le'))
472
+ lower(stubs.fp16.hlt, types.float16, types.float16)(_gen_fp16_cmp('lt'))
473
+ lower(operator.lt, types.float16, types.float16)(_gen_fp16_cmp('lt'))
474
+
475
+
476
+ def lower_fp16_minmax(fn, fname, op):
477
+ @lower(fn, types.float16, types.float16)
478
+ def ptx_fp16_minmax(context, builder, sig, args):
479
+ choice = _gen_fp16_cmp(op)(context, builder, sig, args)
480
+ return builder.select(choice, args[0], args[1])
481
+
482
+
483
+ lower_fp16_minmax(stubs.fp16.hmax, 'max', 'gt')
484
+ lower_fp16_minmax(stubs.fp16.hmin, 'min', 'lt')
485
+
486
+ # See:
487
+ # https://docs.nvidia.com/cuda/libdevice-users-guide/__nv_cbrt.html#__nv_cbrt
488
+ # https://docs.nvidia.com/cuda/libdevice-users-guide/__nv_cbrtf.html#__nv_cbrtf
489
+
490
+
491
+ cbrt_funcs = {
492
+ types.float32: '__nv_cbrtf',
493
+ types.float64: '__nv_cbrt',
494
+ }
495
+
496
+
497
+ @lower(stubs.cbrt, types.float32)
498
+ @lower(stubs.cbrt, types.float64)
499
+ def ptx_cbrt(context, builder, sig, args):
500
+ ty = sig.return_type
501
+ fname = cbrt_funcs[ty]
502
+ fty = context.get_value_type(ty)
503
+ lmod = builder.module
504
+ fnty = ir.FunctionType(fty, [fty])
505
+ fn = cgutils.get_or_insert_function(lmod, fnty, fname)
506
+ return builder.call(fn, args)
507
+
508
+
509
+ @lower(stubs.brev, types.u4)
510
+ def ptx_brev_u4(context, builder, sig, args):
511
+ # FIXME the llvm.bitreverse.i32 intrinsic isn't supported by nvcc
512
+ # return builder.bitreverse(args[0])
513
+
514
+ fn = cgutils.get_or_insert_function(
515
+ builder.module,
516
+ ir.FunctionType(ir.IntType(32), (ir.IntType(32),)),
517
+ '__nv_brev')
518
+ return builder.call(fn, args)
519
+
520
+
521
+ @lower(stubs.brev, types.u8)
522
+ def ptx_brev_u8(context, builder, sig, args):
523
+ # FIXME the llvm.bitreverse.i64 intrinsic isn't supported by nvcc
524
+ # return builder.bitreverse(args[0])
525
+
526
+ fn = cgutils.get_or_insert_function(
527
+ builder.module,
528
+ ir.FunctionType(ir.IntType(64), (ir.IntType(64),)),
529
+ '__nv_brevll')
530
+ return builder.call(fn, args)
531
+
532
+
533
+ @lower(stubs.clz, types.Any)
534
+ def ptx_clz(context, builder, sig, args):
535
+ return builder.ctlz(
536
+ args[0],
537
+ context.get_constant(types.boolean, 0))
538
+
539
+
540
+ @lower(stubs.ffs, types.i4)
541
+ @lower(stubs.ffs, types.u4)
542
+ def ptx_ffs_32(context, builder, sig, args):
543
+ fn = cgutils.get_or_insert_function(
544
+ builder.module,
545
+ ir.FunctionType(ir.IntType(32), (ir.IntType(32),)),
546
+ '__nv_ffs')
547
+ return builder.call(fn, args)
548
+
549
+
550
+ @lower(stubs.ffs, types.i8)
551
+ @lower(stubs.ffs, types.u8)
552
+ def ptx_ffs_64(context, builder, sig, args):
553
+ fn = cgutils.get_or_insert_function(
554
+ builder.module,
555
+ ir.FunctionType(ir.IntType(32), (ir.IntType(64),)),
556
+ '__nv_ffsll')
557
+ return builder.call(fn, args)
558
+
559
+
560
+ @lower(stubs.selp, types.Any, types.Any, types.Any)
561
+ def ptx_selp(context, builder, sig, args):
562
+ test, a, b = args
563
+ return builder.select(test, a, b)
564
+
565
+
566
+ @lower(max, types.f4, types.f4)
567
+ def ptx_max_f4(context, builder, sig, args):
568
+ fn = cgutils.get_or_insert_function(
569
+ builder.module,
570
+ ir.FunctionType(
571
+ ir.FloatType(),
572
+ (ir.FloatType(), ir.FloatType())),
573
+ '__nv_fmaxf')
574
+ return builder.call(fn, args)
575
+
576
+
577
+ @lower(max, types.f8, types.f4)
578
+ @lower(max, types.f4, types.f8)
579
+ @lower(max, types.f8, types.f8)
580
+ def ptx_max_f8(context, builder, sig, args):
581
+ fn = cgutils.get_or_insert_function(
582
+ builder.module,
583
+ ir.FunctionType(
584
+ ir.DoubleType(),
585
+ (ir.DoubleType(), ir.DoubleType())),
586
+ '__nv_fmax')
587
+
588
+ return builder.call(fn, [
589
+ context.cast(builder, args[0], sig.args[0], types.double),
590
+ context.cast(builder, args[1], sig.args[1], types.double),
591
+ ])
592
+
593
+
594
+ @lower(min, types.f4, types.f4)
595
+ def ptx_min_f4(context, builder, sig, args):
596
+ fn = cgutils.get_or_insert_function(
597
+ builder.module,
598
+ ir.FunctionType(
599
+ ir.FloatType(),
600
+ (ir.FloatType(), ir.FloatType())),
601
+ '__nv_fminf')
602
+ return builder.call(fn, args)
603
+
604
+
605
+ @lower(min, types.f8, types.f4)
606
+ @lower(min, types.f4, types.f8)
607
+ @lower(min, types.f8, types.f8)
608
+ def ptx_min_f8(context, builder, sig, args):
609
+ fn = cgutils.get_or_insert_function(
610
+ builder.module,
611
+ ir.FunctionType(
612
+ ir.DoubleType(),
613
+ (ir.DoubleType(), ir.DoubleType())),
614
+ '__nv_fmin')
615
+
616
+ return builder.call(fn, [
617
+ context.cast(builder, args[0], sig.args[0], types.double),
618
+ context.cast(builder, args[1], sig.args[1], types.double),
619
+ ])
620
+
621
+
622
+ @lower(round, types.f4)
623
+ @lower(round, types.f8)
624
+ def ptx_round(context, builder, sig, args):
625
+ fn = cgutils.get_or_insert_function(
626
+ builder.module,
627
+ ir.FunctionType(
628
+ ir.IntType(64),
629
+ (ir.DoubleType(),)),
630
+ '__nv_llrint')
631
+ return builder.call(fn, [
632
+ context.cast(builder, args[0], sig.args[0], types.double),
633
+ ])
634
+
635
+
636
+ # This rounding implementation follows the algorithm used in the "fallback
637
+ # version" of double_round in CPython.
638
+ # https://github.com/python/cpython/blob/a755410e054e1e2390de5830befc08fe80706c66/Objects/floatobject.c#L964-L1007
639
+
640
+ @lower(round, types.f4, types.Integer)
641
+ @lower(round, types.f8, types.Integer)
642
+ def round_to_impl(context, builder, sig, args):
643
+ def round_ndigits(x, ndigits):
644
+ if math.isinf(x) or math.isnan(x):
645
+ return x
646
+
647
+ if ndigits >= 0:
648
+ if ndigits > 22:
649
+ # pow1 and pow2 are each safe from overflow, but
650
+ # pow1*pow2 ~= pow(10.0, ndigits) might overflow.
651
+ pow1 = 10.0 ** (ndigits - 22)
652
+ pow2 = 1e22
653
+ else:
654
+ pow1 = 10.0 ** ndigits
655
+ pow2 = 1.0
656
+ y = (x * pow1) * pow2
657
+ if math.isinf(y):
658
+ return x
659
+
660
+ else:
661
+ pow1 = 10.0 ** (-ndigits)
662
+ y = x / pow1
663
+
664
+ z = round(y)
665
+ if (math.fabs(y - z) == 0.5):
666
+ # halfway between two integers; use round-half-even
667
+ z = 2.0 * round(y / 2.0)
668
+
669
+ if ndigits >= 0:
670
+ z = (z / pow2) / pow1
671
+ else:
672
+ z *= pow1
673
+
674
+ return z
675
+
676
+ return context.compile_internal(builder, round_ndigits, sig, args, )
677
+
678
+
679
+ def gen_deg_rad(const):
680
+ def impl(context, builder, sig, args):
681
+ argty, = sig.args
682
+ factor = context.get_constant(argty, const)
683
+ return builder.fmul(factor, args[0])
684
+ return impl
685
+
686
+
687
+ _deg2rad = math.pi / 180.
688
+ _rad2deg = 180. / math.pi
689
+ lower(math.radians, types.f4)(gen_deg_rad(_deg2rad))
690
+ lower(math.radians, types.f8)(gen_deg_rad(_deg2rad))
691
+ lower(math.degrees, types.f4)(gen_deg_rad(_rad2deg))
692
+ lower(math.degrees, types.f8)(gen_deg_rad(_rad2deg))
693
+
694
+
695
+ def _normalize_indices(context, builder, indty, inds, aryty, valty):
696
+ """
697
+ Convert integer indices into tuple of intp
698
+ """
699
+ if indty in types.integer_domain:
700
+ indty = types.UniTuple(dtype=indty, count=1)
701
+ indices = [inds]
702
+ else:
703
+ indices = cgutils.unpack_tuple(builder, inds, count=len(indty))
704
+ indices = [context.cast(builder, i, t, types.intp)
705
+ for t, i in zip(indty, indices)]
706
+
707
+ dtype = aryty.dtype
708
+ if dtype != valty:
709
+ raise TypeError("expect %s but got %s" % (dtype, valty))
710
+
711
+ if aryty.ndim != len(indty):
712
+ raise TypeError("indexing %d-D array with %d-D index" %
713
+ (aryty.ndim, len(indty)))
714
+
715
+ return indty, indices
716
+
717
+
718
+ def _atomic_dispatcher(dispatch_fn):
719
+ def imp(context, builder, sig, args):
720
+ # The common argument handling code
721
+ aryty, indty, valty = sig.args
722
+ ary, inds, val = args
723
+ dtype = aryty.dtype
724
+
725
+ indty, indices = _normalize_indices(context, builder, indty, inds,
726
+ aryty, valty)
727
+
728
+ lary = context.make_array(aryty)(context, builder, ary)
729
+ ptr = cgutils.get_item_pointer(context, builder, aryty, lary, indices,
730
+ wraparound=True)
731
+ # dispatcher to implementation base on dtype
732
+ return dispatch_fn(context, builder, dtype, ptr, val)
733
+ return imp
734
+
735
+
736
+ @lower(stubs.atomic.add, types.Array, types.intp, types.Any)
737
+ @lower(stubs.atomic.add, types.Array, types.UniTuple, types.Any)
738
+ @lower(stubs.atomic.add, types.Array, types.Tuple, types.Any)
739
+ @_atomic_dispatcher
740
+ def ptx_atomic_add_tuple(context, builder, dtype, ptr, val):
741
+ if dtype == types.float32:
742
+ lmod = builder.module
743
+ return builder.call(nvvmutils.declare_atomic_add_float32(lmod),
744
+ (ptr, val))
745
+ elif dtype == types.float64:
746
+ lmod = builder.module
747
+ return builder.call(nvvmutils.declare_atomic_add_float64(lmod),
748
+ (ptr, val))
749
+ else:
750
+ return builder.atomic_rmw('add', ptr, val, 'monotonic')
751
+
752
+
753
+ @lower(stubs.atomic.sub, types.Array, types.intp, types.Any)
754
+ @lower(stubs.atomic.sub, types.Array, types.UniTuple, types.Any)
755
+ @lower(stubs.atomic.sub, types.Array, types.Tuple, types.Any)
756
+ @_atomic_dispatcher
757
+ def ptx_atomic_sub(context, builder, dtype, ptr, val):
758
+ if dtype == types.float32:
759
+ lmod = builder.module
760
+ return builder.call(nvvmutils.declare_atomic_sub_float32(lmod),
761
+ (ptr, val))
762
+ elif dtype == types.float64:
763
+ lmod = builder.module
764
+ return builder.call(nvvmutils.declare_atomic_sub_float64(lmod),
765
+ (ptr, val))
766
+ else:
767
+ return builder.atomic_rmw('sub', ptr, val, 'monotonic')
768
+
769
+
770
+ @lower(stubs.atomic.inc, types.Array, types.intp, types.Any)
771
+ @lower(stubs.atomic.inc, types.Array, types.UniTuple, types.Any)
772
+ @lower(stubs.atomic.inc, types.Array, types.Tuple, types.Any)
773
+ @_atomic_dispatcher
774
+ def ptx_atomic_inc(context, builder, dtype, ptr, val):
775
+ if dtype in cuda.cudadecl.unsigned_int_numba_types:
776
+ bw = dtype.bitwidth
777
+ lmod = builder.module
778
+ fn = getattr(nvvmutils, f'declare_atomic_inc_int{bw}')
779
+ return builder.call(fn(lmod), (ptr, val))
780
+ else:
781
+ raise TypeError(f'Unimplemented atomic inc with {dtype} array')
782
+
783
+
784
+ @lower(stubs.atomic.dec, types.Array, types.intp, types.Any)
785
+ @lower(stubs.atomic.dec, types.Array, types.UniTuple, types.Any)
786
+ @lower(stubs.atomic.dec, types.Array, types.Tuple, types.Any)
787
+ @_atomic_dispatcher
788
+ def ptx_atomic_dec(context, builder, dtype, ptr, val):
789
+ if dtype in cuda.cudadecl.unsigned_int_numba_types:
790
+ bw = dtype.bitwidth
791
+ lmod = builder.module
792
+ fn = getattr(nvvmutils, f'declare_atomic_dec_int{bw}')
793
+ return builder.call(fn(lmod), (ptr, val))
794
+ else:
795
+ raise TypeError(f'Unimplemented atomic dec with {dtype} array')
796
+
797
+
798
+ def ptx_atomic_bitwise(stub, op):
799
+ @_atomic_dispatcher
800
+ def impl_ptx_atomic(context, builder, dtype, ptr, val):
801
+ if dtype in (cuda.cudadecl.integer_numba_types):
802
+ return builder.atomic_rmw(op, ptr, val, 'monotonic')
803
+ else:
804
+ raise TypeError(f'Unimplemented atomic {op} with {dtype} array')
805
+
806
+ for ty in (types.intp, types.UniTuple, types.Tuple):
807
+ lower(stub, types.Array, ty, types.Any)(impl_ptx_atomic)
808
+
809
+
810
+ ptx_atomic_bitwise(stubs.atomic.and_, 'and')
811
+ ptx_atomic_bitwise(stubs.atomic.or_, 'or')
812
+ ptx_atomic_bitwise(stubs.atomic.xor, 'xor')
813
+
814
+
815
+ @lower(stubs.atomic.exch, types.Array, types.intp, types.Any)
816
+ @lower(stubs.atomic.exch, types.Array, types.UniTuple, types.Any)
817
+ @lower(stubs.atomic.exch, types.Array, types.Tuple, types.Any)
818
+ @_atomic_dispatcher
819
+ def ptx_atomic_exch(context, builder, dtype, ptr, val):
820
+ if dtype in (cuda.cudadecl.integer_numba_types):
821
+ return builder.atomic_rmw('xchg', ptr, val, 'monotonic')
822
+ else:
823
+ raise TypeError(f'Unimplemented atomic exch with {dtype} array')
824
+
825
+
826
+ @lower(stubs.atomic.max, types.Array, types.intp, types.Any)
827
+ @lower(stubs.atomic.max, types.Array, types.Tuple, types.Any)
828
+ @lower(stubs.atomic.max, types.Array, types.UniTuple, types.Any)
829
+ @_atomic_dispatcher
830
+ def ptx_atomic_max(context, builder, dtype, ptr, val):
831
+ lmod = builder.module
832
+ if dtype == types.float64:
833
+ return builder.call(nvvmutils.declare_atomic_max_float64(lmod),
834
+ (ptr, val))
835
+ elif dtype == types.float32:
836
+ return builder.call(nvvmutils.declare_atomic_max_float32(lmod),
837
+ (ptr, val))
838
+ elif dtype in (types.int32, types.int64):
839
+ return builder.atomic_rmw('max', ptr, val, ordering='monotonic')
840
+ elif dtype in (types.uint32, types.uint64):
841
+ return builder.atomic_rmw('umax', ptr, val, ordering='monotonic')
842
+ else:
843
+ raise TypeError('Unimplemented atomic max with %s array' % dtype)
844
+
845
+
846
+ @lower(stubs.atomic.min, types.Array, types.intp, types.Any)
847
+ @lower(stubs.atomic.min, types.Array, types.Tuple, types.Any)
848
+ @lower(stubs.atomic.min, types.Array, types.UniTuple, types.Any)
849
+ @_atomic_dispatcher
850
+ def ptx_atomic_min(context, builder, dtype, ptr, val):
851
+ lmod = builder.module
852
+ if dtype == types.float64:
853
+ return builder.call(nvvmutils.declare_atomic_min_float64(lmod),
854
+ (ptr, val))
855
+ elif dtype == types.float32:
856
+ return builder.call(nvvmutils.declare_atomic_min_float32(lmod),
857
+ (ptr, val))
858
+ elif dtype in (types.int32, types.int64):
859
+ return builder.atomic_rmw('min', ptr, val, ordering='monotonic')
860
+ elif dtype in (types.uint32, types.uint64):
861
+ return builder.atomic_rmw('umin', ptr, val, ordering='monotonic')
862
+ else:
863
+ raise TypeError('Unimplemented atomic min with %s array' % dtype)
864
+
865
+
866
+ @lower(stubs.atomic.nanmax, types.Array, types.intp, types.Any)
867
+ @lower(stubs.atomic.nanmax, types.Array, types.Tuple, types.Any)
868
+ @lower(stubs.atomic.nanmax, types.Array, types.UniTuple, types.Any)
869
+ @_atomic_dispatcher
870
+ def ptx_atomic_nanmax(context, builder, dtype, ptr, val):
871
+ lmod = builder.module
872
+ if dtype == types.float64:
873
+ return builder.call(nvvmutils.declare_atomic_nanmax_float64(lmod),
874
+ (ptr, val))
875
+ elif dtype == types.float32:
876
+ return builder.call(nvvmutils.declare_atomic_nanmax_float32(lmod),
877
+ (ptr, val))
878
+ elif dtype in (types.int32, types.int64):
879
+ return builder.atomic_rmw('max', ptr, val, ordering='monotonic')
880
+ elif dtype in (types.uint32, types.uint64):
881
+ return builder.atomic_rmw('umax', ptr, val, ordering='monotonic')
882
+ else:
883
+ raise TypeError('Unimplemented atomic max with %s array' % dtype)
884
+
885
+
886
+ @lower(stubs.atomic.nanmin, types.Array, types.intp, types.Any)
887
+ @lower(stubs.atomic.nanmin, types.Array, types.Tuple, types.Any)
888
+ @lower(stubs.atomic.nanmin, types.Array, types.UniTuple, types.Any)
889
+ @_atomic_dispatcher
890
+ def ptx_atomic_nanmin(context, builder, dtype, ptr, val):
891
+ lmod = builder.module
892
+ if dtype == types.float64:
893
+ return builder.call(nvvmutils.declare_atomic_nanmin_float64(lmod),
894
+ (ptr, val))
895
+ elif dtype == types.float32:
896
+ return builder.call(nvvmutils.declare_atomic_nanmin_float32(lmod),
897
+ (ptr, val))
898
+ elif dtype in (types.int32, types.int64):
899
+ return builder.atomic_rmw('min', ptr, val, ordering='monotonic')
900
+ elif dtype in (types.uint32, types.uint64):
901
+ return builder.atomic_rmw('umin', ptr, val, ordering='monotonic')
902
+ else:
903
+ raise TypeError('Unimplemented atomic min with %s array' % dtype)
904
+
905
+
906
+ @lower(stubs.atomic.compare_and_swap, types.Array, types.Any, types.Any)
907
+ def ptx_atomic_compare_and_swap(context, builder, sig, args):
908
+ sig = sig.return_type(sig.args[0], types.intp, sig.args[1], sig.args[2])
909
+ args = (args[0], context.get_constant(types.intp, 0), args[1], args[2])
910
+ return ptx_atomic_cas(context, builder, sig, args)
911
+
912
+
913
+ @lower(stubs.atomic.cas, types.Array, types.intp, types.Any, types.Any)
914
+ @lower(stubs.atomic.cas, types.Array, types.Tuple, types.Any, types.Any)
915
+ @lower(stubs.atomic.cas, types.Array, types.UniTuple, types.Any, types.Any)
916
+ def ptx_atomic_cas(context, builder, sig, args):
917
+ aryty, indty, oldty, valty = sig.args
918
+ ary, inds, old, val = args
919
+
920
+ indty, indices = _normalize_indices(context, builder, indty, inds, aryty,
921
+ valty)
922
+
923
+ lary = context.make_array(aryty)(context, builder, ary)
924
+ ptr = cgutils.get_item_pointer(context, builder, aryty, lary, indices,
925
+ wraparound=True)
926
+
927
+ if aryty.dtype in (cuda.cudadecl.integer_numba_types):
928
+ lmod = builder.module
929
+ bitwidth = aryty.dtype.bitwidth
930
+ return nvvmutils.atomic_cmpxchg(builder, lmod, bitwidth, ptr, old, val)
931
+ else:
932
+ raise TypeError('Unimplemented atomic cas with %s array' % aryty.dtype)
933
+
934
+
935
+ # -----------------------------------------------------------------------------
936
+
937
+ @lower(stubs.nanosleep, types.uint32)
938
+ def ptx_nanosleep(context, builder, sig, args):
939
+ nanosleep = ir.InlineAsm(ir.FunctionType(ir.VoidType(), [ir.IntType(32)]),
940
+ "nanosleep.u32 $0;", 'r', side_effect=True)
941
+ ns = args[0]
942
+ builder.call(nanosleep, [ns])
943
+
944
+
945
+ # -----------------------------------------------------------------------------
946
+
947
+
948
+ def _generic_array(context, builder, shape, dtype, symbol_name, addrspace,
949
+ can_dynsized=False):
950
+ elemcount = reduce(operator.mul, shape, 1)
951
+
952
+ # Check for valid shape for this type of allocation.
953
+ # Only 1d arrays can be dynamic.
954
+ dynamic_smem = elemcount <= 0 and can_dynsized and len(shape) == 1
955
+ if elemcount <= 0 and not dynamic_smem:
956
+ raise ValueError("array length <= 0")
957
+
958
+ # Check that we support the requested dtype
959
+ data_model = context.data_model_manager[dtype]
960
+ other_supported_type = (
961
+ isinstance(dtype, (types.Record, types.Boolean))
962
+ or isinstance(data_model, models.StructModel)
963
+ or dtype == types.float16
964
+ )
965
+ if dtype not in types.number_domain and not other_supported_type:
966
+ raise TypeError("unsupported type: %s" % dtype)
967
+
968
+ lldtype = context.get_data_type(dtype)
969
+ laryty = ir.ArrayType(lldtype, elemcount)
970
+
971
+ if addrspace == nvvm.ADDRSPACE_LOCAL:
972
+ # Special case local address space allocation to use alloca
973
+ # NVVM is smart enough to only use local memory if no register is
974
+ # available
975
+ dataptr = cgutils.alloca_once(builder, laryty, name=symbol_name)
976
+ else:
977
+ lmod = builder.module
978
+
979
+ # Create global variable in the requested address space
980
+ gvmem = cgutils.add_global_variable(lmod, laryty, symbol_name,
981
+ addrspace)
982
+ # Specify alignment to avoid misalignment bug
983
+ align = context.get_abi_sizeof(lldtype)
984
+ # Alignment is required to be a power of 2 for shared memory. If it is
985
+ # not a power of 2 (e.g. for a Record array) then round up accordingly.
986
+ gvmem.align = 1 << (align - 1 ).bit_length()
987
+
988
+ if dynamic_smem:
989
+ gvmem.linkage = 'external'
990
+ else:
991
+ ## Comment out the following line to workaround a NVVM bug
992
+ ## which generates a invalid symbol name when the linkage
993
+ ## is internal and in some situation.
994
+ ## See _get_unique_smem_id()
995
+ # gvmem.linkage = lc.LINKAGE_INTERNAL
996
+
997
+ gvmem.initializer = ir.Constant(laryty, ir.Undefined)
998
+
999
+ # Convert to generic address-space
1000
+ dataptr = builder.addrspacecast(gvmem, ir.PointerType(ir.IntType(8)),
1001
+ 'generic')
1002
+
1003
+ targetdata = ll.create_target_data(nvvm.NVVM().data_layout)
1004
+ lldtype = context.get_data_type(dtype)
1005
+ itemsize = lldtype.get_abi_size(targetdata)
1006
+
1007
+ # Compute strides
1008
+ laststride = itemsize
1009
+ rstrides = []
1010
+ for i, lastsize in enumerate(reversed(shape)):
1011
+ rstrides.append(laststride)
1012
+ laststride *= lastsize
1013
+ strides = [s for s in reversed(rstrides)]
1014
+ kstrides = [context.get_constant(types.intp, s) for s in strides]
1015
+
1016
+ # Compute shape
1017
+ if dynamic_smem:
1018
+ # Compute the shape based on the dynamic shared memory configuration.
1019
+ # Unfortunately NVVM does not provide an intrinsic for the
1020
+ # %dynamic_smem_size register, so we must read it using inline
1021
+ # assembly.
1022
+ get_dynshared_size = ir.InlineAsm(ir.FunctionType(ir.IntType(32), []),
1023
+ "mov.u32 $0, %dynamic_smem_size;",
1024
+ '=r', side_effect=True)
1025
+ dynsmem_size = builder.zext(builder.call(get_dynshared_size, []),
1026
+ ir.IntType(64))
1027
+ # Only 1-D dynamic shared memory is supported so the following is a
1028
+ # sufficient construction of the shape
1029
+ kitemsize = context.get_constant(types.intp, itemsize)
1030
+ kshape = [builder.udiv(dynsmem_size, kitemsize)]
1031
+ else:
1032
+ kshape = [context.get_constant(types.intp, s) for s in shape]
1033
+
1034
+ # Create array object
1035
+ ndim = len(shape)
1036
+ aryty = types.Array(dtype=dtype, ndim=ndim, layout='C')
1037
+ ary = context.make_array(aryty)(context, builder)
1038
+
1039
+ context.populate_array(ary,
1040
+ data=builder.bitcast(dataptr, ary.data.type),
1041
+ shape=kshape,
1042
+ strides=kstrides,
1043
+ itemsize=context.get_constant(types.intp, itemsize),
1044
+ meminfo=None)
1045
+ return ary._getvalue()
1046
+
1047
+
1048
+ @lower_constant(CUDADispatcher)
1049
+ def cuda_dispatcher_const(context, builder, ty, pyval):
1050
+ return context.get_dummy_value()
1051
+
1052
+
1053
+ # NumPy
1054
+
1055
+ register_ufuncs(ufunc_db.get_ufuncs(), lower)